diff --git a/docs/404.html b/docs/404.html
new file mode 100644
index 00000000..8345141d
--- /dev/null
+++ b/docs/404.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/about-en-US.md b/docs/about-en-US.md
new file mode 100644
index 00000000..e373922a
--- /dev/null
+++ b/docs/about-en-US.md
@@ -0,0 +1,16 @@
+## About md-editor-rt
+
+![](https://img.shields.io/github/stars/imzbf/md-editor-rt?style=social) ![](https://img.shields.io/npm/dm/md-editor-rt) ![](https://img.shields.io/bundlephobia/min/md-editor-rt) ![](https://img.shields.io/github/license/imzbf/md-editor-rt) ![](https://img.shields.io/github/package-json/v/imzbf/md-editor-rt) ![](https://img.shields.io/badge/ssr-%3E1.6.0-brightgreen)
+
+Markdown editor for react, developed in jsx and typescript, dark theme, beautify content by prettier, render articles directly, paste or clip the picture and upload it...
+
+## Same Series
+
+- For vue3, [md-editor-v3](https://github.com/imzbf/md-editor-v3)
+
+## Connect
+
+1. Email:zbfcqtl@gmail.com
+2. Github issue:[github issues](https://github.com/imzbf/md-editor-rt/issues)
+
+I'm not proficient in English, please help me correct wrong grammars.
diff --git a/docs/about-zh-CN.md b/docs/about-zh-CN.md
new file mode 100644
index 00000000..e283401e
--- /dev/null
+++ b/docs/about-zh-CN.md
@@ -0,0 +1,14 @@
+## 关于 md-editor-rt
+
+![](https://img.shields.io/github/stars/imzbf/md-editor-rt?style=social) ![](https://img.shields.io/npm/dm/md-editor-rt) ![](https://img.shields.io/bundlephobia/min/md-editor-rt) ![](https://img.shields.io/github/license/imzbf/md-editor-rt) ![](https://img.shields.io/github/package-json/v/imzbf/md-editor-rt) ![](https://img.shields.io/badge/ssr-%3E1.6.0-brightgreen)
+
+Markdown 编辑器,react 版本,使用 jsx 和 typescript 语法开发,支持切换主题,支持 prettier 美化文本,支持图片粘贴上传,裁剪上传,支持在 tsx 项目使用。
+
+## 同系列
+
+- vue3 版本,[md-editor-v3](https://github.com/imzbf/md-editor-v3)
+
+## 反馈联系
+
+1. 邮箱:zbfcqtl@gmail.com
+2. issue 管理:[github issues](https://github.com/imzbf/md-editor-rt/issues)
diff --git a/docs/assets/apl-f73da2d7.js b/docs/assets/apl-f73da2d7.js
new file mode 100644
index 00000000..548bbc39
--- /dev/null
+++ b/docs/assets/apl-f73da2d7.js
@@ -0,0 +1 @@
+var l={"+":["conjugate","add"],"−":["negate","subtract"],"×":["signOf","multiply"],"÷":["reciprocal","divide"],"⌈":["ceiling","greaterOf"],"⌊":["floor","lesserOf"],"∣":["absolute","residue"],"⍳":["indexGenerate","indexOf"],"?":["roll","deal"],"⋆":["exponentiate","toThePowerOf"],"⍟":["naturalLog","logToTheBase"],"○":["piTimes","circularFuncs"],"!":["factorial","binomial"],"⌹":["matrixInverse","matrixDivide"],"<":[null,"lessThan"],"≤":[null,"lessThanOrEqual"],"=":[null,"equals"],">":[null,"greaterThan"],"≥":[null,"greaterThanOrEqual"],"≠":[null,"notEqual"],"≡":["depth","match"],"≢":[null,"notMatch"],"∈":["enlist","membership"],"⍷":[null,"find"],"∪":["unique","union"],"∩":[null,"intersection"],"∼":["not","without"],"∨":[null,"or"],"∧":[null,"and"],"⍱":[null,"nor"],"⍲":[null,"nand"],"⍴":["shapeOf","reshape"],",":["ravel","catenate"],"⍪":[null,"firstAxisCatenate"],"⌽":["reverse","rotate"],"⊖":["axis1Reverse","axis1Rotate"],"⍉":["transpose",null],"↑":["first","take"],"↓":[null,"drop"],"⊂":["enclose","partitionWithAxis"],"⊃":["diclose","pick"],"⌷":[null,"index"],"⍋":["gradeUp",null],"⍒":["gradeDown",null],"⊤":["encode",null],"⊥":["decode",null],"⍕":["format","formatByExample"],"⍎":["execute",null],"⊣":["stop","left"],"⊢":["pass","right"]},t=/[\.\/⌿⍀¨⍣]/,a=/⍬/,i=/[\+−×÷⌈⌊∣⍳\?⋆⍟○!⌹<≤=>≥≠≡≢∈⍷∪∩∼∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢]/,u=/←/,o=/[⍝#].*$/,s=function(r){var n;return n=!1,function(e){return n=e,e===r?n==="\\":!0}};const f={name:"apl",startState:function(){return{prev:!1,func:!1,op:!1,string:!1,escape:!1}},token:function(r,n){var e;return r.eatSpace()?null:(e=r.next(),e==='"'||e==="'"?(r.eatWhile(s(e)),r.next(),n.prev=!0,"string"):/[\[{\(]/.test(e)?(n.prev=!1,null):/[\]}\)]/.test(e)?(n.prev=!0,null):a.test(e)?(n.prev=!1,"atom"):/[¯\d]/.test(e)?(n.func?(n.func=!1,n.prev=!1):n.prev=!0,r.eatWhile(/[\w\.]/),"number"):t.test(e)||u.test(e)?"operator":i.test(e)?(n.func=!0,n.prev=!1,l[e]?"variableName.function.standard":"variableName.function"):o.test(e)?(r.skipToEnd(),"comment"):e==="∘"&&r.peek()==="."?(r.next(),"variableName.function"):(r.eatWhile(/[\w\$_]/),n.prev=!0,"keyword"))}};export{f as apl};
diff --git a/docs/assets/asciiarmor-e7973ceb.js b/docs/assets/asciiarmor-e7973ceb.js
new file mode 100644
index 00000000..2df03963
--- /dev/null
+++ b/docs/assets/asciiarmor-e7973ceb.js
@@ -0,0 +1 @@
+function t(e){var r=e.match(/^\s*\S/);return e.skipToEnd(),r?"error":null}const i={name:"asciiarmor",token:function(e,r){var n;if(r.state=="top")return e.sol()&&(n=e.match(/^-----BEGIN (.*)?-----\s*$/))?(r.state="headers",r.type=n[1],"tag"):t(e);if(r.state=="headers"){if(e.sol()&&e.match(/^\w+:/))return r.state="header","atom";var o=t(e);return o&&(r.state="body"),o}else{if(r.state=="header")return e.skipToEnd(),r.state="headers","string";if(r.state=="body")return e.sol()&&(n=e.match(/^-----END (.*)?-----\s*$/))?n[1]!=r.type?"error":(r.state="end","tag"):e.eatWhile(/[A-Za-z0-9+\/=]/)?null:(e.next(),"error");if(r.state=="end")return t(e)}},blankLine:function(e){e.state=="headers"&&(e.state="body")},startState:function(){return{state:"top",type:null}}};export{i as asciiArmor};
diff --git a/docs/assets/asn1-f9c290f0.js b/docs/assets/asn1-f9c290f0.js
new file mode 100644
index 00000000..ccddaa8f
--- /dev/null
+++ b/docs/assets/asn1-f9c290f0.js
@@ -0,0 +1 @@
+function u(i){for(var s={},c=i.split(" "),T=0;T?$/.test(i)?(n.extenExten=!0,n.extenStart=!1,"strong"):(n.extenStart=!1,e.skipToEnd(),"error");if(n.extenExten)return n.extenExten=!1,n.extenPriority=!0,e.eatWhile(/[^,]/),n.extenInclude&&(e.skipToEnd(),n.extenPriority=!1,n.extenInclude=!1),n.extenSame&&(n.extenPriority=!1,n.extenSame=!1,n.extenApplication=!0),"tag";if(n.extenPriority)return n.extenPriority=!1,n.extenApplication=!0,e.next(),n.extenSame?null:(e.eatWhile(/[^,]/),"number");if(n.extenApplication){if(e.eatWhile(/,/),i=e.current(),i===",")return null;if(e.eatWhile(/\w/),i=e.current().toLowerCase(),n.extenApplication=!1,c.indexOf(i)!==-1)return"def"}else return l(e,n);return null},languageData:{commentTokens:{line:";",block:{open:";--",close:"--;"}}}};export{s as asterisk};
diff --git a/docs/assets/brainfuck-637b9bf0.js b/docs/assets/brainfuck-637b9bf0.js
new file mode 100644
index 00000000..4d0e4bc8
--- /dev/null
+++ b/docs/assets/brainfuck-637b9bf0.js
@@ -0,0 +1 @@
+var f="><+-.,[]".split("");const r={name:"brainfuck",startState:function(){return{commentLine:!1,left:0,right:0,commentLoop:!1}},token:function(i,n){if(i.eatSpace())return null;i.sol()&&(n.commentLine=!1);var e=i.next().toString();if(f.indexOf(e)!==-1){if(n.commentLine===!0)return i.eol()&&(n.commentLine=!1),"comment";if(e==="]"||e==="[")return e==="["?n.left++:n.right++,"bracket";if(e==="+"||e==="-")return"keyword";if(e==="<"||e===">")return"atom";if(e==="."||e===",")return"def"}else return n.commentLine=!0,i.eol()&&(n.commentLine=!1),"comment";i.eol()&&(n.commentLine=!1)}};export{r as brainfuck};
diff --git a/docs/assets/clike-3f6f5c72.js b/docs/assets/clike-3f6f5c72.js
new file mode 100644
index 00000000..5e6f781c
--- /dev/null
+++ b/docs/assets/clike-3f6f5c72.js
@@ -0,0 +1 @@
+function R(e,t,n,l,s,d){this.indented=e,this.column=t,this.type=n,this.info=l,this.align=s,this.prev=d}function D(e,t,n,l){var s=e.indented;return e.context&&e.context.type=="statement"&&n!="statement"&&(s=e.context.indented),e.context=new R(s,t,n,l,null,e.context)}function x(e){var t=e.context.type;return(t==")"||t=="]"||t=="}")&&(e.indented=e.context.indented),e.context=e.context.prev}function q(e,t,n){if(t.prevToken=="variable"||t.prevToken=="type"||/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(e.string.slice(0,n))||t.typeAtEndOfLine&&e.column()==e.indentation())return!0}function V(e){for(;;){if(!e||e.type=="top")return!0;if(e.type=="}"&&e.prev.info!="namespace")return!1;e=e.prev}}function h(e){var t=e.statementIndentUnit,n=e.dontAlignCalls,l=e.keywords||{},s=e.types||{},d=e.builtin||{},b=e.blockKeywords||{},_=e.defKeywords||{},w=e.atoms||{},y=e.hooks||{},ne=e.multiLineStrings,re=e.indentStatements!==!1,ie=e.indentSwitch!==!1,O=e.namespaceSeparator,oe=e.isPunctuationChar||/[\[\]{}\(\),;\:\.]/,ae=e.numberStart||/[\d\.]/,le=e.number||/^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,F=e.isOperatorChar||/[+\-*&%=<>!?|\/]/,j=e.isIdentifierChar||/[\w\$_\xa1-\uffff]/,B=e.isReservedIdentifier||!1,p,E;function U(i,a){var c=i.next();if(y[c]){var o=y[c](i,a);if(o!==!1)return o}if(c=='"'||c=="'")return a.tokenize=ce(c),a.tokenize(i,a);if(ae.test(c)){if(i.backUp(1),i.match(le))return"number";i.next()}if(oe.test(c))return p=c,null;if(c=="/"){if(i.eat("*"))return a.tokenize=K,K(i,a);if(i.eat("/"))return i.skipToEnd(),"comment"}if(F.test(c)){for(;!i.match(/^\/[\/*]/,!1)&&i.eat(F););return"operator"}if(i.eatWhile(j),O)for(;i.match(O);)i.eatWhile(j);var u=i.current();return k(l,u)?(k(b,u)&&(p="newstatement"),k(_,u)&&(E=!0),"keyword"):k(s,u)?"type":k(d,u)||B&&B(u)?(k(b,u)&&(p="newstatement"),"builtin"):k(w,u)?"atom":"variable"}function ce(i){return function(a,c){for(var o=!1,u,v=!1;(u=a.next())!=null;){if(u==i&&!o){v=!0;break}o=!o&&u=="\\"}return(v||!(o||ne))&&(c.tokenize=null),"string"}}function K(i,a){for(var c=!1,o;o=i.next();){if(o=="/"&&c){a.tokenize=null;break}c=o=="*"}return"comment"}function A(i,a){e.typeFirstDefinitions&&i.eol()&&V(a.context)&&(a.typeAtEndOfLine=q(i,a,i.pos))}return{name:e.name,startState:function(i){return{tokenize:null,context:new R(-i,0,"top",null,!1),indented:0,startOfLine:!0,prevToken:null}},token:function(i,a){var c=a.context;if(i.sol()&&(c.align==null&&(c.align=!1),a.indented=i.indentation(),a.startOfLine=!0),i.eatSpace())return A(i,a),null;p=E=null;var o=(a.tokenize||U)(i,a);if(o=="comment"||o=="meta")return o;if(c.align==null&&(c.align=!0),p==";"||p==":"||p==","&&i.match(/^\s*(?:\/\/.*)?$/,!1))for(;a.context.type=="statement";)x(a);else if(p=="{")D(a,i.column(),"}");else if(p=="[")D(a,i.column(),"]");else if(p=="(")D(a,i.column(),")");else if(p=="}"){for(;c.type=="statement";)c=x(a);for(c.type=="}"&&(c=x(a));c.type=="statement";)c=x(a)}else p==c.type?x(a):re&&((c.type=="}"||c.type=="top")&&p!=";"||c.type=="statement"&&p=="newstatement")&&D(a,i.column(),"statement",i.current());if(o=="variable"&&(a.prevToken=="def"||e.typeFirstDefinitions&&q(i,a,i.start)&&V(a.context)&&i.match(/^\s*\(/,!1))&&(o="def"),y.token){var u=y.token(i,a,o);u!==void 0&&(o=u)}return o=="def"&&e.styleDefs===!1&&(o="variable"),a.startOfLine=!1,a.prevToken=E?"def":o||p,A(i,a),o},indent:function(i,a,c){if(i.tokenize!=U&&i.tokenize!=null||i.typeAtEndOfLine)return null;var o=i.context,u=a&&a.charAt(0),v=u==o.type;if(o.type=="statement"&&u=="}"&&(o=o.prev),e.dontIndentStatements)for(;o.type=="statement"&&e.dontIndentStatements.test(o.info);)o=o.prev;if(y.indent){var $=y.indent(i,o,a,c.unit);if(typeof $=="number")return $}var se=o.prev&&o.prev.info=="switch";if(e.allmanIndentation&&/[{(]/.test(u)){for(;o.type!="top"&&o.type!="}";)o=o.prev;return o.indented}return o.type=="statement"?o.indented+(u=="{"?0:t||c.unit):o.align&&(!n||o.type!=")")?o.column+(v?0:1):o.type==")"&&!v?o.indented+(t||c.unit):o.indented+(v?0:c.unit)+(!v&&se&&!/^(?:case|default)\b/.test(a)?c.unit:0)},languageData:{indentOnInput:ie?/^\s*(?:case .*?:|default:|\{\}?|\})$/:/^\s*[{}]$/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}},autocomplete:Object.keys(l).concat(Object.keys(s)).concat(Object.keys(d)).concat(Object.keys(w)),...e.languageData}}}function r(e){for(var t={},n=e.split(" "),l=0;l!?|\/#:@]/,hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},'"':function(e,t){return e.match('""')?(t.tokenize=J,t.tokenize(e,t)):!1},"'":function(e){return e.match(/^(\\[^'\s]+|[^\\'])'/)?"character":(e.eatWhile(/[\w\$_\xa1-\uffff]/),"atom")},"=":function(e,t){var n=t.context;return n.type=="}"&&n.align&&e.eat(">")?(t.context=new R(n.indented,n.column,n.type,n.info,null,n.prev),"operator"):!1},"/":function(e,t){return e.eat("*")?(t.tokenize=S(1),t.tokenize(e,t)):!1}},languageData:{closeBrackets:{brackets:["(","[","{","'",'"','"""']}}});function de(e){return function(t,n){for(var l=!1,s,d=!1;!t.eol();){if(!e&&!l&&t.match('"')){d=!0;break}if(e&&t.match('"""')){d=!0;break}s=t.next(),!l&&s=="$"&&t.match("{")&&t.skipTo("}"),l=!l&&s=="\\"&&!e}return(d||!e)&&(n.tokenize=null),"string"}}const _e=h({name:"kotlin",keywords:r("package as typealias class interface this super val operator var fun for is in This throw return annotation break continue object if else while do try when !in !is as? file import where by get set abstract enum open inner override private public internal protected catch finally out final vararg reified dynamic companion constructor init sealed field property receiver param sparam lateinit data inline noinline tailrec external annotation crossinline const operator infix suspend actual expect setparam"),types:r("Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy LazyThreadSafetyMode LongArray Nothing ShortArray Unit"),intendSwitch:!1,indentStatements:!1,multiLineStrings:!0,number:/^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+(\.\d+)?|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,blockKeywords:r("catch class do else finally for if where try while enum"),defKeywords:r("class val var object interface fun"),atoms:r("true false null this"),hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},"*":function(e,t){return t.prevToken=="."?"variable":"operator"},'"':function(e,t){return t.tokenize=de(e.match('""')),t.tokenize(e,t)},"/":function(e,t){return e.eat("*")?(t.tokenize=S(1),t.tokenize(e,t)):!1},indent:function(e,t,n,l){var s=n&&n.charAt(0);if((e.prevToken=="}"||e.prevToken==")")&&n=="")return e.indented;if(e.prevToken=="operator"&&n!="}"&&e.context.type!="}"||e.prevToken=="variable"&&s=="."||(e.prevToken=="}"||e.prevToken==")")&&s==".")return l*2+t.indented;if(t.align&&t.type=="}")return t.indented+(e.context.type==(n||"").charAt(0)?0:l)}},languageData:{closeBrackets:{brackets:["(","[","{","'",'"','"""']}}}),xe=h({name:"shader",keywords:r("sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadow const attribute uniform varying break continue discard return for while do if else struct in out inout"),types:r("float int bool void vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 mat2 mat3 mat4"),blockKeywords:r("for while do if else struct"),builtin:r("radians degrees sin cos tan asin acos atan pow exp log exp2 sqrt inversesqrt abs sign floor ceil fract mod min max clamp mix step smoothstep length distance dot cross normalize ftransform faceforward reflect refract matrixCompMult lessThan lessThanEqual greaterThan greaterThanEqual equal notEqual any all not texture1D texture1DProj texture1DLod texture1DProjLod texture2D texture2DProj texture2DLod texture2DProjLod texture3D texture3DProj texture3DLod texture3DProjLod textureCube textureCubeLod shadow1D shadow2D shadow1DProj shadow2DProj shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod dFdx dFdy fwidth noise1 noise2 noise3 noise4"),atoms:r("true false gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_FogCoord gl_PointCoord gl_Position gl_PointSize gl_ClipVertex gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_TexCoord gl_FogFragCoord gl_FragCoord gl_FrontFacing gl_FragData gl_FragDepth gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse gl_TextureMatrixTranspose gl_ModelViewMatrixInverseTranspose gl_ProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixInverseTranspose gl_TextureMatrixInverseTranspose gl_NormalScale gl_DepthRange gl_ClipPlane gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel gl_FrontLightModelProduct gl_BackLightModelProduct gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ gl_FogParameters gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits gl_MaxDrawBuffers"),indentSwitch:!1,hooks:{"#":g}}),Se=h({name:"nesc",keywords:r(T+" as atomic async call command component components configuration event generic implementation includes interface module new norace nx_struct nx_union post provides signal task uses abstract extends"),types:I,blockKeywords:r(N),atoms:r("null true false"),hooks:{"#":g}}),Te=h({name:"objectivec",keywords:r(T+" "+Q),types:X,builtin:r(Z),blockKeywords:r(N+" @synthesize @try @catch @finally @autoreleasepool @synchronized"),defKeywords:r(z+" @interface @implementation @protocol @class"),dontIndentStatements:/^@.*$/,typeFirstDefinitions:!0,atoms:r("YES NO NULL Nil nil true false nullptr"),isReservedIdentifier:C,hooks:{"#":g,"*":M}}),Ie=h({name:"objectivecpp",keywords:r(T+" "+Q+" "+H),types:X,builtin:r(Z),blockKeywords:r(N+" @synthesize @try @catch @finally @autoreleasepool @synchronized class try catch"),defKeywords:r(z+" @interface @implementation @protocol @class class namespace"),dontIndentStatements:/^@.*$|^template$/,typeFirstDefinitions:!0,atoms:r("YES NO NULL Nil nil true false nullptr"),isReservedIdentifier:C,hooks:{"#":g,"*":M,u:m,U:m,L:m,R:m,0:f,1:f,2:f,3:f,4:f,5:f,6:f,7:f,8:f,9:f,token:function(e,t,n){if(n=="variable"&&e.peek()=="("&&(t.prevToken==";"||t.prevToken==null||t.prevToken=="}")&&Y(e.current()))return"def"}},namespaceSeparator:"::"}),Ne=h({name:"squirrel",keywords:r("base break clone continue const default delete enum extends function in class foreach local resume return this throw typeof yield constructor instanceof static"),types:I,blockKeywords:r("case catch class else for foreach if switch try while"),defKeywords:r("function local class"),typeFirstDefinitions:!0,atoms:r("true false null"),hooks:{"#":g}});var L=null;function ee(e){return function(t,n){for(var l=!1,s,d=!1;!t.eol();){if(!l&&t.match('"')&&(e=="single"||t.match('""'))){d=!0;break}if(!l&&t.match("``")){L=ee(e),d=!0;break}s=t.next(),l=e=="single"&&!l&&s=="\\"}return d&&(n.tokenize=null),"string"}}const De=h({name:"ceylon",keywords:r("abstracts alias assembly assert assign break case catch class continue dynamic else exists extends finally for function given if import in interface is let module new nonempty object of out outer package return satisfies super switch then this throw try value void while"),types:function(e){var t=e.charAt(0);return t===t.toUpperCase()&&t!==t.toLowerCase()},blockKeywords:r("case catch class dynamic else finally for function if interface module new object switch try while"),defKeywords:r("class dynamic function interface module object package value"),builtin:r("abstract actual aliased annotation by default deprecated doc final formal late license native optional sealed see serializable shared suppressWarnings tagged throws variable"),isPunctuationChar:/[\[\]{}\(\),;\:\.`]/,isOperatorChar:/[+\-*&%=<>!?|^~:\/]/,numberStart:/[\d#$]/,number:/^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,multiLineStrings:!0,typeFirstDefinitions:!0,atoms:r("true false null larger smaller equal empty finished"),indentSwitch:!1,styleDefs:!1,hooks:{"@":function(e){return e.eatWhile(/[\w\$_]/),"meta"},'"':function(e,t){return t.tokenize=ee(e.match('""')?"triple":"single"),t.tokenize(e,t)},"`":function(e,t){return!L||!e.match("`")?!1:(t.tokenize=L,L=null,t.tokenize(e,t))},"'":function(e){return e.eatWhile(/[\w\$_\xa1-\uffff]/),"atom"},token:function(e,t,n){if((n=="variable"||n=="type")&&t.prevToken==".")return"variableName.special"}},languageData:{closeBrackets:{brackets:["(","[","{","'",'"','"""']}}});function pe(e){(e.interpolationStack||(e.interpolationStack=[])).push(e.tokenize)}function te(e){return(e.interpolationStack||(e.interpolationStack=[])).pop()}function he(e){return e.interpolationStack?e.interpolationStack.length:0}function P(e,t,n,l){var s=!1;if(t.eat(e))if(t.eat(e))s=!0;else return"string";function d(b,_){for(var w=!1;!b.eol();){if(!l&&!w&&b.peek()=="$")return pe(_),_.tokenize=ye,"string";var y=b.next();if(y==e&&!w&&(!s||b.match(e+e))){_.tokenize=null;break}w=!l&&!w&&y=="\\"}return"string"}return n.tokenize=d,d(t,n)}function ye(e,t){return e.eat("$"),e.eat("{")?t.tokenize=null:t.tokenize=ke,null}function ke(e,t){return e.eatWhile(/[\w_]/),t.tokenize=te(t),"variable"}const Le=h({name:"dart",keywords:r("this super static final const abstract class extends external factory implements mixin get native set typedef with enum throw rethrow assert break case continue default in return new deferred async await covariant try catch finally do else for if switch while import library export part of show hide is as extension on yield late required"),blockKeywords:r("try catch finally do else for if switch while"),builtin:r("void bool num int double dynamic var String Null Never"),atoms:r("true false null"),hooks:{"@":function(e){return e.eatWhile(/[\w\$_\.]/),"meta"},"'":function(e,t){return P("'",e,t,!1)},'"':function(e,t){return P('"',e,t,!1)},r:function(e,t){var n=e.peek();return n=="'"||n=='"'?P(e.next(),e,t,!0):!1},"}":function(e,t){return he(t)>0?(t.tokenize=te(t),null):!1},"/":function(e,t){return e.eat("*")?(t.tokenize=S(1),t.tokenize(e,t)):!1},token:function(e,t,n){if(n=="variable"){var l=RegExp("^[_$]*[A-Z][a-zA-Z0-9_$]*$","g");if(l.test(e.current()))return"type"}}}});export{me as c,De as ceylon,h as clike,ge as cpp,we as csharp,Le as dart,be as java,_e as kotlin,Se as nesC,Te as objectiveC,Ie as objectiveCpp,ve as scala,xe as shader,Ne as squirrel};
diff --git a/docs/assets/clojure-46c215dd.js b/docs/assets/clojure-46c215dd.js
new file mode 100644
index 00000000..985d06c1
--- /dev/null
+++ b/docs/assets/clojure-46c215dd.js
@@ -0,0 +1 @@
+var d=["false","nil","true"],l=[".","catch","def","do","if","monitor-enter","monitor-exit","new","quote","recur","set!","throw","try","var"],u=["*","*'","*1","*2","*3","*agent*","*allow-unresolved-vars*","*assert*","*clojure-version*","*command-line-args*","*compile-files*","*compile-path*","*compiler-options*","*data-readers*","*default-data-reader-fn*","*e","*err*","*file*","*flush-on-newline*","*fn-loader*","*in*","*math-context*","*ns*","*out*","*print-dup*","*print-length*","*print-level*","*print-meta*","*print-namespace-maps*","*print-readably*","*read-eval*","*reader-resolver*","*source-path*","*suppress-read*","*unchecked-math*","*use-context-classloader*","*verbose-defrecords*","*warn-on-reflection*","+","+'","-","-'","->","->>","->ArrayChunk","->Eduction","->Vec","->VecNode","->VecSeq","-cache-protocol-fn","-reset-methods","..","/","<","<=","=","==",">",">=","EMPTY-NODE","Inst","StackTraceElement->vec","Throwable->map","accessor","aclone","add-classpath","add-watch","agent","agent-error","agent-errors","aget","alength","alias","all-ns","alter","alter-meta!","alter-var-root","amap","ancestors","and","any?","apply","areduce","array-map","as->","aset","aset-boolean","aset-byte","aset-char","aset-double","aset-float","aset-int","aset-long","aset-short","assert","assoc","assoc!","assoc-in","associative?","atom","await","await-for","await1","bases","bean","bigdec","bigint","biginteger","binding","bit-and","bit-and-not","bit-clear","bit-flip","bit-not","bit-or","bit-set","bit-shift-left","bit-shift-right","bit-test","bit-xor","boolean","boolean-array","boolean?","booleans","bound-fn","bound-fn*","bound?","bounded-count","butlast","byte","byte-array","bytes","bytes?","case","cast","cat","char","char-array","char-escape-string","char-name-string","char?","chars","chunk","chunk-append","chunk-buffer","chunk-cons","chunk-first","chunk-next","chunk-rest","chunked-seq?","class","class?","clear-agent-errors","clojure-version","coll?","comment","commute","comp","comparator","compare","compare-and-set!","compile","complement","completing","concat","cond","cond->","cond->>","condp","conj","conj!","cons","constantly","construct-proxy","contains?","count","counted?","create-ns","create-struct","cycle","dec","dec'","decimal?","declare","dedupe","default-data-readers","definline","definterface","defmacro","defmethod","defmulti","defn","defn-","defonce","defprotocol","defrecord","defstruct","deftype","delay","delay?","deliver","denominator","deref","derive","descendants","destructure","disj","disj!","dissoc","dissoc!","distinct","distinct?","doall","dorun","doseq","dosync","dotimes","doto","double","double-array","double?","doubles","drop","drop-last","drop-while","eduction","empty","empty?","ensure","ensure-reduced","enumeration-seq","error-handler","error-mode","eval","even?","every-pred","every?","ex-data","ex-info","extend","extend-protocol","extend-type","extenders","extends?","false?","ffirst","file-seq","filter","filterv","find","find-keyword","find-ns","find-protocol-impl","find-protocol-method","find-var","first","flatten","float","float-array","float?","floats","flush","fn","fn?","fnext","fnil","for","force","format","frequencies","future","future-call","future-cancel","future-cancelled?","future-done?","future?","gen-class","gen-interface","gensym","get","get-in","get-method","get-proxy-class","get-thread-bindings","get-validator","group-by","halt-when","hash","hash-combine","hash-map","hash-ordered-coll","hash-set","hash-unordered-coll","ident?","identical?","identity","if-let","if-not","if-some","ifn?","import","in-ns","inc","inc'","indexed?","init-proxy","inst-ms","inst-ms*","inst?","instance?","int","int-array","int?","integer?","interleave","intern","interpose","into","into-array","ints","io!","isa?","iterate","iterator-seq","juxt","keep","keep-indexed","key","keys","keyword","keyword?","last","lazy-cat","lazy-seq","let","letfn","line-seq","list","list*","list?","load","load-file","load-reader","load-string","loaded-libs","locking","long","long-array","longs","loop","macroexpand","macroexpand-1","make-array","make-hierarchy","map","map-entry?","map-indexed","map?","mapcat","mapv","max","max-key","memfn","memoize","merge","merge-with","meta","method-sig","methods","min","min-key","mix-collection-hash","mod","munge","name","namespace","namespace-munge","nat-int?","neg-int?","neg?","newline","next","nfirst","nil?","nnext","not","not-any?","not-empty","not-every?","not=","ns","ns-aliases","ns-imports","ns-interns","ns-map","ns-name","ns-publics","ns-refers","ns-resolve","ns-unalias","ns-unmap","nth","nthnext","nthrest","num","number?","numerator","object-array","odd?","or","parents","partial","partition","partition-all","partition-by","pcalls","peek","persistent!","pmap","pop","pop!","pop-thread-bindings","pos-int?","pos?","pr","pr-str","prefer-method","prefers","primitives-classnames","print","print-ctor","print-dup","print-method","print-simple","print-str","printf","println","println-str","prn","prn-str","promise","proxy","proxy-call-with-super","proxy-mappings","proxy-name","proxy-super","push-thread-bindings","pvalues","qualified-ident?","qualified-keyword?","qualified-symbol?","quot","rand","rand-int","rand-nth","random-sample","range","ratio?","rational?","rationalize","re-find","re-groups","re-matcher","re-matches","re-pattern","re-seq","read","read-line","read-string","reader-conditional","reader-conditional?","realized?","record?","reduce","reduce-kv","reduced","reduced?","reductions","ref","ref-history-count","ref-max-history","ref-min-history","ref-set","refer","refer-clojure","reify","release-pending-sends","rem","remove","remove-all-methods","remove-method","remove-ns","remove-watch","repeat","repeatedly","replace","replicate","require","reset!","reset-meta!","reset-vals!","resolve","rest","restart-agent","resultset-seq","reverse","reversible?","rseq","rsubseq","run!","satisfies?","second","select-keys","send","send-off","send-via","seq","seq?","seqable?","seque","sequence","sequential?","set","set-agent-send-executor!","set-agent-send-off-executor!","set-error-handler!","set-error-mode!","set-validator!","set?","short","short-array","shorts","shuffle","shutdown-agents","simple-ident?","simple-keyword?","simple-symbol?","slurp","some","some->","some->>","some-fn","some?","sort","sort-by","sorted-map","sorted-map-by","sorted-set","sorted-set-by","sorted?","special-symbol?","spit","split-at","split-with","str","string?","struct","struct-map","subs","subseq","subvec","supers","swap!","swap-vals!","symbol","symbol?","sync","tagged-literal","tagged-literal?","take","take-last","take-nth","take-while","test","the-ns","thread-bound?","time","to-array","to-array-2d","trampoline","transduce","transient","tree-seq","true?","type","unchecked-add","unchecked-add-int","unchecked-byte","unchecked-char","unchecked-dec","unchecked-dec-int","unchecked-divide-int","unchecked-double","unchecked-float","unchecked-inc","unchecked-inc-int","unchecked-int","unchecked-long","unchecked-multiply","unchecked-multiply-int","unchecked-negate","unchecked-negate-int","unchecked-remainder-int","unchecked-short","unchecked-subtract","unchecked-subtract-int","underive","unquote","unquote-splicing","unreduced","unsigned-bit-shift-right","update","update-in","update-proxy","uri?","use","uuid?","val","vals","var-get","var-set","var?","vary-meta","vec","vector","vector-of","vector?","volatile!","volatile?","vreset!","vswap!","when","when-first","when-let","when-not","when-some","while","with-bindings","with-bindings*","with-in-str","with-loading-context","with-local-vars","with-meta","with-open","with-out-str","with-precision","with-redefs","with-redefs-fn","xml-seq","zero?","zipmap"],p=["->","->>","as->","binding","bound-fn","case","catch","comment","cond","cond->","cond->>","condp","def","definterface","defmethod","defn","defmacro","defprotocol","defrecord","defstruct","deftype","do","doseq","dotimes","doto","extend","extend-protocol","extend-type","fn","for","future","if","if-let","if-not","if-some","let","letfn","locking","loop","ns","proxy","reify","struct-map","some->","some->>","try","when","when-first","when-let","when-not","when-some","while","with-bindings","with-bindings*","with-in-str","with-loading-context","with-local-vars","with-meta","with-open","with-out-str","with-precision","with-redefs","with-redefs-fn"],f=o(d),m=o(l),h=o(u),y=o(p),b=/^(?:[\\\[\]\s"(),;@^`{}~]|$)/,v=/^(?:[+\-]?\d+(?:(?:N|(?:[eE][+\-]?\d+))|(?:\.?\d*(?:M|(?:[eE][+\-]?\d+))?)|\/\d+|[xX][0-9a-fA-F]+|r[0-9a-zA-Z]+)?(?=[\\\[\]\s"#'(),;@^`{}~]|$))/,g=/^(?:\\(?:backspace|formfeed|newline|return|space|tab|o[0-7]{3}|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{4}|.)?(?=[\\\[\]\s"(),;@^`{}~]|$))/,k=/^(?:(?:[^\\\/\[\]\d\s"#'(),;@^`{}~.][^\\\[\]\s"(),;@^`{}~.\/]*(?:\.[^\\\/\[\]\d\s"#'(),;@^`{}~.][^\\\[\]\s"(),;@^`{}~.\/]*)*\/)?(?:\/|[^\\\/\[\]\d\s"#'(),;@^`{}~][^\\\[\]\s"(),;@^`{}~]*)*(?=[\\\[\]\s"(),;@^`{}~]|$))/;function s(t,e){if(t.eatSpace()||t.eat(","))return["space",null];if(t.match(v))return[null,"number"];if(t.match(g))return[null,"string.special"];if(t.eat(/^"/))return(e.tokenize=x)(t,e);if(t.eat(/^[(\[{]/))return["open","bracket"];if(t.eat(/^[)\]}]/))return["close","bracket"];if(t.eat(/^;/))return t.skipToEnd(),["space","comment"];if(t.eat(/^[#'@^`~]/))return[null,"meta"];var r=t.match(k),n=r&&r[0];return n?n==="comment"&&e.lastToken==="("?(e.tokenize=w)(t,e):a(n,f)||n.charAt(0)===":"?["symbol","atom"]:a(n,m)||a(n,h)?["symbol","keyword"]:e.lastToken==="("?["symbol","builtin"]:["symbol","variable"]:(t.next(),t.eatWhile(function(i){return!a(i,b)}),[null,"error"])}function x(t,e){for(var r=!1,n;n=t.next();){if(n==='"'&&!r){e.tokenize=s;break}r=!r&&n==="\\"}return[null,"string"]}function w(t,e){for(var r=1,n;n=t.next();)if(n===")"&&r--,n==="("&&r++,r===0){t.backUp(1),e.tokenize=s;break}return["space","comment"]}function o(t){for(var e={},r=0;r >= "),N={digit:/\d/,digit_or_colon:/[\d:]/,hex:/[0-9a-f]/i,sign:/[+-]/,exponent:/e/i,keyword_char:/[^\s\(\[\;\)\]]/,symbol:/[\w*+\-]/};function F(E,T){return E==="0"&&T.eat(/x/i)?(T.eatWhile(N.hex),!0):((E=="+"||E=="-")&&N.digit.test(T.peek())&&(T.eat(N.sign),E=T.next()),N.digit.test(E)?(T.eat(E),T.eatWhile(N.digit),T.peek()=="."&&(T.eat("."),T.eatWhile(N.digit)),T.eat(N.exponent)&&(T.eat(N.sign),T.eatWhile(N.digit)),!0):!1)}const Y={name:"cobol",startState:function(){return{indentStack:null,indentation:0,mode:!1}},token:function(E,T){if(T.indentStack==null&&E.sol()&&(T.indentation=6),E.eatSpace())return null;var I=null;switch(T.mode){case"string":for(var R=!1;(R=E.next())!=null;)if((R=='"'||R=="'")&&!E.match(/['"]/,!1)){T.mode=!1;break}I=C;break;default:var O=E.next(),A=E.column();if(A>=0&&A<=5)I=B;else if(A>=72&&A<=79)E.skipToEnd(),I=i;else if(O=="*"&&A==6)E.skipToEnd(),I=e;else if(O=='"'||O=="'")T.mode="string",I=C;else if(O=="'"&&!N.digit_or_colon.test(E.peek()))I=D;else if(O==".")I=t;else if(F(O,E))I=G;else{if(E.current().match(N.symbol))for(;A<71&&E.eat(N.symbol)!==void 0;)A++;U&&U.propertyIsEnumerable(E.current().toUpperCase())?I=n:P&&P.propertyIsEnumerable(E.current().toUpperCase())?I=M:S&&S.propertyIsEnumerable(E.current().toUpperCase())?I=D:I=null}}return I},indent:function(E){return E.indentStack==null?E.indentation:E.indentStack.indent}};export{Y as cobol};
diff --git a/docs/assets/coffeescript-cf6fb77c.js b/docs/assets/coffeescript-cf6fb77c.js
new file mode 100644
index 00000000..ca71cbf7
--- /dev/null
+++ b/docs/assets/coffeescript-cf6fb77c.js
@@ -0,0 +1 @@
+var k="error";function p(e){return new RegExp("^(("+e.join(")|(")+"))\\b")}var g=/^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/,y=/^(?:[()\[\]{},:`=;]|\.\.?\.?)/,h=/^[_A-Za-z$][_A-Za-z$0-9]*/,w=/^@[_A-Za-z$][_A-Za-z$0-9]*/,z=p(["and","or","not","is","isnt","in","instanceof","typeof"]),l=["for","while","loop","if","unless","else","switch","try","catch","finally","class"],a=["break","by","continue","debugger","delete","do","in","of","new","return","then","this","@","throw","when","until","extends"],x=p(l.concat(a));l=p(l);var b=/^('{3}|\"{3}|['\"])/,A=/^(\/{3}|\/)/,S=["Infinity","NaN","undefined","null","true","false","on","off","yes","no"],O=p(S);function u(e,n){if(e.sol()){n.scope.align===null&&(n.scope.align=!1);var i=n.scope.offset;if(e.eatSpace()){var f=e.indentation();return f>i&&n.scope.type=="coffee"?"indent":f0&&v(e,n)}if(e.eatSpace())return null;var r=e.peek();if(e.match("####"))return e.skipToEnd(),"comment";if(e.match("###"))return n.tokenize=R,n.tokenize(e,n);if(r==="#")return e.skipToEnd(),"comment";if(e.match(/^-?[0-9\.]/,!1)){var c=!1;if(e.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)&&(c=!0),e.match(/^-?\d+\.\d*/)&&(c=!0),e.match(/^-?\.\d+/)&&(c=!0),c)return e.peek()=="."&&e.backUp(1),"number";var o=!1;if(e.match(/^-?0x[0-9a-f]+/i)&&(o=!0),e.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)&&(o=!0),e.match(/^-?0(?![\dx])/i)&&(o=!0),o)return"number"}if(e.match(b))return n.tokenize=t(e.current(),!1,"string"),n.tokenize(e,n);if(e.match(A)){if(e.current()!="/"||e.match(/^.*\//,!1))return n.tokenize=t(e.current(),!0,"string.special"),n.tokenize(e,n);e.backUp(1)}return e.match(g)||e.match(z)?"operator":e.match(y)?"punctuation":e.match(O)?"atom":e.match(w)||n.prop&&e.match(h)?"property":e.match(x)?"keyword":e.match(h)?"variable":(e.next(),k)}function t(e,n,i){return function(f,r){for(;!f.eol();)if(f.eatWhile(/[^'"\/\\]/),f.eat("\\")){if(f.next(),n&&f.eol())return i}else{if(f.match(e))return r.tokenize=u,i;f.eat(/['"\/]/)}return n&&(r.tokenize=u),i}}function R(e,n){for(;!e.eol();){if(e.eatWhile(/[^#]/),e.match("###")){n.tokenize=u;break}e.eatWhile("#")}return"comment"}function d(e,n,i="coffee"){for(var f=0,r=!1,c=null,o=n.scope;o;o=o.prev)if(o.type==="coffee"||o.type=="}"){f=o.offset+e.indentUnit;break}i!=="coffee"?(r=null,c=e.column()+e.current().length):n.scope.align&&(n.scope.align=!1),n.scope={offset:f,type:i,prev:n.scope,align:r,alignOffset:c}}function v(e,n){if(n.scope.prev)if(n.scope.type==="coffee"){for(var i=e.indentation(),f=!1,r=n.scope;r;r=r.prev)if(i===r.offset){f=!0;break}if(!f)return!0;for(;n.scope.prev&&n.scope.offset!==i;)n.scope=n.scope.prev;return!1}else return n.scope=n.scope.prev,!1}function E(e,n){var i=n.tokenize(e,n),f=e.current();f==="return"&&(n.dedent=!0),((f==="->"||f==="=>")&&e.eol()||i==="indent")&&d(e,n);var r="[({".indexOf(f);if(r!==-1&&d(e,n,"])}".slice(r,r+1)),l.exec(f)&&d(e,n),f=="then"&&v(e,n),i==="dedent"&&v(e,n))return k;if(r="])}".indexOf(f),r!==-1){for(;n.scope.type=="coffee"&&n.scope.prev;)n.scope=n.scope.prev;n.scope.type==f&&(n.scope=n.scope.prev)}return n.dedent&&e.eol()&&(n.scope.type=="coffee"&&n.scope.prev&&(n.scope=n.scope.prev),n.dedent=!1),i=="indent"||i=="dedent"?null:i}const Z={name:"coffeescript",startState:function(){return{tokenize:u,scope:{offset:0,type:"coffee",prev:null,align:!1},prop:!1,dedent:0}},token:function(e,n){var i=n.scope.align===null&&n.scope;i&&e.sol()&&(i.align=!1);var f=E(e,n);return f&&f!="comment"&&(i&&(i.align=!0),n.prop=f=="punctuation"&&e.current()=="."),f},indent:function(e,n){if(e.tokenize!=u)return 0;var i=e.scope,f=n&&"])}".indexOf(n.charAt(0))>-1;if(f)for(;i.type=="coffee"&&i.prev;)i=i.prev;var r=f&&i.type===n.charAt(0);return i.align?i.alignOffset-(r?1:0):(r?i.prev:i).offset},languageData:{commentTokens:{line:"#"}}};export{Z as coffeeScript};
diff --git a/docs/assets/commonlisp-0ea12945.js b/docs/assets/commonlisp-0ea12945.js
new file mode 100644
index 00000000..56b01f6d
--- /dev/null
+++ b/docs/assets/commonlisp-0ea12945.js
@@ -0,0 +1 @@
+var u=/^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/,c=/^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/,f=/^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/,d=/[^\s'`,@()\[\]";]/,l;function i(e){for(var n;n=e.next();)if(n=="\\")e.next();else if(!d.test(n)){e.backUp(1);break}return e.current()}function o(e,n){if(e.eatSpace())return l="ws",null;if(e.match(f))return"number";var t=e.next();if(t=="\\"&&(t=e.next()),t=='"')return(n.tokenize=p)(e,n);if(t=="(")return l="open","bracket";if(t==")"||t=="]")return l="close","bracket";if(t==";")return e.skipToEnd(),l="ws","comment";if(/['`,@]/.test(t))return null;if(t=="|")return e.skipTo("|")?(e.next(),"variableName"):(e.skipToEnd(),"error");if(t=="#"){var t=e.next();return t=="("?(l="open","bracket"):/[+\-=\.']/.test(t)||/\d/.test(t)&&e.match(/^\d*#/)?null:t=="|"?(n.tokenize=x)(e,n):t==":"?(i(e),"meta"):t=="\\"?(e.next(),i(e),"string.special"):"error"}else{var r=i(e);return r=="."?null:(l="symbol",r=="nil"||r=="t"||r.charAt(0)==":"?"atom":n.lastType=="open"&&(u.test(r)||c.test(r))?"keyword":r.charAt(0)=="&"?"variableName.special":"variableName")}}function p(e,n){for(var t=!1,r;r=e.next();){if(r=='"'&&!t){n.tokenize=o;break}t=!t&&r=="\\"}return"string"}function x(e,n){for(var t,r;t=e.next();){if(t=="#"&&r=="|"){n.tokenize=o;break}r=t}return l="ws","comment"}const s={name:"commonlisp",startState:function(){return{ctx:{prev:null,start:0,indentTo:0},lastType:null,tokenize:o}},token:function(e,n){e.sol()&&typeof n.ctx.indentTo!="number"&&(n.ctx.indentTo=n.ctx.start+1),l=null;var t=n.tokenize(e,n);return l!="ws"&&(n.ctx.indentTo==null?l=="symbol"&&c.test(e.current())?n.ctx.indentTo=n.ctx.start+e.indentUnit:n.ctx.indentTo="next":n.ctx.indentTo=="next"&&(n.ctx.indentTo=e.column()),n.lastType=l),l=="open"?n.ctx={prev:n.ctx,start:e.column(),indentTo:null}:l=="close"&&(n.ctx=n.ctx.prev||n.ctx),t},indent:function(e){var n=e.ctx.indentTo;return typeof n=="number"?n:e.ctx.start+1},languageData:{commentTokens:{line:";;",block:{open:"#|",close:"|#"}},closeBrackets:{brackets:["(","[","{",'"']}}};export{s as commonLisp};
diff --git a/docs/assets/crystal-594a913c.js b/docs/assets/crystal-594a913c.js
new file mode 100644
index 00000000..b569c69d
--- /dev/null
+++ b/docs/assets/crystal-594a913c.js
@@ -0,0 +1 @@
+function l(n,e){return new RegExp((e?"":"^")+"(?:"+n.join("|")+")"+(e?"$":"\\b"))}function o(n,e,r){return r.tokenize.push(n),n(e,r)}var v=/^(?:[-+/%|&^]|\*\*?|[<>]{2})/,z=/^(?:[=!]~|===|<=>|[<>=!]=?|[|&]{2}|~)/,g=/^(?:\[\][?=]?)/,b=/^(?:\.(?:\.{2})?|->|[?:])/,p=/^[a-z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/,d=/^[A-Z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/,E=l(["abstract","alias","as","asm","begin","break","case","class","def","do","else","elsif","end","ensure","enum","extend","for","fun","if","include","instance_sizeof","lib","macro","module","next","of","out","pointerof","private","protected","rescue","return","require","select","sizeof","struct","super","then","type","typeof","uninitialized","union","unless","until","when","while","with","yield","__DIR__","__END_LINE__","__FILE__","__LINE__"]),S=l(["true","false","nil","self"]),T=["def","fun","macro","class","module","struct","lib","enum","union","do","for"],A=l(T),s=["if","unless","case","while","until","begin","then"],O=l(s),x=["end","else","elsif","rescue","ensure"],K=l(x),I=["\\)","\\}","\\]"],D=new RegExp("^(?:"+I.join("|")+")$"),w={def:y,fun:y,macro:N,class:c,module:c,struct:c,lib:c,enum:c,union:c},k={"[":"]","{":"}","(":")","<":">"};function _(n,e){if(n.eatSpace())return null;if(e.lastToken!="\\"&&n.match("{%",!1))return o(f("%","%"),n,e);if(e.lastToken!="\\"&&n.match("{{",!1))return o(f("{","}"),n,e);if(n.peek()=="#")return n.skipToEnd(),"comment";var r;if(n.match(p))return n.eat(/[?!]/),r=n.current(),n.eat(":")?"atom":e.lastToken=="."?"property":E.test(r)?(A.test(r)?!(r=="fun"&&e.blocks.indexOf("lib")>=0)&&!(r=="def"&&e.lastToken=="abstract")&&(e.blocks.push(r),e.currentIndent+=1):(e.lastStyle=="operator"||!e.lastStyle)&&O.test(r)?(e.blocks.push(r),e.currentIndent+=1):r=="end"&&(e.blocks.pop(),e.currentIndent-=1),w.hasOwnProperty(r)&&e.tokenize.push(w[r]),"keyword"):S.test(r)?"atom":"variable";if(n.eat("@"))return n.peek()=="["?o(h("[","]","meta"),n,e):(n.eat("@"),n.match(p)||n.match(d),"propertyName");if(n.match(d))return"tag";if(n.eat(":"))return n.eat('"')?o(F('"',"atom",!1),n,e):n.match(p)||n.match(d)||n.match(v)||n.match(z)||n.match(g)?"atom":(n.eat(":"),"operator");if(n.eat('"'))return o(F('"',"string",!0),n,e);if(n.peek()=="%"){var t="string",u=!0,i;if(n.match("%r"))t="string.special",i=n.next();else if(n.match("%w"))u=!1,i=n.next();else if(n.match("%q"))u=!1,i=n.next();else if(i=n.match(/^%([^\w\s=])/))i=i[1];else{if(n.match(/^%[a-zA-Z_\u009F-\uFFFF][\w\u009F-\uFFFF]*/))return"meta";if(n.eat("%"))return"operator"}return k.hasOwnProperty(i)&&(i=k[i]),o(F(i,t,u),n,e)}return(r=n.match(/^<<-('?)([A-Z]\w*)\1/))?o(Z(r[2],!r[1]),n,e):n.eat("'")?(n.match(/^(?:[^']|\\(?:[befnrtv0'"]|[0-7]{3}|u(?:[0-9a-fA-F]{4}|\{[0-9a-fA-F]{1,6}\})))/),n.eat("'"),"atom"):n.eat("0")?(n.eat("x")?n.match(/^[0-9a-fA-F_]+/):n.eat("o")?n.match(/^[0-7_]+/):n.eat("b")&&n.match(/^[01_]+/),"number"):n.eat(/^\d/)?(n.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?\d+)?/),"number"):n.match(v)?(n.eat("="),"operator"):n.match(z)||n.match(b)?"operator":(r=n.match(/[({[]/,!1))?(r=r[0],o(h(r,k[r],null),n,e)):n.eat("\\")?(n.next(),"meta"):(n.next(),null)}function h(n,e,r,t){return function(u,i){if(!t&&u.match(n))return i.tokenize[i.tokenize.length-1]=h(n,e,r,!0),i.currentIndent+=1,r;var a=_(u,i);return u.current()===e&&(i.tokenize.pop(),i.currentIndent-=1,a=r),a}}function f(n,e,r){return function(t,u){return!r&&t.match("{"+n)?(u.currentIndent+=1,u.tokenize[u.tokenize.length-1]=f(n,e,!0),"meta"):t.match(e+"}")?(u.currentIndent-=1,u.tokenize.pop(),"meta"):_(t,u)}}function N(n,e){if(n.eatSpace())return null;var r;if(r=n.match(p)){if(r=="def")return"keyword";n.eat(/[?!]/)}return e.tokenize.pop(),"def"}function y(n,e){return n.eatSpace()?null:(n.match(p)?n.eat(/[!?]/):n.match(v)||n.match(z)||n.match(g),e.tokenize.pop(),"def")}function c(n,e){return n.eatSpace()?null:(n.match(d),e.tokenize.pop(),"def")}function F(n,e,r){return function(t,u){for(var i=!1;t.peek();)if(i)t.next(),i=!1;else{if(t.match("{%",!1))return u.tokenize.push(f("%","%")),e;if(t.match("{{",!1))return u.tokenize.push(f("{","}")),e;if(r&&t.match("#{",!1))return u.tokenize.push(h("#{","}","meta")),e;var a=t.next();if(a==n)return u.tokenize.pop(),e;i=r&&a=="\\"}return e}}function Z(n,e){return function(r,t){if(r.sol()&&(r.eatSpace(),r.match(n)))return t.tokenize.pop(),"string";for(var u=!1;r.peek();)if(u)r.next(),u=!1;else{if(r.match("{%",!1))return t.tokenize.push(f("%","%")),"string";if(r.match("{{",!1))return t.tokenize.push(f("{","}")),"string";if(e&&r.match("#{",!1))return t.tokenize.push(h("#{","}","meta")),"string";u=e&&r.next()=="\\"}return"string"}}const P={name:"crystal",startState:function(){return{tokenize:[_],currentIndent:0,lastToken:null,lastStyle:null,blocks:[]}},token:function(n,e){var r=e.tokenize[e.tokenize.length-1](n,e),t=n.current();return r&&r!="comment"&&(e.lastToken=t,e.lastStyle=r),r},indent:function(n,e,r){return e=e.replace(/^\s*(?:\{%)?\s*|\s*(?:%\})?\s*$/g,""),K.test(e)||D.test(e)?r.unit*(n.currentIndent-1):r.unit*n.currentIndent},languageData:{indentOnInput:l(I.concat(x),!0),commentTokens:{line:"#"}}};export{P as crystal};
diff --git a/docs/assets/css-ae0ae1d0.js b/docs/assets/css-ae0ae1d0.js
new file mode 100644
index 00000000..0a0eedee
--- /dev/null
+++ b/docs/assets/css-ae0ae1d0.js
@@ -0,0 +1 @@
+function y(i){i={...ae,...i};var l=i.inline,m=i.tokenHooks,b=i.documentTypes||{},G=i.mediaTypes||{},J=i.mediaFeatures||{},Q=i.mediaValueKeywords||{},O=i.propertyKeywords||{},F=i.nonStandardPropertyKeywords||{},R=i.fontProperties||{},ee=i.counterDescriptors||{},N=i.colorKeywords||{},V=i.valueKeywords||{},g=i.allowNested,re=i.lineComment,oe=i.supportsAtComponent===!0,W=i.highlightNonStandardPropertyKeywords!==!1,w,n;function c(e,o){return w=o,e}function ie(e,o){var r=e.next();if(m[r]){var t=m[r](e,o);if(t!==!1)return t}if(r=="@")return e.eatWhile(/[\w\\\-]/),c("def",e.current());if(r=="="||(r=="~"||r=="|")&&e.eat("="))return c(null,"compare");if(r=='"'||r=="'")return o.tokenize=$(r),o.tokenize(e,o);if(r=="#")return e.eatWhile(/[\w\\\-]/),c("atom","hash");if(r=="!")return e.match(/^\s*\w*/),c("keyword","important");if(/\d/.test(r)||r=="."&&e.eat(/\d/))return e.eatWhile(/[\w.%]/),c("number","unit");if(r==="-"){if(/[\d.]/.test(e.peek()))return e.eatWhile(/[\w.%]/),c("number","unit");if(e.match(/^-[\w\\\-]*/))return e.eatWhile(/[\w\\\-]/),e.match(/^\s*:/,!1)?c("def","variable-definition"):c("variableName","variable");if(e.match(/^\w+-/))return c("meta","meta")}else return/[,+>*\/]/.test(r)?c(null,"select-op"):r=="."&&e.match(/^-?[_a-z][_a-z0-9-]*/i)?c("qualifier","qualifier"):/[:;{}\[\]\(\)]/.test(r)?c(null,r):e.match(/^[\w-.]+(?=\()/)?(/^(url(-prefix)?|domain|regexp)$/i.test(e.current())&&(o.tokenize=te),c("variableName.function","variable")):/[\w\\\-]/.test(r)?(e.eatWhile(/[\w\\\-]/),c("property","word")):c(null,null)}function $(e){return function(o,r){for(var t=!1,d;(d=o.next())!=null;){if(d==e&&!t){e==")"&&o.backUp(1);break}t=!t&&d=="\\"}return(d==e||!t&&e!=")")&&(r.tokenize=null),c("string","string")}}function te(e,o){return e.next(),e.match(/^\s*[\"\')]/,!1)?o.tokenize=null:o.tokenize=$(")"),c(null,"(")}function D(e,o,r){this.type=e,this.indent=o,this.prev=r}function s(e,o,r,t){return e.context=new D(r,o.indentation()+(t===!1?0:o.indentUnit),e.context),r}function u(e){return e.context.prev&&(e.context=e.context.prev),e.context.type}function k(e,o,r){return a[r.context.type](e,o,r)}function h(e,o,r,t){for(var d=t||1;d>0;d--)r.context=r.context.prev;return k(e,o,r)}function L(e){var o=e.current().toLowerCase();V.hasOwnProperty(o)?n="atom":N.hasOwnProperty(o)?n="keyword":n="variable"}var a={};return a.top=function(e,o,r){if(e=="{")return s(r,o,"block");if(e=="}"&&r.context.prev)return u(r);if(oe&&/@component/i.test(e))return s(r,o,"atComponentBlock");if(/^@(-moz-)?document$/i.test(e))return s(r,o,"documentTypes");if(/^@(media|supports|(-moz-)?document|import)$/i.test(e))return s(r,o,"atBlock");if(/^@(font-face|counter-style)/i.test(e))return r.stateArg=e,"restricted_atBlock_before";if(/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(e))return"keyframes";if(e&&e.charAt(0)=="@")return s(r,o,"at");if(e=="hash")n="builtin";else if(e=="word")n="tag";else{if(e=="variable-definition")return"maybeprop";if(e=="interpolation")return s(r,o,"interpolation");if(e==":")return"pseudo";if(g&&e=="(")return s(r,o,"parens")}return r.context.type},a.block=function(e,o,r){if(e=="word"){var t=o.current().toLowerCase();return O.hasOwnProperty(t)?(n="property","maybeprop"):F.hasOwnProperty(t)?(n=W?"string.special":"property","maybeprop"):g?(n=o.match(/^\s*:(?:\s|$)/,!1)?"property":"tag","block"):(n="error","maybeprop")}else return e=="meta"?"block":!g&&(e=="hash"||e=="qualifier")?(n="error","block"):a.top(e,o,r)},a.maybeprop=function(e,o,r){return e==":"?s(r,o,"prop"):k(e,o,r)},a.prop=function(e,o,r){if(e==";")return u(r);if(e=="{"&&g)return s(r,o,"propBlock");if(e=="}"||e=="{")return h(e,o,r);if(e=="(")return s(r,o,"parens");if(e=="hash"&&!/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(o.current()))n="error";else if(e=="word")L(o);else if(e=="interpolation")return s(r,o,"interpolation");return"prop"},a.propBlock=function(e,o,r){return e=="}"?u(r):e=="word"?(n="property","maybeprop"):r.context.type},a.parens=function(e,o,r){return e=="{"||e=="}"?h(e,o,r):e==")"?u(r):e=="("?s(r,o,"parens"):e=="interpolation"?s(r,o,"interpolation"):(e=="word"&&L(o),"parens")},a.pseudo=function(e,o,r){return e=="meta"?"pseudo":e=="word"?(n="variableName.constant",r.context.type):k(e,o,r)},a.documentTypes=function(e,o,r){return e=="word"&&b.hasOwnProperty(o.current())?(n="tag",r.context.type):a.atBlock(e,o,r)},a.atBlock=function(e,o,r){if(e=="(")return s(r,o,"atBlock_parens");if(e=="}"||e==";")return h(e,o,r);if(e=="{")return u(r)&&s(r,o,g?"block":"top");if(e=="interpolation")return s(r,o,"interpolation");if(e=="word"){var t=o.current().toLowerCase();t=="only"||t=="not"||t=="and"||t=="or"?n="keyword":G.hasOwnProperty(t)?n="attribute":J.hasOwnProperty(t)?n="property":Q.hasOwnProperty(t)?n="keyword":O.hasOwnProperty(t)?n="property":F.hasOwnProperty(t)?n=W?"string.special":"property":V.hasOwnProperty(t)?n="atom":N.hasOwnProperty(t)?n="keyword":n="error"}return r.context.type},a.atComponentBlock=function(e,o,r){return e=="}"?h(e,o,r):e=="{"?u(r)&&s(r,o,g?"block":"top",!1):(e=="word"&&(n="error"),r.context.type)},a.atBlock_parens=function(e,o,r){return e==")"?u(r):e=="{"||e=="}"?h(e,o,r,2):a.atBlock(e,o,r)},a.restricted_atBlock_before=function(e,o,r){return e=="{"?s(r,o,"restricted_atBlock"):e=="word"&&r.stateArg=="@counter-style"?(n="variable","restricted_atBlock_before"):k(e,o,r)},a.restricted_atBlock=function(e,o,r){return e=="}"?(r.stateArg=null,u(r)):e=="word"?(r.stateArg=="@font-face"&&!R.hasOwnProperty(o.current().toLowerCase())||r.stateArg=="@counter-style"&&!ee.hasOwnProperty(o.current().toLowerCase())?n="error":n="property","maybeprop"):"restricted_atBlock"},a.keyframes=function(e,o,r){return e=="word"?(n="variable","keyframes"):e=="{"?s(r,o,"top"):k(e,o,r)},a.at=function(e,o,r){return e==";"?u(r):e=="{"||e=="}"?h(e,o,r):(e=="word"?n="tag":e=="hash"&&(n="builtin"),"at")},a.interpolation=function(e,o,r){return e=="}"?u(r):e=="{"||e==";"?h(e,o,r):(e=="word"?n="variable":e!="variable"&&e!="("&&e!=")"&&(n="error"),"interpolation")},{name:i.name,startState:function(){return{tokenize:null,state:l?"block":"top",stateArg:null,context:new D(l?"block":"top",0,null)}},token:function(e,o){if(!o.tokenize&&e.eatSpace())return null;var r=(o.tokenize||ie)(e,o);return r&&typeof r=="object"&&(w=r[1],r=r[0]),n=r,w!="comment"&&(o.state=a[o.state](w,e,o)),n},indent:function(e,o,r){var t=e.context,d=o&&o.charAt(0),q=t.indent;return t.type=="prop"&&(d=="}"||d==")")&&(t=t.prev),t.prev&&(d=="}"&&(t.type=="block"||t.type=="top"||t.type=="interpolation"||t.type=="restricted_atBlock")?(t=t.prev,q=t.indent):(d==")"&&(t.type=="parens"||t.type=="atBlock_parens")||d=="{"&&(t.type=="at"||t.type=="atBlock"))&&(q=Math.max(0,t.indent-r.unit))),q},languageData:{indentOnInput:/^\s*\}$/,commentTokens:{line:re,block:{open:"/*",close:"*/"}},autocomplete:M}}}function p(i){for(var l={},m=0;m=&|~%^]/;const g={name:"cypher",startState:function(){return{tokenize:p,context:null,indent:0,col:0}},token:function(n,e){if(n.sol()&&(e.context&&e.context.align==null&&(e.context.align=!1),e.indent=n.indentation()),n.eatSpace())return null;var t=e.tokenize(n,e);if(t!=="comment"&&e.context&&e.context.align==null&&e.context.type!=="pattern"&&(e.context.align=!0),i==="(")o(e,")",n.column());else if(i==="[")o(e,"]",n.column());else if(i==="{")o(e,"}",n.column());else if(/[\]\}\)]/.test(i)){for(;e.context&&e.context.type==="pattern";)c(e);e.context&&i===e.context.type&&c(e)}else i==="."&&e.context&&e.context.type==="pattern"?c(e):/atom|string|variable/.test(t)&&e.context&&(/[\}\]]/.test(e.context.type)?o(e,"pattern",n.column()):e.context.type==="pattern"&&!e.context.align&&(e.context.align=!0,e.context.col=n.column()));return t},indent:function(n,e,t){var a=e&&e.charAt(0),r=n.context;if(/[\]\}]/.test(a))for(;r&&r.type==="pattern";)r=r.prev;var s=r&&a===r.type;return r?r.type==="keywords"?null:r.align?r.col+(s?0:1):r.indent+(s?0:t.unit):0}};export{g as cypher};
diff --git a/docs/assets/d-76ab4361.js b/docs/assets/d-76ab4361.js
new file mode 100644
index 00000000..795e106b
--- /dev/null
+++ b/docs/assets/d-76ab4361.js
@@ -0,0 +1 @@
+function c(e){for(var n={},t=e.split(" "),i=0;i!?|\/]/,o;function m(e,n){var t=e.next();if(p[t]){var i=p[t](e,n);if(i!==!1)return i}if(t=='"'||t=="'"||t=="`")return n.tokenize=z(t),n.tokenize(e,n);if(/[\[\]{}\(\),;\:\.]/.test(t))return o=t,null;if(/\d/.test(t))return e.eatWhile(/[\w\.]/),"number";if(t=="/"){if(e.eat("+"))return n.tokenize=k,k(e,n);if(e.eat("*"))return n.tokenize=y,y(e,n);if(e.eat("/"))return e.skipToEnd(),"comment"}if(h.test(t))return e.eatWhile(h),"operator";e.eatWhile(/[\w\$_\xa1-\uffff]/);var r=e.current();return v.propertyIsEnumerable(r)?(d.propertyIsEnumerable(r)&&(o="newstatement"),"keyword"):x.propertyIsEnumerable(r)?(d.propertyIsEnumerable(r)&&(o="newstatement"),"builtin"):g.propertyIsEnumerable(r)?"atom":"variable"}function z(e){return function(n,t){for(var i=!1,r,u=!1;(r=n.next())!=null;){if(r==e&&!i){u=!0;break}i=!i&&r=="\\"}return(u||!(i||_))&&(t.tokenize=null),"string"}}function y(e,n){for(var t=!1,i;i=e.next();){if(i=="/"&&t){n.tokenize=null;break}t=i=="*"}return"comment"}function k(e,n){for(var t=!1,i;i=e.next();){if(i=="/"&&t){n.tokenize=null;break}t=i=="+"}return"comment"}function b(e,n,t,i,r){this.indented=e,this.column=n,this.type=t,this.align=i,this.prev=r}function f(e,n,t){var i=e.indented;return e.context&&e.context.type=="statement"&&(i=e.context.indented),e.context=new b(i,n,t,null,e.context)}function a(e){var n=e.context.type;return(n==")"||n=="]"||n=="}")&&(e.indented=e.context.indented),e.context=e.context.prev}const E={name:"d",startState:function(e){return{tokenize:null,context:new b(-e,0,"top",!1),indented:0,startOfLine:!0}},token:function(e,n){var t=n.context;if(e.sol()&&(t.align==null&&(t.align=!1),n.indented=e.indentation(),n.startOfLine=!0),e.eatSpace())return null;o=null;var i=(n.tokenize||m)(e,n);if(i=="comment"||i=="meta")return i;if(t.align==null&&(t.align=!0),(o==";"||o==":"||o==",")&&t.type=="statement")a(n);else if(o=="{")f(n,e.column(),"}");else if(o=="[")f(n,e.column(),"]");else if(o=="(")f(n,e.column(),")");else if(o=="}"){for(;t.type=="statement";)t=a(n);for(t.type=="}"&&(t=a(n));t.type=="statement";)t=a(n)}else o==t.type?a(n):((t.type=="}"||t.type=="top")&&o!=";"||t.type=="statement"&&o=="newstatement")&&f(n,e.column(),"statement");return n.startOfLine=!1,i},indent:function(e,n,t){if(e.tokenize!=m&&e.tokenize!=null)return null;var i=e.context,r=n&&n.charAt(0);i.type=="statement"&&r=="}"&&(i=i.prev);var u=r==i.type;return i.type=="statement"?i.indented+(r=="{"?0:w||t.unit):i.align?i.column+(u?0:1):i.indented+(u?0:t.unit)},languageData:{indentOnInput:/^\s*[{}]$/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}}}};export{E as d};
diff --git a/docs/assets/diff-1bf42f34.js b/docs/assets/diff-1bf42f34.js
new file mode 100644
index 00000000..91a492b9
--- /dev/null
+++ b/docs/assets/diff-1bf42f34.js
@@ -0,0 +1 @@
+var o={"+":"inserted","-":"deleted","@":"meta"};const r={name:"diff",token:function(n){var e=n.string.search(/[\t ]+?$/);if(!n.sol()||e===0)return n.skipToEnd(),("error "+(o[n.string.charAt(0)]||"")).replace(/ $/,"");var i=o[n.peek()]||n.skipToEnd();return e===-1?n.skipToEnd():n.pos=e,i}};export{r as diff};
diff --git a/docs/assets/dockerfile-c8a8b9da.js b/docs/assets/dockerfile-c8a8b9da.js
new file mode 100644
index 00000000..51970eeb
--- /dev/null
+++ b/docs/assets/dockerfile-c8a8b9da.js
@@ -0,0 +1 @@
+import{s as o}from"./simple-mode-851e42ff.js";var e="from",s=new RegExp("^(\\s*)\\b("+e+")\\b","i"),n=["run","cmd","entrypoint","shell"],l=new RegExp("^(\\s*)("+n.join("|")+")(\\s+\\[)","i"),t="expose",x=new RegExp("^(\\s*)("+t+")(\\s+)","i"),g=["arg","from","maintainer","label","env","add","copy","volume","user","workdir","onbuild","stopsignal","healthcheck","shell"],u=[e,t].concat(n).concat(g),r="("+u.join("|")+")",a=new RegExp("^(\\s*)"+r+"(\\s*)(#.*)?$","i"),k=new RegExp("^(\\s*)"+r+"(\\s+)","i");const m=o({start:[{regex:/^\s*#.*$/,sol:!0,token:"comment"},{regex:s,token:[null,"keyword"],sol:!0,next:"from"},{regex:a,token:[null,"keyword",null,"error"],sol:!0},{regex:l,token:[null,"keyword",null],sol:!0,next:"array"},{regex:x,token:[null,"keyword",null],sol:!0,next:"expose"},{regex:k,token:[null,"keyword",null],sol:!0,next:"arguments"},{regex:/./,token:null}],from:[{regex:/\s*$/,token:null,next:"start"},{regex:/(\s*)(#.*)$/,token:[null,"error"],next:"start"},{regex:/(\s*\S+\s+)(as)/i,token:[null,"keyword"],next:"start"},{token:null,next:"start"}],single:[{regex:/(?:[^\\']|\\.)/,token:"string"},{regex:/'/,token:"string",pop:!0}],double:[{regex:/(?:[^\\"]|\\.)/,token:"string"},{regex:/"/,token:"string",pop:!0}],array:[{regex:/\]/,token:null,next:"start"},{regex:/"(?:[^\\"]|\\.)*"?/,token:"string"}],expose:[{regex:/\d+$/,token:"number",next:"start"},{regex:/[^\d]+$/,token:null,next:"start"},{regex:/\d+/,token:"number"},{regex:/[^\d]+/,token:null},{token:null,next:"start"}],arguments:[{regex:/^\s*#.*$/,sol:!0,token:"comment"},{regex:/"(?:[^\\"]|\\.)*"?$/,token:"string",next:"start"},{regex:/"/,token:"string",push:"double"},{regex:/'(?:[^\\']|\\.)*'?$/,token:"string",next:"start"},{regex:/'/,token:"string",push:"single"},{regex:/[^#"']+[\\`]$/,token:null},{regex:/[^#"']+$/,token:null,next:"start"},{regex:/[^#"']+/,token:null},{token:null,next:"start"}],languageData:{commentTokens:{line:"#"}}});export{m as dockerFile};
diff --git a/docs/assets/dtd-8d673f3f.js b/docs/assets/dtd-8d673f3f.js
new file mode 100644
index 00000000..d0b492f7
--- /dev/null
+++ b/docs/assets/dtd-8d673f3f.js
@@ -0,0 +1 @@
+var u;function r(e,n){return u=n,e}function t(e,n){var l=e.next();if(l=="<"&&e.eat("!")){if(e.eatWhile(/[\-]/))return n.tokenize=o,o(e,n);if(e.eatWhile(/[\w]/))return r("keyword","doindent")}else{if(l=="<"&&e.eat("?"))return n.tokenize=a("meta","?>"),r("meta",l);if(l=="#"&&e.eatWhile(/[\w]/))return r("atom","tag");if(l=="|")return r("keyword","separator");if(l.match(/[\(\)\[\]\-\.,\+\?>]/))return r(null,l);if(l.match(/[\[\]]/))return r("rule",l);if(l=='"'||l=="'")return n.tokenize=k(l),n.tokenize(e,n);if(e.eatWhile(/[a-zA-Z\?\+\d]/)){var i=e.current();return i.substr(i.length-1,i.length).match(/\?|\+/)!==null&&e.backUp(1),r("tag","tag")}else return l=="%"||l=="*"?r("number","number"):(e.eatWhile(/[\w\\\-_%.{,]/),r(null,null))}}function o(e,n){for(var l=0,i;(i=e.next())!=null;){if(l>=2&&i==">"){n.tokenize=t;break}l=i=="-"?l+1:0}return r("comment","comment")}function k(e){return function(n,l){for(var i=!1,c;(c=n.next())!=null;){if(c==e&&!i){l.tokenize=t;break}i=!i&&c=="\\"}return r("string","tag")}}function a(e,n){return function(l,i){for(;!l.eol();){if(l.match(n)){i.tokenize=t;break}l.next()}return e}}const f={name:"dtd",startState:function(){return{tokenize:t,baseIndent:0,stack:[]}},token:function(e,n){if(e.eatSpace())return null;var l=n.tokenize(e,n),i=n.stack[n.stack.length-1];return e.current()=="["||u==="doindent"||u=="["?n.stack.push("rule"):u==="endtag"?n.stack[n.stack.length-1]="endtag":e.current()=="]"||u=="]"||u==">"&&i=="rule"?n.stack.pop():u=="["&&n.stack.push("["),l},indent:function(e,n,l){var i=e.stack.length;return n.charAt(0)==="]"?i--:n.substr(n.length-1,n.length)===">"&&(n.substr(0,1)==="<"||u=="doindent"&&n.length>1||(u=="doindent"?i--:u==">"&&n.length>1||u=="tag"&&n!==">"||(u=="tag"&&e.stack[e.stack.length-1]=="rule"?i--:u=="tag"?i++:n===">"&&e.stack[e.stack.length-1]=="rule"&&u===">"?i--:n===">"&&e.stack[e.stack.length-1]=="rule"||(n.substr(0,1)!=="<"&&n.substr(0,1)===">"?i=i-1:n===">"||(i=i-1)))),(u==null||u=="]")&&i--),e.baseIndent+i*l.unit},languageData:{indentOnInput:/^\s*[\]>]$/}};export{f as dtd};
diff --git a/docs/assets/dylan-94e68d48.js b/docs/assets/dylan-94e68d48.js
new file mode 100644
index 00000000..58860c59
--- /dev/null
+++ b/docs/assets/dylan-94e68d48.js
@@ -0,0 +1 @@
+function p(e,i){for(var n=0;n",symbolGlobal:"\\*"+f+"\\*",symbolConstant:"\\$"+f},w={symbolKeyword:"atom",symbolClass:"tag",symbolGlobal:"variableName.standard",symbolConstant:"variableName.constant"};for(var c in a)a.hasOwnProperty(c)&&(a[c]=new RegExp("^"+a[c]));a.keyword=[/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/];var u={};u.keyword="keyword";u.definition="def";u.simpleDefinition="def";u.signalingCalls="builtin";var y={},k={};p(["keyword","definition","simpleDefinition","signalingCalls"],function(e){p(t[e],function(i){y[i]=e,k[i]=u[e]})});function d(e,i,n){return i.tokenize=n,n(e,i)}function s(e,i){var n=e.peek();if(n=="'"||n=='"')return e.next(),d(e,i,h(n,"string"));if(n=="/"){if(e.next(),e.eat("*"))return d(e,i,D);if(e.eat("/"))return e.skipToEnd(),"comment";e.backUp(1)}else if(/[+\-\d\.]/.test(n)){if(e.match(/^[+-]?[0-9]*\.[0-9]*([esdx][+-]?[0-9]+)?/i)||e.match(/^[+-]?[0-9]+([esdx][+-]?[0-9]+)/i)||e.match(/^[+-]?\d+/))return"number"}else{if(n=="#")return e.next(),n=e.peek(),n=='"'?(e.next(),d(e,i,h('"',"string"))):n=="b"?(e.next(),e.eatWhile(/[01]/),"number"):n=="x"?(e.next(),e.eatWhile(/[\da-f]/i),"number"):n=="o"?(e.next(),e.eatWhile(/[0-7]/),"number"):n=="#"?(e.next(),"punctuation"):n=="["||n=="("?(e.next(),"bracket"):e.match(/f|t|all-keys|include|key|next|rest/i)?"atom":(e.eatWhile(/[-a-zA-Z]/),"error");if(n=="~")return e.next(),n=e.peek(),n=="="?(e.next(),n=e.peek(),n=="="&&e.next(),"operator"):"operator";if(n==":"){if(e.next(),n=e.peek(),n=="=")return e.next(),"operator";if(n==":")return e.next(),"punctuation"}else{if("[](){}".indexOf(n)!=-1)return e.next(),"bracket";if(".,".indexOf(n)!=-1)return e.next(),"punctuation";if(e.match("end"))return"keyword"}}for(var l in a)if(a.hasOwnProperty(l)){var r=a[l];if(r instanceof Array&&x(r,function(o){return e.match(o)})||e.match(r))return w[l]}return/[+\-*\/^=<>&|]/.test(n)?(e.next(),"operator"):e.match("define")?"def":(e.eatWhile(/[\w\-]/),y.hasOwnProperty(e.current())?k[e.current()]:e.current().match(v)?"variable":(e.next(),"variableName.standard"))}function D(e,i){for(var n=!1,l=!1,r=0,o;o=e.next();){if(o=="/"&&n)if(r>0)r--;else{i.tokenize=s;break}else o=="*"&&l&&r++;n=o=="*",l=o=="/"}return"comment"}function h(e,i){return function(n,l){for(var r=!1,o,b=!1;(o=n.next())!=null;){if(o==e&&!r){b=!0;break}r=!r&&o=="\\"}return(b||!r)&&(l.tokenize=s),i}}const g={name:"dylan",startState:function(){return{tokenize:s,currentIndent:0}},token:function(e,i){if(e.eatSpace())return null;var n=i.tokenize(e,i);return n},languageData:{commentTokens:{block:{open:"/*",close:"*/"}}}};export{g as dylan};
diff --git a/docs/assets/ebnf-9a58f677.js b/docs/assets/ebnf-9a58f677.js
new file mode 100644
index 00000000..0824acdf
--- /dev/null
+++ b/docs/assets/ebnf-9a58f677.js
@@ -0,0 +1 @@
+var i={slash:0,parenthesis:1},n={comment:0,_string:1,characterClass:2};const l={name:"ebnf",startState:function(){return{stringType:null,commentType:null,braced:0,lhs:!0,localState:null,stack:[],inDefinition:!1}},token:function(e,c){if(e){switch(c.stack.length===0&&(e.peek()=='"'||e.peek()=="'"?(c.stringType=e.peek(),e.next(),c.stack.unshift(n._string)):e.match("/*")?(c.stack.unshift(n.comment),c.commentType=i.slash):e.match("(*")&&(c.stack.unshift(n.comment),c.commentType=i.parenthesis)),c.stack[0]){case n._string:for(;c.stack[0]===n._string&&!e.eol();)e.peek()===c.stringType?(e.next(),c.stack.shift()):e.peek()==="\\"?(e.next(),e.next()):e.match(/^.[^\\\"\']*/);return c.lhs?"property":"string";case n.comment:for(;c.stack[0]===n.comment&&!e.eol();)c.commentType===i.slash&&e.match("*/")||c.commentType===i.parenthesis&&e.match("*)")?(c.stack.shift(),c.commentType=null):e.match(/^.[^\*]*/);return"comment";case n.characterClass:for(;c.stack[0]===n.characterClass&&!e.eol();)e.match(/^[^\]\\]+/)||e.match(".")||c.stack.shift();return"operator"}var t=e.peek();switch(t){case"[":return e.next(),c.stack.unshift(n.characterClass),"bracket";case":":case"|":case";":return e.next(),"operator";case"%":if(e.match("%%"))return"header";if(e.match(/[%][A-Za-z]+/))return"keyword";if(e.match(/[%][}]/))return"bracket";break;case"/":if(e.match(/[\/][A-Za-z]+/))return"keyword";case"\\":if(e.match(/[\][a-z]+/))return"string.special";case".":if(e.match("."))return"atom";case"*":case"-":case"+":case"^":if(e.match(t))return"atom";case"$":if(e.match("$$"))return"builtin";if(e.match(/[$][0-9]+/))return"variableName.special";case"<":if(e.match(/<<[a-zA-Z_]+>>/))return"builtin"}return e.match("//")?(e.skipToEnd(),"comment"):e.match("return")?"operator":e.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)?e.match(/(?=[\(.])/)?"variable":e.match(/(?=[\s\n]*[:=])/)?"def":"variableName.special":["[","]","(",")"].indexOf(e.peek())!=-1?(e.next(),"bracket"):(e.eatSpace()||e.next(),null)}}};export{l as ebnf};
diff --git a/docs/assets/ecl-8c848bde.js b/docs/assets/ecl-8c848bde.js
new file mode 100644
index 00000000..51f4d3ab
--- /dev/null
+++ b/docs/assets/ecl-8c848bde.js
@@ -0,0 +1 @@
+function l(e){for(var n={},t=e.split(" "),r=0;r!?|\/]/,o;function p(e,n){var t=e.next();if(m[t]){var r=m[t](e,n);if(r!==!1)return r}if(t=='"'||t=="'")return n.tokenize=I(t),n.tokenize(e,n);if(/[\[\]{}\(\),;\:\.]/.test(t))return o=t,null;if(/\d/.test(t))return e.eatWhile(/[\w\.]/),"number";if(t=="/"){if(e.eat("*"))return n.tokenize=y,y(e,n);if(e.eat("/"))return e.skipToEnd(),"comment"}if(h.test(t))return e.eatWhile(h),"operator";e.eatWhile(/[\w\$_]/);var i=e.current().toLowerCase();if(g.propertyIsEnumerable(i))return s.propertyIsEnumerable(i)&&(o="newstatement"),"keyword";if(w.propertyIsEnumerable(i))return s.propertyIsEnumerable(i)&&(o="newstatement"),"variable";if(x.propertyIsEnumerable(i))return s.propertyIsEnumerable(i)&&(o="newstatement"),"modifier";if(f.propertyIsEnumerable(i))return s.propertyIsEnumerable(i)&&(o="newstatement"),"type";if(k.propertyIsEnumerable(i))return s.propertyIsEnumerable(i)&&(o="newstatement"),"builtin";for(var a=i.length-1;a>=0&&(!isNaN(i[a])||i[a]=="_");)--a;if(a>0){var d=i.substr(0,a+1);if(f.propertyIsEnumerable(d))return s.propertyIsEnumerable(d)&&(o="newstatement"),"type"}return E.propertyIsEnumerable(i)?"atom":null}function I(e){return function(n,t){for(var r=!1,i,a=!1;(i=n.next())!=null;){if(i==e&&!r){a=!0;break}r=!r&&i=="\\"}return(a||!r)&&(t.tokenize=p),"string"}}function y(e,n){for(var t=!1,r;r=e.next();){if(r=="/"&&t){n.tokenize=p;break}t=r=="*"}return"comment"}function v(e,n,t,r,i){this.indented=e,this.column=n,this.type=t,this.align=r,this.prev=i}function c(e,n,t){return e.context=new v(e.indented,n,t,null,e.context)}function u(e){var n=e.context.type;return(n==")"||n=="]"||n=="}")&&(e.indented=e.context.indented),e.context=e.context.prev}const z={name:"ecl",startState:function(e){return{tokenize:null,context:new v(-e,0,"top",!1),indented:0,startOfLine:!0}},token:function(e,n){var t=n.context;if(e.sol()&&(t.align==null&&(t.align=!1),n.indented=e.indentation(),n.startOfLine=!0),e.eatSpace())return null;o=null;var r=(n.tokenize||p)(e,n);if(r=="comment"||r=="meta")return r;if(t.align==null&&(t.align=!0),(o==";"||o==":")&&t.type=="statement")u(n);else if(o=="{")c(n,e.column(),"}");else if(o=="[")c(n,e.column(),"]");else if(o=="(")c(n,e.column(),")");else if(o=="}"){for(;t.type=="statement";)t=u(n);for(t.type=="}"&&(t=u(n));t.type=="statement";)t=u(n)}else o==t.type?u(n):(t.type=="}"||t.type=="top"||t.type=="statement"&&o=="newstatement")&&c(n,e.column(),"statement");return n.startOfLine=!1,r},indent:function(e,n,t){if(e.tokenize!=p&&e.tokenize!=null)return 0;var r=e.context,i=n&&n.charAt(0);r.type=="statement"&&i=="}"&&(r=r.prev);var a=i==r.type;return r.type=="statement"?r.indented+(i=="{"?0:t.unit):r.align?r.column+(a?0:1):r.indented+(a?0:t.unit)},languageData:{indentOnInput:/^\s*[{}]$/}};export{z as ecl};
diff --git a/docs/assets/eiffel-c812667a.js b/docs/assets/eiffel-c812667a.js
new file mode 100644
index 00000000..c12d6e07
--- /dev/null
+++ b/docs/assets/eiffel-c812667a.js
@@ -0,0 +1 @@
+function u(e){for(var r={},n=0,t=e.length;n>"]);function f(e,r,n){return n.tokenize.push(e),e(r,n)}function s(e,r){if(e.eatSpace())return null;var n=e.next();return n=='"'||n=="'"?f(p(n,"string"),e,r):n=="-"&&e.eat("-")?(e.skipToEnd(),"comment"):n==":"&&e.eat("=")?"operator":/[0-9]/.test(n)?(e.eatWhile(/[xXbBCc0-9\.]/),e.eat(/[\?\!]/),"variable"):/[a-zA-Z_0-9]/.test(n)?(e.eatWhile(/[a-zA-Z_0-9]/),e.eat(/[\?\!]/),"variable"):/[=+\-\/*^%<>~]/.test(n)?(e.eatWhile(/[=+\-\/*^%<>~]/),"operator"):null}function p(e,r,n){return function(t,o){for(var a=!1,i;(i=t.next())!=null;){if(i==e&&(n||!a)){o.tokenize.pop();break}a=!a&&i=="%"}return r}}const d={name:"eiffel",startState:function(){return{tokenize:[s]}},token:function(e,r){var n=r.tokenize[r.tokenize.length-1](e,r);if(n=="variable"){var t=e.current();n=l.propertyIsEnumerable(e.current())?"keyword":c.propertyIsEnumerable(e.current())?"operator":/^[A-Z][A-Z_0-9]*$/g.test(t)?"tag":/^0[bB][0-1]+$/g.test(t)||/^0[cC][0-7]+$/g.test(t)||/^0[xX][a-fA-F0-9]+$/g.test(t)||/^([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)$/g.test(t)||/^[0-9]+$/g.test(t)?"number":"variable"}return n},languageData:{commentTokens:{line:"--"}}};export{d as eiffel};
diff --git a/docs/assets/elm-389625db.js b/docs/assets/elm-389625db.js
new file mode 100644
index 00000000..7e57009c
--- /dev/null
+++ b/docs/assets/elm-389625db.js
@@ -0,0 +1 @@
+function a(n,t,i){return t(i),i(n,t)}var v=/[a-z]/,g=/[A-Z]/,l=/[a-zA-Z0-9_]/,f=/[0-9]/,o=/[0-9A-Fa-f]/,p=/[-&*+.\\/<>=?^|:]/,w=/[(),[\]{}]/,x=/[ \v\f]/;function r(){return function(n,t){if(n.eatWhile(x))return null;var i=n.next();if(w.test(i))return i==="{"&&n.eat("-")?a(n,t,h(1)):i==="["&&n.match("glsl|")?a(n,t,u):"builtin";if(i==="'")return a(n,t,d);if(i==='"')return n.eat('"')?n.eat('"')?a(n,t,k):"string":a(n,t,E);if(g.test(i))return n.eatWhile(l),"type";if(v.test(i)){var e=n.pos===1;return n.eatWhile(l),e?"def":"variable"}if(f.test(i)){if(i==="0"){if(n.eat(/[xX]/))return n.eatWhile(o),"number"}else n.eatWhile(f);return n.eat(".")&&n.eatWhile(f),n.eat(/[eE]/)&&(n.eat(/[-+]/),n.eatWhile(f)),"number"}return p.test(i)?i==="-"&&n.eat("-")?(n.skipToEnd(),"comment"):(n.eatWhile(p),"keyword"):i==="_"?"keyword":"error"}}function h(n){return n==0?r():function(t,i){for(;!t.eol();){var e=t.next();if(e=="{"&&t.eat("-"))++n;else if(e=="-"&&t.eat("}")&&(--n,n===0))return i(r()),"comment"}return i(h(n)),"comment"}}function k(n,t){for(;!n.eol();){var i=n.next();if(i==='"'&&n.eat('"')&&n.eat('"'))return t(r()),"string"}return"string"}function E(n,t){for(;n.skipTo('\\"');)n.next(),n.next();return n.skipTo('"')?(n.next(),t(r()),"string"):(n.skipToEnd(),t(r()),"error")}function d(n,t){for(;n.skipTo("\\'");)n.next(),n.next();return n.skipTo("'")?(n.next(),t(r()),"string"):(n.skipToEnd(),t(r()),"error")}function u(n,t){for(;!n.eol();){var i=n.next();if(i==="|"&&n.eat("]"))return t(r()),"string"}return"string"}var y={case:1,of:1,as:1,if:1,then:1,else:1,let:1,in:1,type:1,alias:1,module:1,where:1,import:1,exposing:1,port:1};const W={name:"elm",startState:function(){return{f:r()}},copyState:function(n){return{f:n.f}},token:function(n,t){var i=t.f(n,function(m){t.f=m}),e=n.current();return y.hasOwnProperty(e)?"keyword":i},languageData:{commentTokens:{line:"--"}}};export{W as elm};
diff --git a/docs/assets/erlang-72724d5c.js b/docs/assets/erlang-72724d5c.js
new file mode 100644
index 00000000..d59e853b
--- /dev/null
+++ b/docs/assets/erlang-72724d5c.js
@@ -0,0 +1 @@
+var S=["-type","-spec","-export_type","-opaque"],x=["after","begin","catch","case","cond","end","fun","if","let","of","query","receive","try","when"],z=/[\->,;]/,E=["->",";",","],T=["and","andalso","band","bnot","bor","bsl","bsr","bxor","div","not","or","orelse","rem","xor"],R=/[\+\-\*\/<>=\|:!]/,A=["=","+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-","!"],U=/[<\(\[\{]/,b=["<<","(","[","{"],Z=/[>\)\]\}]/,y=["}","]",")",">>"],m=["is_atom","is_binary","is_bitstring","is_boolean","is_float","is_function","is_integer","is_list","is_number","is_pid","is_port","is_record","is_reference","is_tuple","atom","binary","bitstring","boolean","function","integer","list","number","pid","port","record","reference","tuple"],P=["abs","adler32","adler32_combine","alive","apply","atom_to_binary","atom_to_list","binary_to_atom","binary_to_existing_atom","binary_to_list","binary_to_term","bit_size","bitstring_to_list","byte_size","check_process_code","contact_binary","crc32","crc32_combine","date","decode_packet","delete_module","disconnect_node","element","erase","exit","float","float_to_list","garbage_collect","get","get_keys","group_leader","halt","hd","integer_to_list","internal_bif","iolist_size","iolist_to_binary","is_alive","is_atom","is_binary","is_bitstring","is_boolean","is_float","is_function","is_integer","is_list","is_number","is_pid","is_port","is_process_alive","is_record","is_reference","is_tuple","length","link","list_to_atom","list_to_binary","list_to_bitstring","list_to_existing_atom","list_to_float","list_to_integer","list_to_pid","list_to_tuple","load_module","make_ref","module_loaded","monitor_node","node","node_link","node_unlink","nodes","notalive","now","open_port","pid_to_list","port_close","port_command","port_connect","port_control","pre_loaded","process_flag","process_info","processes","purge_module","put","register","registered","round","self","setelement","size","spawn","spawn_link","spawn_monitor","spawn_opt","split_binary","statistics","term_to_binary","time","throw","tl","trunc","tuple_size","tuple_to_list","unlink","unregister","whereis"],p=/[\w@Ø-ÞÀ-Öß-öø-ÿ]/,q=/[0-7]{1,3}|[bdefnrstv\\"']|\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/;function j(e,n){if(n.in_string)return n.in_string=!v(e),t(n,e,"string");if(n.in_atom)return n.in_atom=!h(e),t(n,e,"atom");if(e.eatSpace())return t(n,e,"whitespace");if(!_(n)&&e.match(/-\s*[a-zß-öø-ÿ][\wØ-ÞÀ-Öß-öø-ÿ]*/))return u(e.current(),S)?t(n,e,"type"):t(n,e,"attribute");var r=e.next();if(r=="%")return e.skipToEnd(),t(n,e,"comment");if(r==":")return t(n,e,"colon");if(r=="?")return e.eatSpace(),e.eatWhile(p),t(n,e,"macro");if(r=="#")return e.eatSpace(),e.eatWhile(p),t(n,e,"record");if(r=="$")return e.next()=="\\"&&!e.match(q)?t(n,e,"error"):t(n,e,"number");if(r==".")return t(n,e,"dot");if(r=="'"){if(!(n.in_atom=!h(e))){if(e.match(/\s*\/\s*[0-9]/,!1))return e.match(/\s*\/\s*[0-9]/,!0),t(n,e,"fun");if(e.match(/\s*\(/,!1)||e.match(/\s*:/,!1))return t(n,e,"function")}return t(n,e,"atom")}if(r=='"')return n.in_string=!v(e),t(n,e,"string");if(/[A-Z_Ø-ÞÀ-Ö]/.test(r))return e.eatWhile(p),t(n,e,"variable");if(/[a-z_ß-öø-ÿ]/.test(r)){if(e.eatWhile(p),e.match(/\s*\/\s*[0-9]/,!1))return e.match(/\s*\/\s*[0-9]/,!0),t(n,e,"fun");var i=e.current();return u(i,x)?t(n,e,"keyword"):u(i,T)?t(n,e,"operator"):e.match(/\s*\(/,!1)?u(i,P)&&(_(n).token!=":"||_(n,2).token=="erlang")?t(n,e,"builtin"):u(i,m)?t(n,e,"guard"):t(n,e,"function"):Q(e)==":"?i=="erlang"?t(n,e,"builtin"):t(n,e,"function"):u(i,["true","false"])?t(n,e,"boolean"):t(n,e,"atom")}var l=/[0-9]/,o=/[0-9a-zA-Z]/;return l.test(r)?(e.eatWhile(l),e.eat("#")?e.eatWhile(o)||e.backUp(1):e.eat(".")&&(e.eatWhile(l)?e.eat(/[eE]/)&&(e.eat(/[-+]/)?e.eatWhile(l)||e.backUp(2):e.eatWhile(l)||e.backUp(1)):e.backUp(1)),t(n,e,"number")):g(e,U,b)?t(n,e,"open_paren"):g(e,Z,y)?t(n,e,"close_paren"):k(e,z,E)?t(n,e,"separator"):k(e,R,A)?t(n,e,"operator"):t(n,e,null)}function g(e,n,r){if(e.current().length==1&&n.test(e.current())){for(e.backUp(1);n.test(e.peek());)if(e.next(),u(e.current(),r))return!0;e.backUp(e.current().length-1)}return!1}function k(e,n,r){if(e.current().length==1&&n.test(e.current())){for(;n.test(e.peek());)e.next();for(;01&&e[n].type==="fun"&&e[n-1].token==="fun")return e.slice(0,n-1);switch(e[n].token){case"}":return a(e,{g:["{"]});case"]":return a(e,{i:["["]});case")":return a(e,{i:["("]});case">>":return a(e,{i:["<<"]});case"end":return a(e,{i:["begin","case","fun","if","receive","try"]});case",":return a(e,{e:["begin","try","when","->",",","(","[","{","<<"]});case"->":return a(e,{r:["when"],m:["try","if","case","receive"]});case";":return a(e,{E:["case","fun","if","receive","try","when"]});case"catch":return a(e,{e:["try"]});case"of":return a(e,{e:["case"]});case"after":return a(e,{e:["receive","try"]});default:return e}}function a(e,n){for(var r in n)for(var i=e.length-1,l=n[r],o=i-1;-1"?u(c.token,["receive","case","if","try"])?c.column+r.unit+r.unit:c.column+r.unit:u(o.token,b)?o.column+o.token.length:(i=G(e),f(i)?i.column+r.unit:0):0}function C(e){var n=e.match(/,|[a-z]+|\}|\]|\)|>>|\|+|\(/);return f(n)&&n.index===0?n[0]:""}function F(e){var n=e.tokenStack.slice(0,-1),r=d(n,"type",["open_paren"]);return f(n[r])?n[r]:!1}function G(e){var n=e.tokenStack,r=d(n,"type",["open_paren","separator","keyword"]),i=d(n,"type",["operator"]);return f(r)&&f(i)&&r|\.\*\?]+(?=\s|$)/,token:"builtin"},{regex:/[\)><]+\S+(?=\s|$)/,token:"builtin"},{regex:/(?:[\+\-\=\/\*<>])(?=\s|$)/,token:"keyword"},{regex:/\S+/,token:"variable"},{regex:/\s+|./,token:null}],vocabulary:[{regex:/;/,token:"keyword",next:"start"},{regex:/\S+/,token:"tag"},{regex:/\s+|./,token:null}],string:[{regex:/(?:[^\\]|\\.)*?"/,token:"string",next:"start"},{regex:/.*/,token:"string"}],string2:[{regex:/^;/,token:"keyword",next:"start"},{regex:/.*/,token:"string"}],string3:[{regex:/(?:[^\\]|\\.)*?"""/,token:"string",next:"start"},{regex:/.*/,token:"string"}],stack:[{regex:/\)/,token:"bracket",next:"start"},{regex:/--/,token:"bracket"},{regex:/\S+/,token:"meta"},{regex:/\s+|./,token:null}],languageData:{name:"factor",dontIndentStates:["start","vocabulary","string","string3","stack"],commentTokens:{line:"!"}}});export{n as factor};
diff --git a/docs/assets/fcl-d5e95185.js b/docs/assets/fcl-d5e95185.js
new file mode 100644
index 00000000..45c8ec30
--- /dev/null
+++ b/docs/assets/fcl-d5e95185.js
@@ -0,0 +1 @@
+var d={term:!0,method:!0,accu:!0,rule:!0,then:!0,is:!0,and:!0,or:!0,if:!0,default:!0},f={var_input:!0,var_output:!0,fuzzify:!0,defuzzify:!0,function_block:!0,ruleblock:!0},o={end_ruleblock:!0,end_defuzzify:!0,end_function_block:!0,end_fuzzify:!0,end_var:!0},p={true:!0,false:!0,nan:!0,real:!0,min:!0,max:!0,cog:!0,cogs:!0},l=/[+\-*&^%:=<>!|\/]/;function i(e,n){var t=e.next();if(/[\d\.]/.test(t))return t=="."?e.match(/^[0-9]+([eE][\-+]?[0-9]+)?/):t=="0"?e.match(/^[xX][0-9a-fA-F]+/)||e.match(/^0[0-7]+/):e.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/),"number";if(t=="/"||t=="("){if(e.eat("*"))return n.tokenize=c,c(e,n);if(e.eat("/"))return e.skipToEnd(),"comment"}if(l.test(t))return e.eatWhile(l),"operator";e.eatWhile(/[\w\$_\xa1-\uffff]/);var r=e.current().toLowerCase();return d.propertyIsEnumerable(r)||f.propertyIsEnumerable(r)||o.propertyIsEnumerable(r)?"keyword":p.propertyIsEnumerable(r)?"atom":"variable"}function c(e,n){for(var t=!1,r;r=e.next();){if((r=="/"||r==")")&&t){n.tokenize=i;break}t=r=="*"}return"comment"}function a(e,n,t,r,u){this.indented=e,this.column=n,this.type=t,this.align=r,this.prev=u}function k(e,n,t){return e.context=new a(e.indented,n,t,null,e.context)}function v(e){if(e.context.prev){var n=e.context.type;return n=="end_block"&&(e.indented=e.context.indented),e.context=e.context.prev}}const x={name:"fcl",startState:function(e){return{tokenize:null,context:new a(-e,0,"top",!1),indented:0,startOfLine:!0}},token:function(e,n){var t=n.context;if(e.sol()&&(t.align==null&&(t.align=!1),n.indented=e.indentation(),n.startOfLine=!0),e.eatSpace())return null;var r=(n.tokenize||i)(e,n);if(r=="comment")return r;t.align==null&&(t.align=!0);var u=e.current().toLowerCase();return f.propertyIsEnumerable(u)?k(n,e.column(),"end_block"):o.propertyIsEnumerable(u)&&v(n),n.startOfLine=!1,r},indent:function(e,n,t){if(e.tokenize!=i&&e.tokenize!=null)return 0;var r=e.context,u=o.propertyIsEnumerable(n);return r.align?r.column+(u?0:1):r.indented+(u?0:t.unit)},languageData:{commentTokens:{line:"//",block:{open:"(*",close:"*)"}}}};export{x as fcl};
diff --git a/docs/assets/forth-a6c07be1.js b/docs/assets/forth-a6c07be1.js
new file mode 100644
index 00000000..a7a0bd6b
--- /dev/null
+++ b/docs/assets/forth-a6c07be1.js
@@ -0,0 +1 @@
+function t(i){var n=[];return i.split(" ").forEach(function(E){n.push({name:E})}),n}var r=t("INVERT AND OR XOR 2* 2/ LSHIFT RSHIFT 0= = 0< < > U< MIN MAX 2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP >R R> R@ + - 1+ 1- ABS NEGATE S>D * M* UM* FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2! ALIGN ALIGNED +! ALLOT CHAR [CHAR] [ ] BL FIND EXECUTE IMMEDIATE COUNT LITERAL STATE ; DOES> >BODY EVALUATE SOURCE >IN <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL FILL MOVE . CR EMIT SPACE SPACES TYPE U. .R U.R ACCEPT TRUE FALSE <> U> 0<> 0> NIP TUCK ROLL PICK 2>R 2R@ 2R> WITHIN UNUSED MARKER I J TO COMPILE, [COMPILE] SAVE-INPUT RESTORE-INPUT PAD ERASE 2LITERAL DNEGATE D- D+ D0< D0= D2* D2/ D< D= DMAX DMIN D>S DABS M+ M*/ D. D.R 2ROT DU< CATCH THROW FREE RESIZE ALLOCATE CS-PICK CS-ROLL GET-CURRENT SET-CURRENT FORTH-WORDLIST GET-ORDER SET-ORDER PREVIOUS SEARCH-WORDLIST WORDLIST FIND ALSO ONLY FORTH DEFINITIONS ORDER -TRAILING /STRING SEARCH COMPARE CMOVE CMOVE> BLANK SLITERAL"),O=t("IF ELSE THEN BEGIN WHILE REPEAT UNTIL RECURSE [IF] [ELSE] [THEN] ?DO DO LOOP +LOOP UNLOOP LEAVE EXIT AGAIN CASE OF ENDOF ENDCASE");function R(i,n){var E;for(E=i.length-1;E>=0;E--)if(i[E].name===n.toUpperCase())return i[E]}const L={name:"forth",startState:function(){return{state:"",base:10,coreWordList:r,immediateWordList:O,wordList:[]}},token:function(i,n){var E;if(i.eatSpace())return null;if(n.state===""){if(i.match(/^(\]|:NONAME)(\s|$)/i))return n.state=" compilation","builtin";if(E=i.match(/^(\:)\s+(\S+)(\s|$)+/),E)return n.wordList.push({name:E[2].toUpperCase()}),n.state=" compilation","def";if(E=i.match(/^(VARIABLE|2VARIABLE|CONSTANT|2CONSTANT|CREATE|POSTPONE|VALUE|WORD)\s+(\S+)(\s|$)+/i),E)return n.wordList.push({name:E[2].toUpperCase()}),"def";if(E=i.match(/^(\'|\[\'\])\s+(\S+)(\s|$)+/),E)return"builtin"}else{if(i.match(/^(\;|\[)(\s)/))return n.state="",i.backUp(1),"builtin";if(i.match(/^(\;|\[)($)/))return n.state="","builtin";if(i.match(/^(POSTPONE)\s+\S+(\s|$)+/))return"builtin"}if(E=i.match(/^(\S+)(\s+|$)/),E)return R(n.wordList,E[1])!==void 0?"variable":E[1]==="\\"?(i.skipToEnd(),"comment"):R(n.coreWordList,E[1])!==void 0?"builtin":R(n.immediateWordList,E[1])!==void 0?"keyword":E[1]==="("?(i.eatWhile(function(e){return e!==")"}),i.eat(")"),"comment"):E[1]===".("?(i.eatWhile(function(e){return e!==")"}),i.eat(")"),"string"):E[1]==='S"'||E[1]==='."'||E[1]==='C"'?(i.eatWhile(function(e){return e!=='"'}),i.eat('"'),"string"):E[1]-68719476735?"number":"atom"}};export{L as forth};
diff --git a/docs/assets/fortran-b746f455.js b/docs/assets/fortran-b746f455.js
new file mode 100644
index 00000000..ef7d7050
--- /dev/null
+++ b/docs/assets/fortran-b746f455.js
@@ -0,0 +1 @@
+function r(t){for(var n={},e=0;e\/\:]/,_=/^\.(and|or|eq|lt|le|gt|ge|ne|not|eqv|neqv)\./i;function u(t,n){if(t.match(_))return"operator";var e=t.next();if(e=="!")return t.skipToEnd(),"comment";if(e=='"'||e=="'")return n.tokenize=m(e),n.tokenize(t,n);if(/[\[\]\(\),]/.test(e))return null;if(/\d/.test(e))return t.eatWhile(/[\w\.]/),"number";if(c.test(e))return t.eatWhile(c),"operator";t.eatWhile(/[\w\$_]/);var i=t.current().toLowerCase();return l.hasOwnProperty(i)?"keyword":s.hasOwnProperty(i)||d.hasOwnProperty(i)?"builtin":"variable"}function m(t){return function(n,e){for(var i=!1,a,o=!1;(a=n.next())!=null;){if(a==t&&!i){o=!0;break}i=!i&&a=="\\"}return(o||!i)&&(e.tokenize=null),"string"}}const p={name:"fortran",startState:function(){return{tokenize:null}},token:function(t,n){if(t.eatSpace())return null;var e=(n.tokenize||u)(t,n);return e=="comment"||e=="meta",e}};export{p as fortran};
diff --git a/docs/assets/gas-a519128b.js b/docs/assets/gas-a519128b.js
new file mode 100644
index 00000000..d9ffcb72
--- /dev/null
+++ b/docs/assets/gas-a519128b.js
@@ -0,0 +1 @@
+function v(r){var u=[],b="",o={".abort":"builtin",".align":"builtin",".altmacro":"builtin",".ascii":"builtin",".asciz":"builtin",".balign":"builtin",".balignw":"builtin",".balignl":"builtin",".bundle_align_mode":"builtin",".bundle_lock":"builtin",".bundle_unlock":"builtin",".byte":"builtin",".cfi_startproc":"builtin",".comm":"builtin",".data":"builtin",".def":"builtin",".desc":"builtin",".dim":"builtin",".double":"builtin",".eject":"builtin",".else":"builtin",".elseif":"builtin",".end":"builtin",".endef":"builtin",".endfunc":"builtin",".endif":"builtin",".equ":"builtin",".equiv":"builtin",".eqv":"builtin",".err":"builtin",".error":"builtin",".exitm":"builtin",".extern":"builtin",".fail":"builtin",".file":"builtin",".fill":"builtin",".float":"builtin",".func":"builtin",".global":"builtin",".gnu_attribute":"builtin",".hidden":"builtin",".hword":"builtin",".ident":"builtin",".if":"builtin",".incbin":"builtin",".include":"builtin",".int":"builtin",".internal":"builtin",".irp":"builtin",".irpc":"builtin",".lcomm":"builtin",".lflags":"builtin",".line":"builtin",".linkonce":"builtin",".list":"builtin",".ln":"builtin",".loc":"builtin",".loc_mark_labels":"builtin",".local":"builtin",".long":"builtin",".macro":"builtin",".mri":"builtin",".noaltmacro":"builtin",".nolist":"builtin",".octa":"builtin",".offset":"builtin",".org":"builtin",".p2align":"builtin",".popsection":"builtin",".previous":"builtin",".print":"builtin",".protected":"builtin",".psize":"builtin",".purgem":"builtin",".pushsection":"builtin",".quad":"builtin",".reloc":"builtin",".rept":"builtin",".sbttl":"builtin",".scl":"builtin",".section":"builtin",".set":"builtin",".short":"builtin",".single":"builtin",".size":"builtin",".skip":"builtin",".sleb128":"builtin",".space":"builtin",".stab":"builtin",".string":"builtin",".struct":"builtin",".subsection":"builtin",".symver":"builtin",".tag":"builtin",".text":"builtin",".title":"builtin",".type":"builtin",".uleb128":"builtin",".val":"builtin",".version":"builtin",".vtable_entry":"builtin",".vtable_inherit":"builtin",".warning":"builtin",".weak":"builtin",".weakref":"builtin",".word":"builtin"},i={};function p(){b="#",i.al="variable",i.ah="variable",i.ax="variable",i.eax="variableName.special",i.rax="variableName.special",i.bl="variable",i.bh="variable",i.bx="variable",i.ebx="variableName.special",i.rbx="variableName.special",i.cl="variable",i.ch="variable",i.cx="variable",i.ecx="variableName.special",i.rcx="variableName.special",i.dl="variable",i.dh="variable",i.dx="variable",i.edx="variableName.special",i.rdx="variableName.special",i.si="variable",i.esi="variableName.special",i.rsi="variableName.special",i.di="variable",i.edi="variableName.special",i.rdi="variableName.special",i.sp="variable",i.esp="variableName.special",i.rsp="variableName.special",i.bp="variable",i.ebp="variableName.special",i.rbp="variableName.special",i.ip="variable",i.eip="variableName.special",i.rip="variableName.special",i.cs="keyword",i.ds="keyword",i.ss="keyword",i.es="keyword",i.fs="keyword",i.gs="keyword"}function f(){b="@",o.syntax="builtin",i.r0="variable",i.r1="variable",i.r2="variable",i.r3="variable",i.r4="variable",i.r5="variable",i.r6="variable",i.r7="variable",i.r8="variable",i.r9="variable",i.r10="variable",i.r11="variable",i.r12="variable",i.sp="variableName.special",i.lr="variableName.special",i.pc="variableName.special",i.r13=i.sp,i.r14=i.lr,i.r15=i.pc,u.push(function(l,n){if(l==="#")return n.eatWhile(/\w/),"number"})}r==="x86"?p():(r==="arm"||r==="armv6")&&f();function d(l,n){for(var e=!1,a;(a=l.next())!=null;){if(a===n&&!e)return!1;e=!e&&a==="\\"}return e}function s(l,n){for(var e=!1,a;(a=l.next())!=null;){if(a==="/"&&e){n.tokenize=null;break}e=a==="*"}return"comment"}return{name:"gas",startState:function(){return{tokenize:null}},token:function(l,n){if(n.tokenize)return n.tokenize(l,n);if(l.eatSpace())return null;var e,a,t=l.next();if(t==="/"&&l.eat("*"))return n.tokenize=s,s(l,n);if(t===b)return l.skipToEnd(),"comment";if(t==='"')return d(l,'"'),"string";if(t===".")return l.eatWhile(/\w/),a=l.current().toLowerCase(),e=o[a],e||null;if(t==="=")return l.eatWhile(/\w/),"tag";if(t==="{"||t==="}")return"bracket";if(/\d/.test(t))return t==="0"&&l.eat("x")?(l.eatWhile(/[0-9a-fA-F]/),"number"):(l.eatWhile(/\d/),"number");if(/\w/.test(t))return l.eatWhile(/\w/),l.eat(":")?"tag":(a=l.current().toLowerCase(),e=i[a],e||null);for(var c=0;c]*>?/)?"variable":(n.next(),n.eatWhile(/[^@"<#]/),null)}};export{a as gherkin};
diff --git a/docs/assets/go-8a088acb.js b/docs/assets/go-8a088acb.js
new file mode 100644
index 00000000..cacb8014
--- /dev/null
+++ b/docs/assets/go-8a088acb.js
@@ -0,0 +1 @@
+var h={break:!0,case:!0,chan:!0,const:!0,continue:!0,default:!0,defer:!0,else:!0,fallthrough:!0,for:!0,func:!0,go:!0,goto:!0,if:!0,import:!0,interface:!0,map:!0,package:!0,range:!0,return:!0,select:!0,struct:!0,switch:!0,type:!0,var:!0,bool:!0,byte:!0,complex64:!0,complex128:!0,float32:!0,float64:!0,int8:!0,int16:!0,int32:!0,int64:!0,string:!0,uint8:!0,uint16:!0,uint32:!0,uint64:!0,int:!0,uint:!0,uintptr:!0,error:!0,rune:!0,any:!0,comparable:!0},k={true:!0,false:!0,iota:!0,nil:!0,append:!0,cap:!0,close:!0,complex:!0,copy:!0,delete:!0,imag:!0,len:!0,make:!0,new:!0,panic:!0,print:!0,println:!0,real:!0,recover:!0},f=/[+\-*&^%:=<>!|\/]/,u;function l(e,t){var n=e.next();if(n=='"'||n=="'"||n=="`")return t.tokenize=x(n),t.tokenize(e,t);if(/[\d\.]/.test(n))return n=="."?e.match(/^[0-9]+([eE][\-+]?[0-9]+)?/):n=="0"?e.match(/^[xX][0-9a-fA-F]+/)||e.match(/^0[0-7]+/):e.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/),"number";if(/[\[\]{}\(\),;\:\.]/.test(n))return u=n,null;if(n=="/"){if(e.eat("*"))return t.tokenize=a,a(e,t);if(e.eat("/"))return e.skipToEnd(),"comment"}if(f.test(n))return e.eatWhile(f),"operator";e.eatWhile(/[\w\$_\xa1-\uffff]/);var r=e.current();return h.propertyIsEnumerable(r)?((r=="case"||r=="default")&&(u="case"),"keyword"):k.propertyIsEnumerable(r)?"atom":"variable"}function x(e){return function(t,n){for(var r=!1,i,o=!1;(i=t.next())!=null;){if(i==e&&!r){o=!0;break}r=!r&&e!="`"&&i=="\\"}return(o||!(r||e=="`"))&&(n.tokenize=l),"string"}}function a(e,t){for(var n=!1,r;r=e.next();){if(r=="/"&&n){t.tokenize=l;break}n=r=="*"}return"comment"}function d(e,t,n,r,i){this.indented=e,this.column=t,this.type=n,this.align=r,this.prev=i}function c(e,t,n){return e.context=new d(e.indented,t,n,null,e.context)}function p(e){if(e.context.prev){var t=e.context.type;return(t==")"||t=="]"||t=="}")&&(e.indented=e.context.indented),e.context=e.context.prev}}const s={name:"go",startState:function(e){return{tokenize:null,context:new d(-e,0,"top",!1),indented:0,startOfLine:!0}},token:function(e,t){var n=t.context;if(e.sol()&&(n.align==null&&(n.align=!1),t.indented=e.indentation(),t.startOfLine=!0,n.type=="case"&&(n.type="}")),e.eatSpace())return null;u=null;var r=(t.tokenize||l)(e,t);return r=="comment"||(n.align==null&&(n.align=!0),u=="{"?c(t,e.column(),"}"):u=="["?c(t,e.column(),"]"):u=="("?c(t,e.column(),")"):u=="case"?n.type="case":(u=="}"&&n.type=="}"||u==n.type)&&p(t),t.startOfLine=!1),r},indent:function(e,t,n){if(e.tokenize!=l&&e.tokenize!=null)return null;var r=e.context,i=t&&t.charAt(0);if(r.type=="case"&&/^(?:case|default)\b/.test(t))return r.indented;var o=i==r.type;return r.align?r.column+(o?0:1):r.indented+(o?0:n.unit)},languageData:{indentOnInput:/^\s([{}]|case |default\s*:)$/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}}}};export{s as go};
diff --git a/docs/assets/groovy-4592a472.js b/docs/assets/groovy-4592a472.js
new file mode 100644
index 00000000..4e3c129c
--- /dev/null
+++ b/docs/assets/groovy-4592a472.js
@@ -0,0 +1 @@
+function a(e){for(var n={},t=e.split(" "),i=0;i"))return r="->",null;if(/[+\-*&%=<>!?|\/~]/.test(t))return e.eatWhile(/[+\-*&%=<>|~]/),"operator";if(e.eatWhile(/[\w\$_]/),t=="@")return e.eatWhile(/[\w\$_\.]/),"meta";if(n.lastToken==".")return"property";if(e.eat(":"))return r="proplabel","property";var i=e.current();return z.propertyIsEnumerable(i)?"atom":b.propertyIsEnumerable(i)?(g.propertyIsEnumerable(i)?r="newstatement":x.propertyIsEnumerable(i)&&(r="standalone"),"keyword"):"variable"}k.isBase=!0;function y(e,n,t){var i=!1;if(e!="/"&&n.eat(e))if(n.eat(e))i=!0;else return"string";function o(l,d){for(var f=!1,c,s=!i;(c=l.next())!=null;){if(c==e&&!f){if(!i)break;if(l.match(e+e)){s=!0;break}}if(e=='"'&&c=="$"&&!f){if(l.eat("{"))return d.tokenize.push(m()),"string";if(l.match(/^\w/,!1))return d.tokenize.push(E),"string"}f=!f&&c=="\\"}return s&&d.tokenize.pop(),"string"}return t.tokenize.push(o),o(n,t)}function m(){var e=1;function n(t,i){if(t.peek()=="}"){if(e--,e==0)return i.tokenize.pop(),i.tokenize[i.tokenize.length-1](t,i)}else t.peek()=="{"&&e++;return k(t,i)}return n.isBase=!0,n}function E(e,n){var t=e.match(/^(\.|[\w\$_]+)/);return t?t[0]=="."?null:"variable":(n.tokenize.pop(),n.tokenize[n.tokenize.length-1](e,n))}function v(e,n){for(var t=!1,i;i=e.next();){if(i=="/"&&t){n.tokenize.pop();break}t=i=="*"}return"comment"}function h(e,n){return!e||e=="operator"||e=="->"||/[\.\[\{\(,;:]/.test(e)||e=="newstatement"||e=="keyword"||e=="proplabel"||e=="standalone"&&!n}function w(e,n,t,i,o){this.indented=e,this.column=n,this.type=t,this.align=i,this.prev=o}function p(e,n,t){return e.context=new w(e.indented,n,t,null,e.context)}function u(e){var n=e.context.type;return(n==")"||n=="]"||n=="}")&&(e.indented=e.context.indented),e.context=e.context.prev}const T={name:"groovy",startState:function(e){return{tokenize:[k],context:new w(-e,0,"top",!1),indented:0,startOfLine:!0,lastToken:null}},token:function(e,n){var t=n.context;if(e.sol()&&(t.align==null&&(t.align=!1),n.indented=e.indentation(),n.startOfLine=!0,t.type=="statement"&&!h(n.lastToken,!0)&&(u(n),t=n.context)),e.eatSpace())return null;r=null;var i=n.tokenize[n.tokenize.length-1](e,n);if(i=="comment")return i;if(t.align==null&&(t.align=!0),(r==";"||r==":")&&t.type=="statement")u(n);else if(r=="->"&&t.type=="statement"&&t.prev.type=="}")u(n),n.context.align=!1;else if(r=="{")p(n,e.column(),"}");else if(r=="[")p(n,e.column(),"]");else if(r=="(")p(n,e.column(),")");else if(r=="}"){for(;t.type=="statement";)t=u(n);for(t.type=="}"&&(t=u(n));t.type=="statement";)t=u(n)}else r==t.type?u(n):(t.type=="}"||t.type=="top"||t.type=="statement"&&r=="newstatement")&&p(n,e.column(),"statement");return n.startOfLine=!1,n.lastToken=r||i,i},indent:function(e,n,t){if(!e.tokenize[e.tokenize.length-1].isBase)return null;var i=n&&n.charAt(0),o=e.context;o.type=="statement"&&!h(e.lastToken,!0)&&(o=o.prev);var l=i==o.type;return o.type=="statement"?o.indented+(i=="{"?0:t.unit):o.align?o.column+(l?0:1):o.indented+(l?0:t.unit)},languageData:{indentOnInput:/^\s*[{}]$/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}},closeBrackets:{brackets:["(","[","{","'",'"',"'''",'"""']}}};export{T as groovy};
diff --git a/docs/assets/haskell-b620645c.js b/docs/assets/haskell-b620645c.js
new file mode 100644
index 00000000..d393bcef
--- /dev/null
+++ b/docs/assets/haskell-b620645c.js
@@ -0,0 +1 @@
+function f(e,n,t){return n(t),t(e,n)}var g=/[a-z_]/,c=/[A-Z]/,l=/\d/,v=/[0-9A-Fa-f]/,w=/[0-7]/,d=/[a-z_A-Z0-9'\xa1-\uffff]/,o=/[-!#$%&*+.\/<=>?@\\^|~:]/,E=/[(),;[\]`{}]/,h=/[ \t\v\f]/;function i(e,n){if(e.eatWhile(h))return null;var t=e.next();if(E.test(t)){if(t=="{"&&e.eat("-")){var r="comment";return e.eat("#")&&(r="meta"),f(e,n,s(r,1))}return null}if(t=="'")return e.eat("\\"),e.next(),e.eat("'")?"string":"error";if(t=='"')return f(e,n,p);if(c.test(t))return e.eatWhile(d),e.eat(".")?"qualifier":"type";if(g.test(t))return e.eatWhile(d),"variable";if(l.test(t)){if(t=="0"){if(e.eat(/[xX]/))return e.eatWhile(v),"integer";if(e.eat(/[oO]/))return e.eatWhile(w),"number"}e.eatWhile(l);var r="number";return e.match(/^\.\d+/)&&(r="number"),e.eat(/[eE]/)&&(r="number",e.eat(/[-+]/),e.eatWhile(l)),r}return t=="."&&e.eat(".")?"keyword":o.test(t)?t=="-"&&e.eat(/-/)&&(e.eatWhile(/-/),!e.eat(o))?(e.skipToEnd(),"comment"):(e.eatWhile(o),"variable"):"error"}function s(e,n){return n==0?i:function(t,r){for(var a=n;!t.eol();){var u=t.next();if(u=="{"&&t.eat("-"))++a;else if(u=="-"&&t.eat("}")&&(--a,a==0))return r(i),e}return r(s(e,a)),e}}function p(e,n){for(;!e.eol();){var t=e.next();if(t=='"')return n(i),"string";if(t=="\\"){if(e.eol()||e.eat(h))return n(x),"string";e.eat("&")||e.next()}}return n(i),"error"}function x(e,n){return e.eat("\\")?f(e,n,p):(e.next(),n(i),"error")}var m=function(){var e={};function n(t){return function(){for(var r=0;r","@","~","=>"),n("builtin")("!!","$!","$","&&","+","++","-",".","/","/=","<","<*","<=","<$>","<*>","=<<","==",">",">=",">>",">>=","^","^^","||","*","*>","**"),n("builtin")("Applicative","Bool","Bounded","Char","Double","EQ","Either","Enum","Eq","False","FilePath","Float","Floating","Fractional","Functor","GT","IO","IOError","Int","Integer","Integral","Just","LT","Left","Maybe","Monad","Nothing","Num","Ord","Ordering","Rational","Read","ReadS","Real","RealFloat","RealFrac","Right","Show","ShowS","String","True"),n("builtin")("abs","acos","acosh","all","and","any","appendFile","asTypeOf","asin","asinh","atan","atan2","atanh","break","catch","ceiling","compare","concat","concatMap","const","cos","cosh","curry","cycle","decodeFloat","div","divMod","drop","dropWhile","either","elem","encodeFloat","enumFrom","enumFromThen","enumFromThenTo","enumFromTo","error","even","exp","exponent","fail","filter","flip","floatDigits","floatRadix","floatRange","floor","fmap","foldl","foldl1","foldr","foldr1","fromEnum","fromInteger","fromIntegral","fromRational","fst","gcd","getChar","getContents","getLine","head","id","init","interact","ioError","isDenormalized","isIEEE","isInfinite","isNaN","isNegativeZero","iterate","last","lcm","length","lex","lines","log","logBase","lookup","map","mapM","mapM_","max","maxBound","maximum","maybe","min","minBound","minimum","mod","negate","not","notElem","null","odd","or","otherwise","pi","pred","print","product","properFraction","pure","putChar","putStr","putStrLn","quot","quotRem","read","readFile","readIO","readList","readLn","readParen","reads","readsPrec","realToFrac","recip","rem","repeat","replicate","return","reverse","round","scaleFloat","scanl","scanl1","scanr","scanr1","seq","sequence","sequence_","show","showChar","showList","showParen","showString","shows","showsPrec","significand","signum","sin","sinh","snd","span","splitAt","sqrt","subtract","succ","sum","tail","take","takeWhile","tan","tanh","toEnum","toInteger","toRational","truncate","uncurry","undefined","unlines","until","unwords","unzip","unzip3","userError","words","writeFile","zip","zip3","zipWith","zipWith3"),e}();const F={name:"haskell",startState:function(){return{f:i}},copyState:function(e){return{f:e.f}},token:function(e,n){var t=n.f(e,function(a){n.f=a}),r=e.current();return m.hasOwnProperty(r)?m[r]:t},languageData:{commentTokens:{line:"--",block:{open:"{-",close:"-}"}}}};export{F as haskell};
diff --git a/docs/assets/haxe-7215664e.js b/docs/assets/haxe-7215664e.js
new file mode 100644
index 00000000..3524b994
--- /dev/null
+++ b/docs/assets/haxe-7215664e.js
@@ -0,0 +1 @@
+function o(e){return{type:e,style:"keyword"}}var P=o("keyword a"),W=o("keyword b"),g=o("keyword c"),K=o("operator"),z={type:"atom",style:"atom"},y={type:"attribute",style:"attribute"},c=o("typedef"),B={if:P,while:P,else:W,do:W,try:W,return:g,break:g,continue:g,new:g,throw:g,var:o("var"),inline:y,static:y,using:o("import"),public:y,private:y,cast:o("cast"),import:o("import"),macro:o("macro"),function:o("function"),catch:o("catch"),untyped:o("untyped"),callback:o("cb"),for:o("for"),switch:o("switch"),case:o("case"),default:o("default"),in:K,never:o("property_access"),trace:o("trace"),class:c,abstract:c,enum:c,interface:c,typedef:c,extends:c,implements:c,dynamic:c,true:z,false:z,null:z},E=/[+\-*&%=<>!?|]/;function I(e,r,n){return r.tokenize=n,n(e,r)}function L(e,r){for(var n=!1,i;(i=e.next())!=null;){if(i==r&&!n)return!0;n=!n&&i=="\\"}}var c,N;function p(e,r,n){return c=e,N=n,r}function A(e,r){var n=e.next();if(n=='"'||n=="'")return I(e,r,M(n));if(/[\[\]{}\(\),;\:\.]/.test(n))return p(n);if(n=="0"&&e.eat(/x/i))return e.eatWhile(/[\da-f]/i),p("number","number");if(/\d/.test(n)||n=="-"&&e.eat(/\d/))return e.match(/^\d*(?:\.\d*(?!\.))?(?:[eE][+\-]?\d+)?/),p("number","number");if(r.reAllowed&&n=="~"&&e.eat(/\//))return L(e,"/"),e.eatWhile(/[gimsu]/),p("regexp","string.special");if(n=="/")return e.eat("*")?I(e,r,Q):e.eat("/")?(e.skipToEnd(),p("comment","comment")):(e.eatWhile(E),p("operator",null,e.current()));if(n=="#")return e.skipToEnd(),p("conditional","meta");if(n=="@")return e.eat(/:/),e.eatWhile(/[\w_]/),p("metadata","meta");if(E.test(n))return e.eatWhile(E),p("operator",null,e.current());var i;if(/[A-Z]/.test(n))return e.eatWhile(/[\w_<>]/),i=e.current(),p("type","type",i);e.eatWhile(/[\w_]/);var i=e.current(),u=B.propertyIsEnumerable(i)&&B[i];return u&&r.kwAllowed?p(u.type,u.style,i):p("variable","variable",i)}function M(e){return function(r,n){return L(r,e)&&(n.tokenize=A),p("string","string")}}function Q(e,r){for(var n=!1,i;i=e.next();){if(i=="/"&&n){r.tokenize=A;break}n=i=="*"}return p("comment","comment")}var $={atom:!0,number:!0,variable:!0,string:!0,regexp:!0};function j(e,r,n,i,u,s){this.indented=e,this.column=r,this.type=n,this.prev=u,this.info=s,i!=null&&(this.align=i)}function R(e,r){for(var n=e.localVars;n;n=n.next)if(n.name==r)return!0}function X(e,r,n,i,u){var s=e.cc;for(a.state=e,a.stream=u,a.marked=null,a.cc=s,e.lexical.hasOwnProperty("align")||(e.lexical.align=!0);;){var k=s.length?s.pop():x;if(k(n,i)){for(;s.length&&s[s.length-1].lex;)s.pop()();return a.marked?a.marked:n=="variable"&&R(e,i)?"variableName.local":n=="variable"&&Y(e,i)?"variableName.special":r}}}function Y(e,r){if(/[a-z]/.test(r.charAt(0)))return!1;for(var n=e.importedtypes.length,i=0;i=0;e--)a.cc.push(arguments[e])}function t(){return b.apply(null,arguments),!0}function H(e,r){for(var n=r;n;n=n.next)if(n.name==e)return!0;return!1}function S(e){var r=a.state;if(r.context){if(a.marked="def",H(e,r.localVars))return;r.localVars={name:e,next:r.localVars}}else if(r.globalVars){if(H(e,r.globalVars))return;r.globalVars={name:e,next:r.globalVars}}}var ee={name:"this",next:null};function D(){a.state.context||(a.state.localVars=ee),a.state.context={prev:a.state.context,vars:a.state.localVars}}function V(){a.state.localVars=a.state.context.vars,a.state.context=a.state.context.prev}V.lex=!0;function l(e,r){var n=function(){var i=a.state;i.lexical=new j(i.indented,a.stream.column(),e,null,i.lexical,r)};return n.lex=!0,n}function f(){var e=a.state;e.lexical.prev&&(e.lexical.type==")"&&(e.indented=e.lexical.indented),e.lexical=e.lexical.prev)}f.lex=!0;function d(e){function r(n){return n==e?t():e==";"?b():t(r)}return r}function x(e){return e=="@"?t(Z):e=="var"?t(l("vardef"),C,d(";"),f):e=="keyword a"?t(l("form"),h,x,f):e=="keyword b"?t(l("form"),x,f):e=="{"?t(l("}"),D,_,f,V):e==";"?t():e=="attribute"?t(U):e=="function"?t(w):e=="for"?t(l("form"),d("("),l(")"),ae,d(")"),f,x,f):e=="variable"?t(l("stat"),te):e=="switch"?t(l("form"),h,l("}","switch"),d("{"),_,f,f):e=="case"?t(h,d(":")):e=="default"?t(d(":")):e=="catch"?t(l("form"),D,d("("),J,d(")"),x,f,V):e=="import"?t(q,d(";")):e=="typedef"?t(ne):b(l("stat"),h,d(";"),f)}function h(e){return $.hasOwnProperty(e)||e=="type"?t(v):e=="function"?t(w):e=="keyword c"?t(O):e=="("?t(l(")"),O,d(")"),f,v):e=="operator"?t(h):e=="["?t(l("]"),m(O,"]"),f,v):e=="{"?t(l("}"),m(ue,"}"),f,v):t()}function O(e){return e.match(/[;\}\)\],]/)?b():b(h)}function v(e,r){if(e=="operator"&&/\+\+|--/.test(r))return t(v);if(e=="operator"||e==":")return t(h);if(e!=";"){if(e=="(")return t(l(")"),m(h,")"),f,v);if(e==".")return t(ie,v);if(e=="[")return t(l("]"),h,d("]"),f,v)}}function U(e){if(e=="attribute")return t(U);if(e=="function")return t(w);if(e=="var")return t(C)}function Z(e){if(e==":"||e=="variable")return t(Z);if(e=="(")return t(l(")"),m(re,")"),f,x)}function re(e){if(e=="variable")return t()}function q(e,r){if(e=="variable"&&/[A-Z]/.test(r.charAt(0)))return F(r),t();if(e=="variable"||e=="property"||e=="."||r=="*")return t(q)}function ne(e,r){if(e=="variable"&&/[A-Z]/.test(r.charAt(0)))return F(r),t();if(e=="type"&&/[A-Z]/.test(r.charAt(0)))return t()}function te(e){return e==":"?t(f,x):b(v,d(";"),f)}function ie(e){if(e=="variable")return a.marked="property",t()}function ue(e){if(e=="variable"&&(a.marked="property"),$.hasOwnProperty(e))return t(d(":"),h)}function m(e,r){function n(i){return i==","?t(e,n):i==r?t():t(d(r))}return function(i){return i==r?t():b(e,n)}}function _(e){return e=="}"?t():b(x,_)}function C(e,r){return e=="variable"?(S(r),t(T,G)):t()}function G(e,r){if(r=="=")return t(h,G);if(e==",")return t(C)}function ae(e,r){return e=="variable"?(S(r),t(fe,h)):b()}function fe(e,r){if(r=="in")return t()}function w(e,r){if(e=="variable"||e=="type")return S(r),t(w);if(r=="new")return t(w);if(e=="(")return t(l(")"),D,m(J,")"),f,T,x,V)}function T(e){if(e==":")return t(oe)}function oe(e){if(e=="type"||e=="variable")return t();if(e=="{")return t(l("}"),m(le,"}"),f)}function le(e){if(e=="variable")return t(T)}function J(e,r){if(e=="variable")return S(r),t(T)}const ce={name:"haxe",startState:function(e){var r=["Int","Float","String","Void","Std","Bool","Dynamic","Array"],n={tokenize:A,reAllowed:!0,kwAllowed:!0,cc:[],lexical:new j(-e,0,"block",!1),importedtypes:r,context:null,indented:0};return n},token:function(e,r){if(e.sol()&&(r.lexical.hasOwnProperty("align")||(r.lexical.align=!1),r.indented=e.indentation()),e.eatSpace())return null;var n=r.tokenize(e,r);return c=="comment"?n:(r.reAllowed=!!(c=="operator"||c=="keyword c"||c.match(/^[\[{}\(,;:]$/)),r.kwAllowed=c!=".",X(r,n,c,N,e))},indent:function(e,r,n){if(e.tokenize!=A)return 0;var i=r&&r.charAt(0),u=e.lexical;u.type=="stat"&&i=="}"&&(u=u.prev);var s=u.type,k=i==s;return s=="vardef"?u.indented+4:s=="form"&&i=="{"?u.indented:s=="stat"||s=="form"?u.indented+n.unit:u.info=="switch"&&!k?u.indented+(/^(?:case|default)\b/.test(r)?n.unit:2*n.unit):u.align?u.column+(k?0:1):u.indented+(k?0:n.unit)},languageData:{indentOnInput:/^\s*[{}]$/,commentTokens:{line:"//",block:{open:"/*",close:"*/"}}}},se={name:"hxml",startState:function(){return{define:!1,inString:!1}},token:function(e,r){var u=e.peek(),n=e.sol();if(u=="#")return e.skipToEnd(),"comment";if(n&&u=="-"){var i="variable-2";return e.eat(/-/),e.peek()=="-"&&(e.eat(/-/),i="keyword a"),e.peek()=="D"&&(e.eat(/[D]/),i="keyword c",r.define=!0),e.eatWhile(/[A-Z]/i),i}var u=e.peek();return r.inString==!1&&u=="'"&&(r.inString=!0,e.next()),r.inString==!0?(e.skipTo("'")||e.skipToEnd(),e.peek()=="'"&&(e.next(),r.inString=!1),"string"):(e.next(),null)},languageData:{commentTokens:{line:"#"}}};export{ce as haxe,se as hxml};
diff --git a/docs/assets/http-e091c18d.js b/docs/assets/http-e091c18d.js
new file mode 100644
index 00000000..7b06438b
--- /dev/null
+++ b/docs/assets/http-e091c18d.js
@@ -0,0 +1 @@
+function u(r,n){return r.skipToEnd(),n.cur=t,"error"}function i(r,n){return r.match(/^HTTP\/\d\.\d/)?(n.cur=f,"keyword"):r.match(/^[A-Z]+/)&&/[ \t]/.test(r.peek())?(n.cur=d,"keyword"):u(r,n)}function f(r,n){var e=r.match(/^\d+/);if(!e)return u(r,n);n.cur=l;var o=Number(e[0]);return o>=100&&o<400?"atom":"error"}function l(r,n){return r.skipToEnd(),n.cur=t,null}function d(r,n){return r.eatWhile(/\S/),n.cur=s,"string.special"}function s(r,n){return r.match(/^HTTP\/\d\.\d$/)?(n.cur=t,"keyword"):u(r,n)}function t(r){return r.sol()&&!r.eat(/[ \t]/)?r.match(/^.*?:/)?"atom":(r.skipToEnd(),"error"):(r.skipToEnd(),"string")}function c(r){return r.skipToEnd(),null}const p={name:"http",token:function(r,n){var e=n.cur;return e!=t&&e!=c&&r.eatSpace()?null:e(r,n)},blankLine:function(r){r.cur=c},startState:function(){return{cur:i}}};export{p as http};
diff --git a/docs/assets/idl-91cb7788.js b/docs/assets/idl-91cb7788.js
new file mode 100644
index 00000000..a779fbe8
--- /dev/null
+++ b/docs/assets/idl-91cb7788.js
@@ -0,0 +1 @@
+function t(e){return new RegExp("^(("+e.join(")|(")+"))\\b","i")}var r=["a_correlate","abs","acos","adapt_hist_equal","alog","alog2","alog10","amoeba","annotate","app_user_dir","app_user_dir_query","arg_present","array_equal","array_indices","arrow","ascii_template","asin","assoc","atan","axis","axis","bandpass_filter","bandreject_filter","barplot","bar_plot","beseli","beselj","beselk","besely","beta","biginteger","bilinear","bin_date","binary_template","bindgen","binomial","bit_ffs","bit_population","blas_axpy","blk_con","boolarr","boolean","boxplot","box_cursor","breakpoint","broyden","bubbleplot","butterworth","bytarr","byte","byteorder","bytscl","c_correlate","calendar","caldat","call_external","call_function","call_method","call_procedure","canny","catch","cd","cdf","ceil","chebyshev","check_math","chisqr_cvf","chisqr_pdf","choldc","cholsol","cindgen","cir_3pnt","clipboard","close","clust_wts","cluster","cluster_tree","cmyk_convert","code_coverage","color_convert","color_exchange","color_quan","color_range_map","colorbar","colorize_sample","colormap_applicable","colormap_gradient","colormap_rotation","colortable","comfit","command_line_args","common","compile_opt","complex","complexarr","complexround","compute_mesh_normals","cond","congrid","conj","constrained_min","contour","contour","convert_coord","convol","convol_fft","coord2to3","copy_lun","correlate","cos","cosh","cpu","cramer","createboxplotdata","create_cursor","create_struct","create_view","crossp","crvlength","ct_luminance","cti_test","cursor","curvefit","cv_coord","cvttobm","cw_animate","cw_animate_getp","cw_animate_load","cw_animate_run","cw_arcball","cw_bgroup","cw_clr_index","cw_colorsel","cw_defroi","cw_field","cw_filesel","cw_form","cw_fslider","cw_light_editor","cw_light_editor_get","cw_light_editor_set","cw_orient","cw_palette_editor","cw_palette_editor_get","cw_palette_editor_set","cw_pdmenu","cw_rgbslider","cw_tmpl","cw_zoom","db_exists","dblarr","dcindgen","dcomplex","dcomplexarr","define_key","define_msgblk","define_msgblk_from_file","defroi","defsysv","delvar","dendro_plot","dendrogram","deriv","derivsig","determ","device","dfpmin","diag_matrix","dialog_dbconnect","dialog_message","dialog_pickfile","dialog_printersetup","dialog_printjob","dialog_read_image","dialog_write_image","dictionary","digital_filter","dilate","dindgen","dissolve","dist","distance_measure","dlm_load","dlm_register","doc_library","double","draw_roi","edge_dog","efont","eigenql","eigenvec","ellipse","elmhes","emboss","empty","enable_sysrtn","eof","eos","erase","erf","erfc","erfcx","erode","errorplot","errplot","estimator_filter","execute","exit","exp","expand","expand_path","expint","extract","extract_slice","f_cvf","f_pdf","factorial","fft","file_basename","file_chmod","file_copy","file_delete","file_dirname","file_expand_path","file_gunzip","file_gzip","file_info","file_lines","file_link","file_mkdir","file_move","file_poll_input","file_readlink","file_same","file_search","file_tar","file_test","file_untar","file_unzip","file_which","file_zip","filepath","findgen","finite","fix","flick","float","floor","flow3","fltarr","flush","format_axis_values","forward_function","free_lun","fstat","fulstr","funct","function","fv_test","fx_root","fz_roots","gamma","gamma_ct","gauss_cvf","gauss_pdf","gauss_smooth","gauss2dfit","gaussfit","gaussian_function","gaussint","get_drive_list","get_dxf_objects","get_kbrd","get_login_info","get_lun","get_screen_size","getenv","getwindows","greg2jul","grib","grid_input","grid_tps","grid3","griddata","gs_iter","h_eq_ct","h_eq_int","hanning","hash","hdf","hdf5","heap_free","heap_gc","heap_nosave","heap_refcount","heap_save","help","hilbert","hist_2d","hist_equal","histogram","hls","hough","hqr","hsv","i18n_multibytetoutf8","i18n_multibytetowidechar","i18n_utf8tomultibyte","i18n_widechartomultibyte","ibeta","icontour","iconvertcoord","idelete","identity","idl_base64","idl_container","idl_validname","idlexbr_assistant","idlitsys_createtool","idlunit","iellipse","igamma","igetcurrent","igetdata","igetid","igetproperty","iimage","image","image_cont","image_statistics","image_threshold","imaginary","imap","indgen","int_2d","int_3d","int_tabulated","intarr","interpol","interpolate","interval_volume","invert","ioctl","iopen","ir_filter","iplot","ipolygon","ipolyline","iputdata","iregister","ireset","iresolve","irotate","isa","isave","iscale","isetcurrent","isetproperty","ishft","isocontour","isosurface","isurface","itext","itranslate","ivector","ivolume","izoom","journal","json_parse","json_serialize","jul2greg","julday","keyword_set","krig2d","kurtosis","kw_test","l64indgen","la_choldc","la_cholmprove","la_cholsol","la_determ","la_eigenproblem","la_eigenql","la_eigenvec","la_elmhes","la_gm_linear_model","la_hqr","la_invert","la_least_square_equality","la_least_squares","la_linear_equation","la_ludc","la_lumprove","la_lusol","la_svd","la_tridc","la_trimprove","la_triql","la_trired","la_trisol","label_date","label_region","ladfit","laguerre","lambda","lambdap","lambertw","laplacian","least_squares_filter","leefilt","legend","legendre","linbcg","lindgen","linfit","linkimage","list","ll_arc_distance","lmfit","lmgr","lngamma","lnp_test","loadct","locale_get","logical_and","logical_or","logical_true","lon64arr","lonarr","long","long64","lsode","lu_complex","ludc","lumprove","lusol","m_correlate","machar","make_array","make_dll","make_rt","map","mapcontinents","mapgrid","map_2points","map_continents","map_grid","map_image","map_patch","map_proj_forward","map_proj_image","map_proj_info","map_proj_init","map_proj_inverse","map_set","matrix_multiply","matrix_power","max","md_test","mean","meanabsdev","mean_filter","median","memory","mesh_clip","mesh_decimate","mesh_issolid","mesh_merge","mesh_numtriangles","mesh_obj","mesh_smooth","mesh_surfacearea","mesh_validate","mesh_volume","message","min","min_curve_surf","mk_html_help","modifyct","moment","morph_close","morph_distance","morph_gradient","morph_hitormiss","morph_open","morph_thin","morph_tophat","multi","n_elements","n_params","n_tags","ncdf","newton","noise_hurl","noise_pick","noise_scatter","noise_slur","norm","obj_class","obj_destroy","obj_hasmethod","obj_isa","obj_new","obj_valid","objarr","on_error","on_ioerror","online_help","openr","openu","openw","oplot","oploterr","orderedhash","p_correlate","parse_url","particle_trace","path_cache","path_sep","pcomp","plot","plot3d","plot","plot_3dbox","plot_field","ploterr","plots","polar_contour","polar_surface","polyfill","polyshade","pnt_line","point_lun","polarplot","poly","poly_2d","poly_area","poly_fit","polyfillv","polygon","polyline","polywarp","popd","powell","pref_commit","pref_get","pref_set","prewitt","primes","print","printf","printd","pro","product","profile","profiler","profiles","project_vol","ps_show_fonts","psafm","pseudo","ptr_free","ptr_new","ptr_valid","ptrarr","pushd","qgrid3","qhull","qromb","qromo","qsimp","query_*","query_ascii","query_bmp","query_csv","query_dicom","query_gif","query_image","query_jpeg","query_jpeg2000","query_mrsid","query_pict","query_png","query_ppm","query_srf","query_tiff","query_video","query_wav","r_correlate","r_test","radon","randomn","randomu","ranks","rdpix","read","readf","read_ascii","read_binary","read_bmp","read_csv","read_dicom","read_gif","read_image","read_interfile","read_jpeg","read_jpeg2000","read_mrsid","read_pict","read_png","read_ppm","read_spr","read_srf","read_sylk","read_tiff","read_video","read_wav","read_wave","read_x11_bitmap","read_xwd","reads","readu","real_part","rebin","recall_commands","recon3","reduce_colors","reform","region_grow","register_cursor","regress","replicate","replicate_inplace","resolve_all","resolve_routine","restore","retall","return","reverse","rk4","roberts","rot","rotate","round","routine_filepath","routine_info","rs_test","s_test","save","savgol","scale3","scale3d","scatterplot","scatterplot3d","scope_level","scope_traceback","scope_varfetch","scope_varname","search2d","search3d","sem_create","sem_delete","sem_lock","sem_release","set_plot","set_shading","setenv","sfit","shade_surf","shade_surf_irr","shade_volume","shift","shift_diff","shmdebug","shmmap","shmunmap","shmvar","show3","showfont","signum","simplex","sin","sindgen","sinh","size","skewness","skip_lun","slicer3","slide_image","smooth","sobel","socket","sort","spawn","sph_4pnt","sph_scat","spher_harm","spl_init","spl_interp","spline","spline_p","sprsab","sprsax","sprsin","sprstp","sqrt","standardize","stddev","stop","strarr","strcmp","strcompress","streamline","streamline","stregex","stretch","string","strjoin","strlen","strlowcase","strmatch","strmessage","strmid","strpos","strput","strsplit","strtrim","struct_assign","struct_hide","strupcase","surface","surface","surfr","svdc","svdfit","svsol","swap_endian","swap_endian_inplace","symbol","systime","t_cvf","t_pdf","t3d","tag_names","tan","tanh","tek_color","temporary","terminal_size","tetra_clip","tetra_surface","tetra_volume","text","thin","thread","threed","tic","time_test2","timegen","timer","timestamp","timestamptovalues","tm_test","toc","total","trace","transpose","tri_surf","triangulate","trigrid","triql","trired","trisol","truncate_lun","ts_coef","ts_diff","ts_fcast","ts_smooth","tv","tvcrs","tvlct","tvrd","tvscl","typename","uindgen","uint","uintarr","ul64indgen","ulindgen","ulon64arr","ulonarr","ulong","ulong64","uniq","unsharp_mask","usersym","value_locate","variance","vector","vector_field","vel","velovect","vert_t3d","voigt","volume","voronoi","voxel_proj","wait","warp_tri","watershed","wdelete","wf_draw","where","widget_base","widget_button","widget_combobox","widget_control","widget_displaycontextmenu","widget_draw","widget_droplist","widget_event","widget_info","widget_label","widget_list","widget_propertysheet","widget_slider","widget_tab","widget_table","widget_text","widget_tree","widget_tree_move","widget_window","wiener_filter","window","window","write_bmp","write_csv","write_gif","write_image","write_jpeg","write_jpeg2000","write_nrif","write_pict","write_png","write_ppm","write_spr","write_srf","write_sylk","write_tiff","write_video","write_wav","write_wave","writeu","wset","wshow","wtn","wv_applet","wv_cwt","wv_cw_wavelet","wv_denoise","wv_dwt","wv_fn_coiflet","wv_fn_daubechies","wv_fn_gaussian","wv_fn_haar","wv_fn_morlet","wv_fn_paul","wv_fn_symlet","wv_import_data","wv_import_wavelet","wv_plot3d_wps","wv_plot_multires","wv_pwt","wv_tool_denoise","xbm_edit","xdisplayfile","xdxf","xfont","xinteranimate","xloadct","xmanager","xmng_tmpl","xmtool","xobjview","xobjview_rotate","xobjview_write_image","xpalette","xpcolor","xplot3d","xregistered","xroi","xsq_test","xsurface","xvaredit","xvolume","xvolume_rotate","xvolume_write_image","xyouts","zlib_compress","zlib_uncompress","zoom","zoom_24"],a=t(r),i=["begin","end","endcase","endfor","endwhile","endif","endrep","endforeach","break","case","continue","for","foreach","goto","if","then","else","repeat","until","switch","while","do","pro","function"],_=t(i),o=new RegExp("^[_a-z¡-][_a-z0-9¡-]*","i"),l=/[+\-*&=<>\/@#~$]/,s=new RegExp("(and|or|eq|lt|le|gt|ge|ne|not)","i");function n(e){return e.eatSpace()?null:e.match(";")?(e.skipToEnd(),"comment"):e.match(/^[0-9\.+-]/,!1)&&(e.match(/^[+-]?0x[0-9a-fA-F]+/)||e.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?/)||e.match(/^[+-]?\d+([EeDd][+-]?\d+)?/))?"number":e.match(/^"([^"]|(""))*"/)||e.match(/^'([^']|(''))*'/)?"string":e.match(_)?"keyword":e.match(a)?"builtin":e.match(o)?"variable":e.match(l)||e.match(s)?"operator":(e.next(),null)}const d={name:"idl",token:function(e){return n(e)},languageData:{autocomplete:r.concat(i)}};export{d as idl};
diff --git a/docs/assets/index-076518c9.js b/docs/assets/index-076518c9.js
new file mode 100644
index 00000000..0618f5c7
--- /dev/null
+++ b/docs/assets/index-076518c9.js
@@ -0,0 +1 @@
+import{s,t as O,L as i,M as p,D as a,k as u,m as l,O as e,P as S}from"./index-46a25777.js";const c=l.deserialize({version:14,states:"%pOVOWOOObQPOOOpOSO'#C_OOOO'#Cp'#CpQVOWOOQxQPOOO!TQQOOQ!YQPOOOOOO,58y,58yO!_OSO,58yOOOO-E6n-E6nO!dQQO'#CqQ{QPOOO!iQPOOQ{QPOOO!qQPOOOOOO1G.e1G.eOOQO,59],59]OOQO-E6o-E6oO!yOpO'#CiO#RO`O'#CiQOQPOOO#ZO#tO'#CmO#fO!bO'#CmOOQO,59T,59TO#qOpO,59TO#vO`O,59TOOOO'#Cr'#CrO#{O#tO,59XOOQO,59X,59XOOOO'#Cs'#CsO$WO!bO,59XOOQO1G.o1G.oOOOO-E6p-E6pOOQO1G.s1G.sOOOO-E6q-E6q",stateData:"$g~OjOS~OQROUROkQO~OWTOXUOZUO`VO~OSXOTWO~OXUO[]OlZO~OY^O~O[_O~OT`O~OYaO~OmcOodO~OmfOogO~O^iOnhO~O_jOphO~ObkOqkOrmO~OcnOsnOtmO~OnpO~OppO~ObkOqkOrrO~OcnOsnOtrO~OWX`~",goto:"!^hPPPiPPPPPPPPPmPPPpPPsy!Q!WTROSRe]Re_QSORYSS[T^Rb[QlfRqlQogRso",nodeNames:"⚠ Content Text Interpolation InterpolationContent }} Entity Attribute VueAttributeName : Identifier @ Is ScriptAttributeValue AttributeScript AttributeScript AttributeName AttributeValue Entity Entity",maxTerm:36,skippedNodes:[0],repeatNodeCount:4,tokenData:"'y~RdXY!aYZ!a]^!apq!ars!rwx!w}!O!|!O!P#t!Q![#y![!]$s!_!`%g!b!c%l!c!}#y#R#S#y#T#j#y#j#k%q#k#o#y%W;'S#y;'S;:j$m<%lO#y~!fSj~XY!aYZ!a]^!apq!a~!wOm~~!|Oo~!b#RX`!b}!O!|!Q![!|![!]!|!c!}!|#R#S!|#T#o!|%W;'S!|;'S;:j#n<%lO!|!b#qP;=`<%l!|~#yOl~%W$QXY#t`!b}!O!|!Q![#y![!]!|!c!}#y#R#S#y#T#o#y%W;'S#y;'S;:j$m<%lO#y%W$pP;=`<%l#y~$zXX~`!b}!O!|!Q![!|![!]!|!c!}!|#R#S!|#T#o!|%W;'S!|;'S;:j#n<%lO!|~%lO[~~%qOZ~%W%xXY#t`!b}!O&e!Q![#y![!]!|!c!}#y#R#S#y#T#o#y%W;'S#y;'S;:j$m<%lO#y!b&jX`!b}!O!|!Q![!|![!]!|!c!}'V#R#S!|#T#o'V%W;'S!|;'S;:j#n<%lO!|!b'^XW!b`!b}!O!|!Q![!|![!]!|!c!}'V#R#S!|#T#o'V%W;'S!|;'S;:j#n<%lO!|",tokenizers:[6,7,new e("b~RP#q#rU~XP#q#r[~aOT~~",17,4),new e("!k~RQvwX#o#p!_~^TU~Opmq!]m!^;'Sm;'S;=`!X<%lOm~pUOpmq!]m!]!^!S!^;'Sm;'S;=`!X<%lOm~!XOU~~![P;=`<%lm~!bP#o#p!e~!jOk~~",72,2),new e("[~RPwxU~ZOp~~",11,15),new e("[~RPrsU~ZOn~~",11,14),new e("!e~RQvwXwx!_~^Tc~Opmq!]m!^;'Sm;'S;=`!X<%lOm~pUOpmq!]m!]!^!S!^;'Sm;'S;=`!X<%lOm~!XOc~~![P;=`<%lm~!dOt~~",66,35),new e("!e~RQrsXvw^~^Or~~cTb~Oprq!]r!^;'Sr;'S;=`!^<%lOr~uUOprq!]r!]!^!X!^;'Sr;'S;=`!^<%lOr~!^Ob~~!aP;=`<%lr~",66,33)],topRules:{Content:[0,1],Attribute:[1,7]},tokenPrec:157}),m=S.parser.configure({top:"SingleExpression"}),n=c.configure({props:[s({Text:O.content,Is:O.definitionOperator,AttributeName:O.attributeName,VueAttributeName:O.keyword,Identifier:O.variableName,"AttributeValue ScriptAttributeValue":O.attributeValue,Entity:O.character,"{{ }}":O.brace,"@ :":O.punctuation})]}),o={parser:m},b=n.configure({wrap:a((t,r)=>t.name=="InterpolationContent"?o:null)}),P=n.configure({wrap:a((t,r)=>t.name=="AttributeScript"?o:null),top:"Attribute"}),Q={parser:b},y={parser:P},R=i.define({name:"vue",parser:p.parser.configure({dialect:"selfClosing",wrap:a(X)}),languageData:{closeBrackets:{brackets:["{",'"']}}});function X(t,r){switch(t.name){case"Attribute":return/^(@|:|v-)/.test(r.read(t.from,t.from+2))?y:null;case"Text":return Q}return null}function g(){return new u(R)}export{g as vue,R as vueLanguage};
diff --git a/docs/assets/index-09684546.js b/docs/assets/index-09684546.js
new file mode 100644
index 00000000..b380c57b
--- /dev/null
+++ b/docs/assets/index-09684546.js
@@ -0,0 +1,3 @@
+import{E as d,F as u,s as E,t as e,m as V,w as h,o as G,L as g,i as k,y as T,h as z,z as v,k as j,G as I,p as A,N as B,H as Q}from"./index-46a25777.js";const F=1,c=188,f=189,D=190,q=191,Z=192,C=193,L=22,M=23,J=47,N=48,H=53,K=54,OO=55,rO=57,oO=58,SO=59,eO=60,lO=61,sO=63,QO=230,PO=71,tO=255,aO=121,pO=142,$O=143,iO=146,a=10,p=13,W=32,i=9,m=35,TO=40,xO=46,nO=new Set([M,J,N,tO,sO,aO,K,OO,QO,eO,lO,oO,SO,PO,pO,$O,iO]);function x(O){return O==a||O==p}const wO=new d((O,r)=>{if(O.next<0)O.acceptToken(C);else if(r.context.depth<0)x(O.next)&&O.acceptToken(Z,1);else if(x(O.peek(-1))&&r.canShift(q)){let o=0;for(;O.next==W||O.next==i;)O.advance(),o++;(O.next==a||O.next==p||O.next==m)&&O.acceptToken(q,-o)}else x(O.next)&&O.acceptToken(r.context.depth<0?Z:D,1)},{contextual:!0}),dO=new d((O,r)=>{let o=r.context.depth;if(o<0)return;let S=O.peek(-1);if((S==a||S==p)&&r.context.depth>=0){let l=0,P=0;for(;;){if(O.next==W)l++;else if(O.next==i)l+=8-l%8;else break;O.advance(),P++}l!=o&&O.next!=a&&O.next!=p&&O.next!=m&&(l{for(let r=0;r<5;r++){if(O.next!="print".charCodeAt(r))return;O.advance()}if(!/\w/.test(String.fromCharCode(O.next)))for(let r=0;;r++){let o=O.peek(r);if(!(o==W||o==i)){o!=TO&&o!=xO&&o!=a&&o!=p&&o!=m&&O.acceptToken(F);return}}}),bO=E({'async "*" "**" FormatConversion FormatSpec':e.modifier,"for while if elif else try except finally return raise break continue with pass assert await yield match case":e.controlKeyword,"in not and or is del":e.operatorKeyword,"from def class global nonlocal lambda":e.definitionKeyword,import:e.moduleKeyword,"with as print":e.keyword,Boolean:e.bool,None:e.null,VariableName:e.variableName,"CallExpression/VariableName":e.function(e.variableName),"FunctionDefinition/VariableName":e.function(e.definition(e.variableName)),"ClassDefinition/VariableName":e.definition(e.className),PropertyName:e.propertyName,"CallExpression/MemberExpression/PropertyName":e.function(e.propertyName),Comment:e.lineComment,Number:e.number,String:e.string,FormatString:e.special(e.string),UpdateOp:e.updateOperator,"ArithOp!":e.arithmeticOperator,BitOp:e.bitwiseOperator,CompareOp:e.compareOperator,AssignOp:e.definitionOperator,Ellipsis:e.punctuation,At:e.meta,"( )":e.paren,"[ ]":e.squareBracket,"{ }":e.brace,".":e.derefOperator,", ;":e.separator}),XO={__proto__:null,await:40,or:50,and:52,in:56,not:58,is:60,if:66,else:68,lambda:72,yield:90,from:92,async:98,for:100,None:152,True:154,False:154,del:168,pass:172,break:176,continue:180,return:184,raise:192,import:196,as:198,global:202,nonlocal:204,assert:208,elif:218,while:222,try:228,except:230,finally:232,with:236,def:240,class:250,match:261,case:267},YO=V.deserialize({version:14,states:"!MbO`Q]OOP$_OSOOO%hQdO'#G|OOQS'#Cm'#CmOOQS'#Cn'#CnO'WQ[O'#ClO(yQdO'#G{OOQS'#G|'#G|OOQS'#DS'#DSOOQS'#G{'#G{O)gQ[O'#D]O)zQ[O'#DdO*[Q[O'#DhOOQS'#Ds'#DsO*oOpO'#DsO*wO!bO'#DsO+PO#tO'#DtO+[O&jO'#DtO+gO,UO'#DtO+rO7[O'#DtO-tQdO'#GmOOQS'#Gm'#GmO'WQ[O'#GlO/WQdO'#GlOOQS'#E]'#E]O/oQ[O'#E^OOQS'#Gk'#GkO/yQ[O'#GjOOQV'#Gj'#GjO0UQ[O'#FPOOQS'#GW'#GWO0ZQ[O'#FOOOQV'#Hx'#HxOOQV'#Gi'#GiOOQV'#Fh'#FhQ`Q]OOO'WQ[O'#CoO0iQ[O'#C{O0pQ[O'#DPO1OQ[O'#HQO1`QdO'#EQO'WQ[O'#EROOQS'#ET'#ETOOQS'#EV'#EVOOQS'#EX'#EXO1tQ[O'#EZO2[Q[O'#E_O0UQ[O'#EaO2oQdO'#EaO0UQ[O'#EdO/oQ[O'#EgO/oQ[O'#EkO/oQ[O'#EnO2zQ[O'#EpO3RQ[O'#EuO3^Q[O'#EqO/oQ[O'#EuO0UQ[O'#EwO0UQ[O'#E|O3cQ[O'#FRP3jO[O'#GhPOOO)CB[)CB[OOQS'#Cc'#CcOOQS'#Cd'#CdOOQS'#Ce'#CeOOQS'#Cf'#CfOOQS'#Cg'#CgOOQS'#Ch'#ChOOQS'#Cj'#CjO'WQ[O,58|O'WQ[O,58|O'WQ[O,58|O'WQ[O,58|O'WQ[O,58|O'WQ[O,58|O3uQ[O'#DmOOQS,5:W,5:WO4YQ[O'#H[OOQS,5:Z,5:ZO4gQMlO,5:ZO4lQdO,59WO0iQ[O,59`O0iQ[O,59`O0iQ[O,59`O7[Q[O,59`O7aQ[O,59`O7hQ[O,59hO7oQ[O'#G{O8uQ[O'#GzOOQS'#Gz'#GzOOQS'#DY'#DYO9^Q[O,59_O'WQ[O,59_O9lQ[O,59_OOQS,59w,59wO9qQ[O,5:PO'WQ[O,5:POOQS,5:O,5:OO:PQ[O,5:OO:UQ[O,5:VO'WQ[O,5:VO'WQ[O,5:TOOQS,5:S,5:SO:gQ[O,5:SO:lQ[O,5:UOOOO'#Fp'#FpO:qOpO,5:_OOQS,5:_,5:_OOOO'#Fq'#FqO:yO!bO,5:_O;RQ[O'#DuOOOO'#Fr'#FrO;cO#tO,5:`OOQS,5:`,5:`OOOO'#Fu'#FuO;nO&jO,5:`OOOO'#Fv'#FvO;yO,UO,5:`OOOO'#Fw'#FwO`OOQS1G1V1G1VO!5tQ[O1G1VOOQS'#DT'#DTO/oQ[O,5=iOOQS,5=i,5=iO!5yQ[O'#FiO!6UQ[O,59mO!6^Q[O1G/VO!6hQdO,5=mOOQS1G3W1G3WOOQS,5:h,5:hO!7XQ[O'#GlOOQS,5cO!9ZQ[O,5>cO!9iQ[O,5>_O!:PQ[O,5>_O!:bQ_O1G0qO!=pQ_O1G0tO!@{Q[O,5>eO!AVQ[O,5>eO!A_QdO,5>eO/oQ[O1G0vO!AiQ[O1G0vO3^Q[O1G0{O! RQ[O1G0}OOQV,5;W,5;WO!AnQ^O,5;WO!AsQ_O1G0wO!EUQ[O'#GTO3^Q[O1G0wO3^Q[O1G0wO!EcQ[O,5>fO!EpQ[O,5>fO0UQ[O,5>fOOQV1G0{1G0{O!ExQ[O'#EyO!FZQMlO1G0}OOQV1G1S1G1SO3^Q[O1G1SO!FcQ[O'#FTOOQV1G1X1G1XO! `QdO1G1XPOOO1G2n1G2nP!FhOSO1G2nOOQS,5=u,5=uOOQS'#Dn'#DnO/oQ[O,5=uO!FmQ[O,5=tO!GQQ[O,5=tOOQS1G/s1G/sO!GYQ[O,5=wO!GjQ[O,5=wO!GrQ[O,5=wO!HVQ[O,5=wO!HgQ[O,5=wOOQS1G3b1G3bOOQS7+$f7+$fO!6^Q[O7+$nO!JYQ[O1G.zO!JaQ[O1G.zOOQS1G/^1G/^OOQS,5SO!NwQ[O,5>SO!NwQ[O,5>SO# VO$ISO'#DwO# bOWO'#HiOOOO1G/{1G/{O# gQ[O1G/{O# oQ!LUO7+(^O#!`QdO1G2PP#!yQ[O'#FyOOQS,5T,5>TOOOO7+%g7+%gO#6pQ[O1G2rO#7ZQ[O1G2rP'WQ[O'#FlO/oQ[O<bO#7}Q[O,5>bO0UQ[O,5>bO#8`Q[O,5>aOOQS<hO#@XQ[O,5>hOOQS,5>h,5>hO#@dQ[O,5>gO#@uQ[O,5>gOOQS1G1P1G1POOQS,5;g,5;gO#@}Q[O1G1ZP#ASQ[O'#FnO#AdQ[O1G1uO#AwQ[O1G1uO#BXQ[O1G1uP#BdQ[O'#FoO#BqQ[O7+(}O#CRQ[O7+(}O#CRQ[O7+(}O#CZQ[O7+(}O#CkQ[O7+(tO7hQ[O7+(tOOQSAN>TAN>TO#DUQ[O<aAN>aO/oQ[O1G1sO#DfQdO1G1sP#DpQ[O'#FmOOQS1G1y1G1yP#D}Q[O'#FsO#E[Q[O7+)YOOOO-E9r-E9rO#ErQ[O7+(^OOQSAN?VAN?VO#F]Q[O,5jO$)RQ[O,5>jO0UQ[O,5;vO$)dQ[O,5;zO$)iQ[O,5;zO#KkQ[O'#IQO$)nQ[O'#IQO$)sQ[O,5;{OOQS,5;|,5;|O'WQ[O'#FgOOQU1G1[1G1[O3^Q[O1G1[OOQSAN@gAN@gO$)xQ[OG27oO$*YQ[O,59{OOQS1G3[1G3[OOQS,5lO#KkQ[O,5>lOOQS1G1g1G1gO$,yQdO,5mO$-XQ[O,5>mOOQS1G1j1G1jOOQS7+&y7+&yP#KkQ[O'#G^O$-aQ[O1G4WO$-kQ[O1G4WO$-sQ[O1G4WOOQS7+%R7+%RO$.RQ[O1G1kO$.aQdO'#FWO$.hQ[O,5UPP'P'PPP'P'P'P'P'P>Y?P'PP?SP?YC]FuPGZ'PPPPG_Ge&wP&w&wP&wP&wP&wP&wP&w&w&wP&wPP&wPP&wPGkPGrGxPGrPGrGrPPPGrPIwPJQJWJ^IwPGrJdPGrPJkJqPJuKZKxLcJuJuLiLvJuJuJuJuM[MbMeMjMmMwM}NZNmNsN}! T! q! w! }!!T!!_!!e!!k!!q!!w!!}!#a!#k!#q!#w!#}!$X!$_!$e!$k!$u!${!%V!%]!%f!%l!%{!&T!&_!&fPPPPPPPPP!&l!&o!&u!'O!'Y!'ePPPPPPPPPPPP!,T!-i!1_!4kPP!4s!5R!5[!6Q!5w!6Z!6a!6d!6g!6j!6r!7cPPPPPPPPPP!7f!7iPPPPPPPPP!7o!7{!8X!8_!8h!8k!8q!8w!8}!9QP!9Y!9c!:_!:b]jOs#r$r)l+l'ueOTYZ[fistuwy}!O!S!T!U!V!Y!]!g!h!i!j!k!l!m!o!s!t!u!w!x#O#S#W#X#b#o#r$T$U$W$Y$]$m$o$p$r$y%V%[%c%f%h%k%o%t%v&Q&Y&[&g&k&t&v&w'O'S'V'^'a'p'q't'v'w'{(Q(S(W([(a(b(h(k(r(t(|)P)])`)d)e)i)l)u*P*Y*]*^*a*g*h*j*l*o*p*s*v*z*{+S+U+V+^+f+g+l+s+t+w,P,Q,R,T,U,X,Z,],_,a,c,d,f,w,y-Q-T-W-v-w.f.j/R/q/r/s/t/v/w/x/y/z/|0Q}!gQ#n#{$^$l$x%m%r%x%y&l'U'k(s)O)c*e*n+e,`/P/u!P!hQ#n#{$^$l$x$}%m%r%x%y&l'U'k(s)O)c*e*n+e,`/P/u!R!iQ#n#{$^$l$x$}%O%m%r%x%y&l'U'k(s)O)c*e*n+e,`/P/u!T!jQ#n#{$^$l$x$}%O%P%m%r%x%y&l'U'k(s)O)c*e*n+e,`/P/u!V!kQ#n#{$^$l$x$}%O%P%Q%m%r%x%y&l'U'k(s)O)c*e*n+e,`/P/u!X!lQ#n#{$^$l$x$}%O%P%Q%R%m%r%x%y&l'U'k(s)O)c*e*n+e,`/P/u!]!lQ!r#n#{$^$l$x$}%O%P%Q%R%S%m%r%x%y&l'U'k(s)O)c*e*n+e,`/P/u'uTOTYZ[fistuwy}!O!S!T!U!V!Y!]!g!h!i!j!k!l!m!o!s!t!u!w!x#O#S#W#X#b#o#r$T$U$W$Y$]$m$o$p$r$y%V%[%c%f%h%k%o%t%v&Q&Y&[&g&k&t&v&w'O'S'V'^'a'p'q't'v'w'{(Q(S(W([(a(b(h(k(r(t(|)P)])`)d)e)i)l)u*P*Y*]*^*a*g*h*j*l*o*p*s*v*z*{+S+U+V+^+f+g+l+s+t+w,P,Q,R,T,U,X,Z,],_,a,c,d,f,w,y-Q-T-W-v-w.f.j/R/q/r/s/t/v/w/x/y/z/|0Q&ZVOYZ[isuw}!O!S!T!U!Y!m!o!s!t!u!w!x#b#o#r$U$W$Y$]$p$r%V%[%c%f%h%o%t%v&Q&Y&g&k&v&w'O'V'^'a'p'q't'v'w'{(S([(b(h(k(r(t(|)])`)i)l)u*P*Y*]*^*a*g*h*j*l*o*p*s*z*{+S+V+^+l+s+t+w,P,Q,R,T,U,X,Z,],_,a,c,d,f,w,y-Q-T-W-v-w.j/R/q/r/s/t/v/w/x/y/|0Q%eXOYZ[isw}!O!S!T!U!Y!m!o#b#o#r$U$W$Y$]$p$r%V%[%f%h%o%t%v&Q&Y&g&k&v&w'O'V'^'a'p'q't'v'w'{(S([(b(h(k(r(t(|)])`)i)l)u*P*Y*]*^*a*g*j*l*o*p*s*z*{+S+V+^+l+s+t+w,P,Q,R,T,U,X,],_,a,c,d,f,w,y-Q-T-v-w.j/w/x/yQ$RvQ.k-{R/}0P'leOTYZ[fistuwy}!O!S!T!U!V!Y!]!g!h!i!j!k!l!o!s!t!u!w!x#O#S#W#X#b#o#r$T$U$W$Y$]$m$o$p$r$y%V%[%c%f%h%k%o%t%v&Q&Y&[&g&k&t&v&w'O'S'V'^'a'p't'v'w'{(Q(S(W([(a(b(h(k(r(t(|)P)])`)d)e)i)l)u*P*]*^*a*g*h*j*l*o*p*s*v*z*{+S+U+V+^+f+g+l+s+t+w,Q,R,T,U,X,Z,],_,a,c,d,f,w,y-Q-T-W-v-w.f.j/R/q/r/s/t/v/w/x/y/z/|0QW#um!P!Q$dW#}v&i-{0PQ$f!RQ$v!ZQ$w![W%U!m'q*Y,PS&h$O$PQ'Y$qQ(u&bQ)T&xU)U&z)V)WU)X&|)Y+]Q)w'cW)x'e+z,{-eS+y)y)zY,h+W,i-]-^.PQ,k+YQ,t+pQ,v+rl-h-P-n-o-q.Z.].b.x.}/S/X/d/i/lQ.O-[Q.c-pQ.o.TQ.z._U/_/T/b/jX/e/Y/f/m/nR&g#}!_!{YZ!T!U!o%[%h%o't'v'w(S([)`*]*^*a*g*j*l,Q,R,T,U,X-Q-T-v-w.jR%f!zQ#PYQ&R#bQ&p$YR&s$]T-z-W/R![!nQ!r#n#{$^$l$x$}%O%P%Q%R%S%m%r%x%y&l'U'k(s)O)c*e*n+e,`/P/uQ&e#vR'h$wR'p%UQ%_!qR.m.R'tdOTYZ[fistuwy}!O!S!T!U!V!Y!]!g!h!i!j!k!l!m!o!s!t!u!w!x#O#S#W#X#b#o#r$T$U$W$Y$]$m$o$p$r$y%V%[%c%f%h%k%o%t%v&Q&Y&[&g&k&t&v&w'O'S'V'^'a'p'q't'v'w'{(Q(S(W([(a(b(h(k(r(t(|)P)])`)d)e)i)l)u*P*Y*]*^*a*g*h*j*l*o*p*s*v*z*{+S+U+V+^+f+g+l+s+t+w,P,Q,R,T,U,X,Z,],_,a,c,d,f,w,y-Q-T-W-v-w.f.j/R/q/r/s/t/v/w/x/y/z/|0QS#ld#m!P-l-P-n-o-p-q.T.Z.].b.x.}/S/T/X/Y/b/d/f/i/j/l/m/n'tdOTYZ[fistuwy}!O!S!T!U!V!Y!]!g!h!i!j!k!l!m!o!s!t!u!w!x#O#S#W#X#b#o#r$T$U$W$Y$]$m$o$p$r$y%V%[%c%f%h%k%o%t%v&Q&Y&[&g&k&t&v&w'O'S'V'^'a'p'q't'v'w'{(Q(S(W([(a(b(h(k(r(t(|)P)])`)d)e)i)l)u*P*Y*]*^*a*g*h*j*l*o*p*s*v*z*{+S+U+V+^+f+g+l+s+t+w,P,Q,R,T,U,X,Z,],_,a,c,d,f,w,y-Q-T-W-v-w.f.j/R/q/r/s/t/v/w/x/y/z/|0QT#ld#mS#c`#dS#fa#gS#hb#iS#jc#kT+O(n+PT(o&R(qQ$[xR+x)xX$Yx$Z$[&rZlOs$r)l+lXpOs)l+lQ$s!XQ'Q$jQ'R$kQ'd$uQ'g$wQ)j'XQ)p'^Q)r'_Q)s'`Q*Q'fQ*S'hQ+a)`Q+c)aQ+d)bQ+h)hS+j)k*RQ+m)nQ+n)oQ+o)qQ,m+`Q,n+bQ,p+iQ,q+kQ,u+qQ-`,oQ-b,sQ-c,tQ.Q-aQ.g-tR/Q.hWpOs)l+lR#xoQ'f$vR)k'YQ+w)xR,y+xQ*R'fR+k)kZnOos)l+lQ'j$xR*U'kT,},O-Ou-s-P-n-o-q.T.Z.].b.x.}/S/T/X/b/d/i/j/lt-s-P-n-o-q.T.Z.].b.x.}/S/T/X/b/d/i/j/lQ.c-pX/e/Y/f/m/n!P-k-P-n-o-p-q.T.Z.].b.x.}/S/T/X/Y/b/d/f/i/j/l/m/nQ.W-jR.t.Xg.Z-m.[.p.w.|/[/^/`/k/o/pu-r-P-n-o-q.T.Z.].b.x.}/S/T/X/b/d/i/j/lX.U-h-r.o/_R.q.TV/a/T/b/jR.h-tQsOS#zs+lR+l)lQ&j$QR(z&jS%u#V$SS(c%u(fT(f%x&lQ%i!}Q%p#RW(T%i%p(Y(^Q(Y%mR(^%rQ&u$^R)Q&uQ(i%yQ*q(dT*w(i*qQ'r%WR*Z'rS'u%Z%[Y*_'u*`,V-U-xU*`'v'w'xU,V*a*b*cS-U,W,XR-x-VQ#^^R%|#^Q#a_R&O#aQ#d`R&S#dQ(l&PS*|(l*}R*}(mQ+P(nR,e+PQ#gaR&U#gQ#ibR&V#iQ#kcR&W#kQ#mdR&X#mQ#pgQ&Z#nW&^#p&Z(}+TQ(}&oR+T/uQ$ZxS&q$Z&rR&r$[Q'P$hR)^'PQ&c#uR(v&cQ$d!QR&y$dQ+X)US,j+X-_R-_,kQ&}$fR)Z&}Q#skR&`#sQ)_'QR+_)_Q'T$lS)f'T)gR)g'UQ']$sR)m']Q'b$tS)v'b+uR+u)wQ+{)|R,|+{WoOs)l+lR#woQ-O,OR-f-Od.[-m.p.w.|/[/^/`/k/o/pR.v.[U.S-h.o/_R.n.SQ/Z.|S/g/Z/hR/h/[S/U.p.qR/c/UQ.^-mR.y.^R!_PXrOs)l+lWqOs)l+lR'Z$rYkOs$r)l+lR&_#r[xOs#r$r)l+lR&p$Y&YQOYZ[isuw}!O!S!T!U!Y!m!o!s!t!u!w!x#b#o#r$U$W$Y$]$p$r%V%[%c%f%h%o%t%v&Q&Y&g&k&v&w'O'V'^'a'p'q't'v'w'{(S([(b(h(k(r(t(|)])`)i)l)u*P*Y*]*^*a*g*h*j*l*o*p*s*z*{+S+V+^+l+s+t+w,P,Q,R,T,U,X,Z,],_,a,c,d,f,w,y-Q-T-W-v-w.j/R/q/r/s/t/v/w/x/y/|0QQ!rTQ#nfQ#{tU$^y%k(WS$l!V$oQ$x!]Q$}!gQ%O!hQ%P!iQ%Q!jQ%R!kQ%S!lQ%m#OQ%r#SQ%x#WQ%y#XQ&l$TQ'U$mQ'k$yQ(s&[U)O&t)P+UW)c'S)e+f+gQ*e(QQ*n(aQ+e)dQ,`*vQ/P.fR/u/zQ!}YQ#RZQ$j!TQ$k!UQ%Z!oQ'x%[^(P%h%o(S([*g*j*l^*['t*^,T,U-T-w.jQ*b'vQ*c'wQ+b)`Q,S*]Q,W*aQ-R,QQ-S,RQ-V,XQ-u-QR.i-v[gOs#r$r)l+l!^!zYZ!T!U!o%[%h%o't'v'w(S([)`*]*^*a*g*j*l,Q,R,T,U,X-Q-T-v-w.jQ#V[Q#qiS$Sw}Q$a!OW$h!S$]'V)iS$t!Y$pW%T!m'q*Y,PQ&P#b`&]#o&Y(r(t(|+S,f/yQ&m$UQ&n$WQ&o$YQ'n%VQ(O%fW(`%t(b*o*sQ(d%vQ(m&QQ(x&gS({&k/wQ)R&vQ)S&wU)['O)]+^Q)q'^Y)t'a)u+s+t,wQ*W'pS*d'{/xW*u(h*p,],aW*y(k*{,c,dQ+}*PQ,b*zQ,g+VQ,x+wQ-Z,_R-d,yhUOs#o#r$r&Y&k'{(r(t)l+l$z!yYZ[iw}!O!S!T!U!Y!m!o#b$U$W$Y$]$p%V%[%f%h%o%t%v&Q&g&v&w'O'V'^'a'p'q't'v'w(S([(b(h(k(|)])`)i)u*P*Y*]*^*a*g*j*l*o*p*s*z*{+S+V+^+s+t+w,P,Q,R,T,U,X,],_,a,c,d,f,w,y-Q-T-v-w.j/w/x/yQ#|uW%`!s!w/r/|Q%a!tQ%b!uQ%d!xQ%n/qS'z%c/vQ'|/sQ'}/tQ,Y*hQ-Y,ZS-y-W/RR0O0QU$Qv-{0PR(y&i[hOs#r$r)l+lX!|Y#b$Y$]Q#[[Q$VwR$`}Q%j!}Q%q#RQ%w#VQ'n%TQ(Z%mQ(_%rQ(g%xQ(j%yQ*r(dQ-X,YQ-}-YR.l-|Q$_yQ(V%kR*i(WQ-|-WR/]/RR#UZR#Z[R%Y!mQ%W!mV*X'q*Y,P!]!pQ!r#n#{$^$l$x$}%O%P%Q%R%S%m%r%x%y&l'U'k(s)O)c*e*n+e,`/P/uR%]!oR&R#bQ(p&RR+R(qQ$i!SQ&s$]Q)h'VR+i)iQ#vmQ$b!PQ$e!QR&{$dQ)T&zR+[)WQ)T&zQ+Z)VR+[)WR$g!RXqOs)l+lQ$n!VR'W$oQ$u!YR'X$pR*O'eQ)|'eV,z+z,{-eQ-t-PQ.`-nR.a-oU-m-P-n-oQ.e-qQ.p.TQ.u.ZU.w.].x/XQ.|.bQ/[.}Q/^/SU/`/T/b/jQ/k/dQ/o/iR/p/lR.d-pR.r.T",nodeNames:"⚠ print Comment Script AssignStatement * BinaryExpression BitOp BitOp BitOp BitOp ArithOp ArithOp @ ArithOp ** UnaryExpression ArithOp BitOp AwaitExpression await ) ( ParenthesizedExpression BinaryExpression or and CompareOp in not is UnaryExpression ConditionalExpression if else LambdaExpression lambda ParamList VariableName AssignOp , : NamedExpression AssignOp YieldExpression yield from TupleExpression ComprehensionExpression async for LambdaExpression ] [ ArrayExpression ArrayComprehensionExpression } { DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression CallExpression ArgList AssignOp MemberExpression . PropertyName Number String FormatString FormatReplacement FormatConversion FormatSpec ContinuedString Ellipsis None Boolean TypeDef AssignOp UpdateStatement UpdateOp ExpressionStatement DeleteStatement del PassStatement pass BreakStatement break ContinueStatement continue ReturnStatement return YieldStatement PrintStatement RaiseStatement raise ImportStatement import as ScopeStatement global nonlocal AssertStatement assert StatementGroup ; IfStatement Body elif WhileStatement while ForStatement TryStatement try except finally WithStatement with FunctionDefinition def ParamList AssignOp TypeDef ClassDefinition class DecoratedStatement Decorator At MatchStatement match MatchBody MatchClause case CapturePattern LiteralPattern ArithOp ArithOp AsPattern OrPattern LogicOp AttributePattern SequencePattern MappingPattern StarPattern ClassPattern PatternArgList KeywordPattern KeywordPattern Guard",maxTerm:267,context:qO,nodeProps:[["group",-14,4,80,82,83,85,87,89,91,93,94,95,97,100,103,"Statement Statement",-22,6,16,19,23,38,47,48,54,55,58,59,60,61,62,65,68,69,70,74,75,76,77,"Expression",-10,105,107,110,112,113,117,119,124,126,129,"Statement",-9,134,135,138,139,141,142,143,144,145,"Pattern"],["openedBy",21,"(",52,"[",56,"{"],["closedBy",22,")",53,"]",57,"}"]],propSources:[bO],skippedNodes:[0,2],repeatNodeCount:37,tokenData:")'WMgR!`OX%TXY!EQY[%T[]!EQ]p%Tpq!EQqr!Gkrs!Ktst#J]tu%Tuv&'{vw&*kwx&+}xy'*fyz'+rz{'-O{|'/z|}'1^}!O'2j!O!P'5]!P!Q'Ae!Q!R'Da!R!['Ho![!](&g!]!^()V!^!_(*c!_!`(-_!`!a(.q!a!b%T!b!c(1j!c!d(3O!d!e(4|!e!h(3O!h!i(?z!i!t(3O!t!u(J[!u!w(3O!w!x(>S!x!}(3O!}#O(Ll#O#P!Fp#P#Q(Mx#Q#R) U#R#S(3O#S#T%T#T#U(3O#U#V(4|#V#Y(3O#Y#Z(?z#Z#f(3O#f#g(J[#g#i(3O#i#j(>S#j#o(3O#o#p)!h#p#q)#d#q#r)$v#r#s)%z#s$g%T$g;'S(3O;'S;=`(4v<%lO(3Ods#O=Q#O#P?P#P#o=Q#o#p@S#p;'S=Q;'S;=`C`<%lO=Q#|>gWOr=Qs#O=Q#O#P?P#P#o=Q#o#p@S#p;'S=Q;'S;=`C`<%lO=Q#|?SRO;'S=Q;'S;=`?];=`O=Q#|?dY&WW&f#tOr=Qrs=ts#O=Q#O#P?P#P#o=Q#o#p@S#p;'S=Q;'S;=`C`;=`<%l=Q<%lO=Q#|@XX&WWOr@trsA`s#O@t#O#PB_#P#o@t#o#p=Q#p;'S@t;'S;=`CY<%lO@tW@yV&WWOr@trsA`s#O@t#O#PB_#P;'S@t;'S;=`CY<%lO@tWAcVOr@trsAxs#O@t#O#PB_#P;'S@t;'S;=`CY<%lO@tWA{UOr@ts#O@t#O#PB_#P;'S@t;'S;=`CY<%lO@tWBbRO;'S@t;'S;=`Bk;=`O@tWBpW&WWOr@trsA`s#O@t#O#PB_#P;'S@t;'S;=`CY;=`<%l@t<%lO@tWC]P;=`<%l@t#|CcP;=`<%l=Q%dCiRO;'S8l;'S;=`Cr;=`O8l%dC}[&TS&WW&d!b&f#tOr8lrs9jsw8lwx;^x#O8l#O#PCf#P#o8l#o#pDs#p;'S8l;'S;=`J`;=`<%l8l<%lO8l%dDzZ&TS&WWOrEmrsFaswEmwxGsx#OEm#O#PIV#P#oEm#o#p8l#p;'SEm;'S;=`JY<%lOEm[EtX&TS&WWOrEmrsFaswEmwxGsx#OEm#O#PIV#P;'SEm;'S;=`JY<%lOEm[FfX&TSOrEmrsGRswEmwxGsx#OEm#O#PIV#P;'SEm;'S;=`JY<%lOEm[GWX&TSOrEmrs4`swEmwxGsx#OEm#O#PIV#P;'SEm;'S;=`JY<%lOEm[GxX&WWOrEmrsFaswEmwxHex#OEm#O#PIV#P;'SEm;'S;=`JY<%lOEm[HjX&WWOrEmrsFaswEmwx@tx#OEm#O#PIV#P;'SEm;'S;=`JY<%lOEm[IYRO;'SEm;'S;=`Ic;=`OEm[IjY&TS&WWOrEmrsFaswEmwxGsx#OEm#O#PIV#P;'SEm;'S;=`JY;=`<%lEm<%lOEm[J]P;=`<%lEm%dJcP;=`<%l8l;pJq[&TS&WW&d!b&f#tOr8lrs9jsw8lwx;^x#O8l#O#PCf#P#o8l#o#pDs#p;'S8l;'S;=`J`;=`<%l)m<%lO8l;pKjP;=`<%l)m;pKv]&^7[&WW&f#tOr)mrs*ssw)mwxLox#O)m#O#P7}#P#o)m#o#pDs#p#q)m#q#r8l#r;'S)m;'S;=`Kg<%lO)m:YLxZ&^7[&WW&f#tOrLorsMks#OLo#O#P! Z#P#oLo#o#p@S#p#qLo#q#r=Q#r;'SLo;'S;=`!!o<%lOLo:YMpZ&^7[OrLorsNcs#OLo#O#P! Z#P#oLo#o#p@S#p#qLo#q#r=Q#r;'SLo;'S;=`!!o<%lOLo:YNhZ&^7[OrLors/cs#OLo#O#P! Z#P#oLo#o#p@S#p#qLo#q#r=Q#r;'SLo;'S;=`!!o<%lOLo:Y! `W&^7[O#oLo#o#p=Q#p#qLo#q#r=Q#r;'SLo;'S;=`! x;=`<%l=Q<%lOLo:Y!!PY&WW&f#tOr=Qrs=ts#O=Q#O#P?P#P#o=Q#o#p@S#p;'S=Q;'S;=`C`;=`<%lLo<%lO=Q:Y!!rP;=`<%lLoV#P#o!=X#o#p!7s#p#q!=X#q#r!5x#r;'S!=X;'S;=`!?m<%lO!=X:z!>[W&^7[O#o!=X#o#p!5x#p#q!=X#q#r!5x#r;'S!=X;'S;=`!>t;=`<%l!5x<%lO!=X:z!>}Y&WW&ap&f#tOr!5xrs=ts#O!5x#O#P!6n#P#o!5x#o#p!7s#p;'S!5x;'S;=`!8e;=`<%l!=X<%lO!5x:z!?pP;=`<%l!=Xds#O=Q#O#P?P#P#o=Q#o#p@S#p;'S=Q;'S;=`C`<%lO=Q/V#,nRO;'S#*w;'S;=`#,w;=`O#*w/V#-Q^&WW&R,X&f#tOY#*wYZ=QZ]#*w]^=Q^r#*wrs#+ys#O#*w#O#P#,k#P#o#*w#o#p#-|#p;'S#*w;'S;=`#1q;=`<%l#*w<%lO#*w/V#.T]&WW&R,XOY#.|YZ@tZ]#.|]^@t^r#.|rs#/vs#O#.|#O#P#0b#P#o#.|#o#p#*w#p;'S#.|;'S;=`#1k<%lO#.|,a#/TZ&WW&R,XOY#.|YZ@tZ]#.|]^@t^r#.|rs#/vs#O#.|#O#P#0b#P;'S#.|;'S;=`#1k<%lO#.|,a#/{V&R,XOr@trsAxs#O@t#O#PB_#P;'S@t;'S;=`CY<%lO@t,a#0eRO;'S#.|;'S;=`#0n;=`O#.|,a#0u[&WW&R,XOY#.|YZ@tZ]#.|]^@t^r#.|rs#/vs#O#.|#O#P#0b#P;'S#.|;'S;=`#1k;=`<%l#.|<%lO#.|,a#1nP;=`<%l#.|/V#1tP;=`<%l#*w0m#1zRO;'S#&_;'S;=`#2T;=`O#&_0m#2b`&TS&WW&R,X&d!b&f#tOY#&_YZ8lZ]#&_]^8l^r#&_rs#'ksw#&_wx#(gx#O#&_#O#P#1w#P#o#&_#o#p#3d#p;'S#&_;'S;=`#9y;=`<%l#&_<%lO#&_0m#3m_&TS&WW&R,XOY#4lYZEmZ]#4l]^Em^r#4lrs#5nsw#4lwx#6bx#O#4l#O#P#8b#P#o#4l#o#p#&_#p;'S#4l;'S;=`#9s<%lO#4l,e#4u]&TS&WW&R,XOY#4lYZEmZ]#4l]^Em^r#4lrs#5nsw#4lwx#6bx#O#4l#O#P#8b#P;'S#4l;'S;=`#9s<%lO#4l,e#5uX&TS&R,XOrEmrsGRswEmwxGsx#OEm#O#PIV#P;'SEm;'S;=`JY<%lOEm,e#6i]&WW&R,XOY#4lYZEmZ]#4l]^Em^r#4lrs#5nsw#4lwx#7bx#O#4l#O#P#8b#P;'S#4l;'S;=`#9s<%lO#4l,e#7i]&WW&R,XOY#4lYZEmZ]#4l]^Em^r#4lrs#5nsw#4lwx#.|x#O#4l#O#P#8b#P;'S#4l;'S;=`#9s<%lO#4l,e#8eRO;'S#4l;'S;=`#8n;=`O#4l,e#8w^&TS&WW&R,XOY#4lYZEmZ]#4l]^Em^r#4lrs#5nsw#4lwx#6bx#O#4l#O#P#8b#P;'S#4l;'S;=`#9s;=`<%l#4l<%lO#4l,e#9vP;=`<%l#4l0m#9|P;=`<%l#&_Fy#:^`&TS&WW&R,X&d!b&f#tOY#&_YZ8lZ]#&_]^8l^r#&_rs#'ksw#&_wx#(gx#O#&_#O#P#1w#P#o#&_#o#p#3d#p;'S#&_;'S;=`#9y;=`<%l##W<%lO#&_Fy#;cP;=`<%l##WFy#;qa&^7[&WW&R,X&f#tOY##WYZ)mZ]##W]^)m^r##Wrs#$lsw##Wwx#Qs#O#z#P#o#XZ&^7[&R,XOrLorsNcs#OLo#O#P! Z#P#oLo#o#p@S#p#qLo#q#r=Q#r;'SLo;'S;=`!!o<%lOLoEc#?PW&^7[O#o#ds#O$=b#O#P$@`#P#o$=b#o#p$At#p;'S$=b;'S;=`$Fp<%lO$=b4q$>i]Q1sOY$=bYZ=QZ]$=b]^=Q^r$=brs$?bs#O$=b#O#P$@`#P#o$=b#o#p$At#p;'S$=b;'S;=`$Fp<%lO$=b4q$?g]Q1sOY$=bYZ=QZ]$=b]^=Q^r$=brs$*gs#O$=b#O#P$@`#P#o$=b#o#p$At#p;'S$=b;'S;=`$Fp<%lO$=b4q$@eWQ1sOY$=bYZ=QZ]$=b]^=Q^;'S$=b;'S;=`$@};=`<%l=Q<%lO$=b4q$AUY&WW&f#tOr=Qrs=ts#O=Q#O#P?P#P#o=Q#o#p@S#p;'S=Q;'S;=`C`;=`<%l$=b<%lO=Q4q$A{]Q1s&WWOY$BtYZ@tZ]$Bt]^@t^r$Btrs$Cns#O$Bt#O#P$E^#P#o$Bt#o#p$=b#p;'S$Bt;'S;=`$Fj<%lO$Bt1{$B{ZQ1s&WWOY$BtYZ@tZ]$Bt]^@t^r$Btrs$Cns#O$Bt#O#P$E^#P;'S$Bt;'S;=`$Fj<%lO$Bt1{$CsZQ1sOY$BtYZ@tZ]$Bt]^@t^r$Btrs$Dfs#O$Bt#O#P$E^#P;'S$Bt;'S;=`$Fj<%lO$Bt1{$DkZQ1sOY$BtYZ@tZ]$Bt]^@t^r$Btrs$*gs#O$Bt#O#P$E^#P;'S$Bt;'S;=`$Fj<%lO$Bt1{$EcWQ1sOY$BtYZ@tZ]$Bt]^@t^;'S$Bt;'S;=`$E{;=`<%l@t<%lO$Bt1{$FQW&WWOr@trsA`s#O@t#O#PB_#P;'S@t;'S;=`CY;=`<%l$Bt<%lO@t1{$FmP;=`<%l$Bt4q$FsP;=`<%l$=b6X$F{WQ1sOY$7dYZ8lZ]$7d]^8l^;'S$7d;'S;=`$Ge;=`<%l8l<%lO$7d6X$Gp[&TS&WW&d!b&f#tOr8lrs9jsw8lwx;^x#O8l#O#PCf#P#o8l#o#pDs#p;'S8l;'S;=`J`;=`<%l$7d<%lO8l6X$Ho_Q1s&TS&WWOY$InYZEmZ]$In]^Em^r$Inrs$Jpsw$Inwx$Lpx#O$In#O#P$Np#P#o$In#o#p$7d#p;'S$In;'S;=`%!U<%lO$In2P$Iw]Q1s&TS&WWOY$InYZEmZ]$In]^Em^r$Inrs$Jpsw$Inwx$Lpx#O$In#O#P$Np#P;'S$In;'S;=`%!U<%lO$In2P$Jw]Q1s&TSOY$InYZEmZ]$In]^Em^r$Inrs$Kpsw$Inwx$Lpx#O$In#O#P$Np#P;'S$In;'S;=`%!U<%lO$In2P$Kw]Q1s&TSOY$InYZEmZ]$In]^Em^r$Inrs$1hsw$Inwx$Lpx#O$In#O#P$Np#P;'S$In;'S;=`%!U<%lO$In2P$Lw]Q1s&WWOY$InYZEmZ]$In]^Em^r$Inrs$Jpsw$Inwx$Mpx#O$In#O#P$Np#P;'S$In;'S;=`%!U<%lO$In2P$Mw]Q1s&WWOY$InYZEmZ]$In]^Em^r$Inrs$Jpsw$Inwx$Btx#O$In#O#P$Np#P;'S$In;'S;=`%!U<%lO$In2P$NuWQ1sOY$InYZEmZ]$In]^Em^;'S$In;'S;=`% _;=`<%lEm<%lO$In2P% fY&TS&WWOrEmrsFaswEmwxGsx#OEm#O#PIV#P;'SEm;'S;=`JY;=`<%l$In<%lOEm2P%!XP;=`<%l$In6X%!_P;=`<%l$7dLe%!m[&TS&WW&d!b&f#tOr8lrs9jsw8lwx;^x#O8l#O#PCf#P#o8l#o#pDs#p;'S8l;'S;=`J`;=`<%l$!P<%lO8lLe%#fP;=`<%l$!PLe%#taQ1s&^7[&WW&f#tOY$!PYZ)mZ]$!P]^)m^r$!Prs$#esw$!Pwx%$yx#O$!P#O#P$6g#P#o$!P#o#p$Hf#p#q$!P#q#r$7d#r;'S$!P;'S;=`%#c<%lO$!PJ}%%U_Q1s&^7[&WW&f#tOY%$yYZLoZ]%$y]^Lo^r%$yrs%&Ts#O%$y#O#P%(a#P#o%$y#o#p$At#p#q%$y#q#r$=b#r;'S%$y;'S;=`%*T<%lO%$yJ}%&[_Q1s&^7[OY%$yYZLoZ]%$y]^Lo^r%$yrs%'Zs#O%$y#O#P%(a#P#o%$y#o#p$At#p#q%$y#q#r$=b#r;'S%$y;'S;=`%*T<%lO%$yJ}%'b_Q1s&^7[OY%$yYZLoZ]%$y]^Lo^r%$yrs$)ms#O%$y#O#P%(a#P#o%$y#o#p$At#p#q%$y#q#r$=b#r;'S%$y;'S;=`%*T<%lO%$yJ}%(h[Q1s&^7[OY%$yYZLoZ]%$y]^Lo^#o%$y#o#p$=b#p#q%$y#q#r$=b#r;'S%$y;'S;=`%)^;=`<%l=Q<%lO%$yJ}%)eY&WW&f#tOr=Qrs=ts#O=Q#O#P?P#P#o=Q#o#p@S#p;'S=Q;'S;=`C`;=`<%l%$y<%lO=QJ}%*WP;=`<%l%$yLu%*b[Q1s&^7[OY#MXYZ'cZ]#MX]^'c^#o#MX#o#p%+W#p#q#MX#q#r%+W#r;'S#MX;'S;=`%5l;=`<%l!#d<%lO#MX6i%+g_Q1s&TS&WW&Z`&d!b&f#tOY%+WYZ!#dZ]%+W]^!#d^r%+Wrs%,fsw%+Wwx$;Qx#O%+W#O#P%2l#P#o%+W#o#p%4^#p;'S%+W;'S;=`%5f<%lO%+W6i%,q_Q1s&TS&Z`&d!bOY%+WYZ!#dZ]%+W]^!#d^r%+Wrs%-psw%+Wwx$;Qx#O%+W#O#P%2l#P#o%+W#o#p%4^#p;'S%+W;'S;=`%5f<%lO%+W6i%-{_Q1s&TS&Z`&d!bOY%+WYZ!#dZ]%+W]^!#d^r%+Wrs%.zsw%+Wwx$;Qx#O%+W#O#P%2l#P#o%+W#o#p%4^#p;'S%+W;'S;=`%5f<%lO%+W3k%/V]Q1s&TS&Z`&d!bOY%.zYZ!&[Z]%.z]^!&[^w%.zwx$-Wx#O%.z#O#P%0O#P#o%.z#o#p%1f#p;'S%.z;'S;=`%2f<%lO%.z3k%0TWQ1sOY%.zYZ!&[Z]%.z]^!&[^;'S%.z;'S;=`%0m;=`<%l!&[<%lO%.z3k%0vY&TS&Z`&d!bOw!&[wx1`x#O!&[#O#P!'Q#P#o!&[#o#p!(V#p;'S!&[;'S;=`!(w;=`<%l%.z<%lO!&[3k%1m]Q1s&TSOY$1hYZ4`Z]$1h]^4`^w$1hwx$2bx#O$1h#O#P$4Q#P#o$1h#o#p%.z#p;'S$1h;'S;=`$5^<%lO$1h3k%2iP;=`<%l%.z6i%2qWQ1sOY%+WYZ!#dZ]%+W]^!#d^;'S%+W;'S;=`%3Z;=`<%l!#d<%lO%+W6i%3h[&TS&WW&Z`&d!b&f#tOr!#drs!$dsw!#dwx;^x#O!#d#O#P!(}#P#o!#d#o#p!*^#p;'S!#d;'S;=`!+W;=`<%l%+W<%lO!#d6i%4g_Q1s&TS&WWOY$InYZEmZ]$In]^Em^r$Inrs$Jpsw$Inwx$Lpx#O$In#O#P$Np#P#o$In#o#p%+W#p;'S$In;'S;=`%!U<%lO$In6i%5iP;=`<%l%+WLu%5y[&TS&WW&Z`&d!b&f#tOr!#drs!$dsw!#dwx;^x#O!#d#O#P!(}#P#o!#d#o#p!*^#p;'S!#d;'S;=`!+W;=`<%l#MX<%lO!#dLu%6rP;=`<%l#MXLu%7SaQ1s&^7[&TS&Z`&d!bOY#MXYZ'cZ]#MX]^'c^r#MXrs%8Xsw#MXwx#Nox#O#MX#O#P%*Z#P#o#MX#o#p%4^#p#q#MX#q#r%+W#r;'S#MX;'S;=`%6o<%lO#MXIw%8f_Q1s&^7[&TS&Z`&d!bOY%8XYZ!-kZ]%8X]^!-k^w%8Xwx$'ax#O%8X#O#P%9e#P#o%8X#o#p%1f#p#q%8X#q#r%.z#r;'S%8X;'S;=`%;Z<%lO%8XIw%9l[Q1s&^7[OY%8XYZ!-kZ]%8X]^!-k^#o%8X#o#p%.z#p#q%8X#q#r%.z#r;'S%8X;'S;=`%:b;=`<%l!&[<%lO%8XIw%:kY&TS&Z`&d!bOw!&[wx1`x#O!&[#O#P!'Q#P#o!&[#o#p!(V#p;'S!&[;'S;=`!(w;=`<%l%8X<%lO!&[Iw%;^P;=`<%l%8XMV%;naQ1s&^7[&WW&ap&f#tOY%Z#P#o%Z#P#o%b[Q1s&^7[OY%ds#O%Bz#O#P%DO#P#o%Bz#o#p%Ef#p;'S%Bz;'S;=`%Ff<%lO%Bz5c%DTWQ1sOY%BzYZ!5xZ]%Bz]^!5x^;'S%Bz;'S;=`%Dm;=`<%l!5x<%lO%Bz5c%DvY&WW&ap&f#tOr!5xrs=ts#O!5x#O#P!6n#P#o!5x#o#p!7s#p;'S!5x;'S;=`!8e;=`<%l%Bz<%lO!5x5c%Em]Q1s&WWOY$BtYZ@tZ]$Bt]^@t^r$Btrs$Cns#O$Bt#O#P$E^#P#o$Bt#o#p%Bz#p;'S$Bt;'S;=`$Fj<%lO$Bt5c%FiP;=`<%l%Bz6y%FqWQ1sOY%?WYZ!3QZ]%?W]^!3Q^;'S%?W;'S;=`%GZ;=`<%l!3Q<%lO%?W6y%Gh[&TS&WW&ap&d!b&f#tOr!3Qrs9jsw!3Qwx!4Qx#O!3Q#O#P!8k#P#o!3Q#o#p!9z#p;'S!3Q;'S;=`!:t;=`<%l%?W<%lO!3Q6y%Hg_Q1s&TS&WWOY$InYZEmZ]$In]^Em^r$Inrs$Jpsw$Inwx$Lpx#O$In#O#P$Np#P#o$In#o#p%?W#p;'S$In;'S;=`%!U<%lO$In6y%IiP;=`<%l%?WMV%Iy[&TS&WW&ap&d!b&f#tOr!3Qrs9jsw!3Qwx!4Qx#O!3Q#O#P!8k#P#o!3Q#o#p!9z#p;'S!3Q;'S;=`!:t;=`<%l%Z#P#o%Ox#O&3b#O#P&>z#P#o&3b#o#p&@g#p;'S&3b;'S;=`&F|<%lO&3b0m&4w_&TS&R,X&d!bOY&3bYZ8lZ]&3b]^8l^r&3brs&5vsw&3bwx&>Ox#O&3b#O#P&>z#P#o&3b#o#p&@g#p;'S&3b;'S;=`&F|<%lO&3b0m&6P_&TS&R,X&d!bOY&3bYZ8lZ]&3b]^8l^r&3brs&7Osw&3bwx&>Ox#O&3b#O#P&>z#P#o&3b#o#p&@g#p;'S&3b;'S;=`&F|<%lO&3b-o&7X]&TS&R,X&d!bOY&7OYZ0lZ]&7O]^0l^w&7Owx&8Qx#O&7O#O#P&8r#P#o&7O#o#p&:T#p;'S&7O;'S;=`&=x<%lO&7O-o&8VX&R,XOw0lwx2Ox#O0l#O#P2k#P#o0l#o#p3n#p;'S0l;'S;=`6z<%lO0l-o&8uRO;'S&7O;'S;=`&9O;=`O&7O-o&9X^&TS&R,X&d!bOY&7OYZ0lZ]&7O]^0l^w&7Owx&8Qx#O&7O#O#P&8r#P#o&7O#o#p&:T#p;'S&7O;'S;=`&=x;=`<%l&7O<%lO&7O-o&:[]&TS&R,XOY&;TYZ4`Z]&;T]^4`^w&;Twx&;}x#O&;T#O#P&XZ&WW&R,X&f#tOr8lrs9jsw8lwx}RO;'S&3b;'S;=`&?W;=`O&3b0m&?e`&TS&WW&R,X&d!b&f#tOY&3bYZ8lZ]&3b]^8l^r&3brs&4nsw&3bwx&>Ox#O&3b#O#P&>z#P#o&3b#o#p&@g#p;'S&3b;'S;=`&F|;=`<%l&3b<%lO&3b0m&@p_&TS&WW&R,XOY&AoYZEmZ]&Ao]^Em^r&Aors&Bqsw&Aowx&Dqx#O&Ao#O#P&Ee#P#o&Ao#o#p&3b#p;'S&Ao;'S;=`&Fv<%lO&Ao,e&Ax]&TS&WW&R,XOY&AoYZEmZ]&Ao]^Em^r&Aors&Bqsw&Aowx&Dqx#O&Ao#O#P&Ee#P;'S&Ao;'S;=`&Fv<%lO&Ao,e&Bx]&TS&R,XOY&AoYZEmZ]&Ao]^Em^r&Aors&Cqsw&Aowx&Dqx#O&Ao#O#P&Ee#P;'S&Ao;'S;=`&Fv<%lO&Ao,e&Cx]&TS&R,XOY&AoYZEmZ]&Ao]^Em^r&Aors&;Tsw&Aowx&Dqx#O&Ao#O#P&Ee#P;'S&Ao;'S;=`&Fv<%lO&Ao,e&DxX&WW&R,XOrEmrsFaswEmwxHex#OEm#O#PIV#P;'SEm;'S;=`JY<%lOEm,e&EhRO;'S&Ao;'S;=`&Eq;=`O&Ao,e&Ez^&TS&WW&R,XOY&AoYZEmZ]&Ao]^Em^r&Aors&Bqsw&Aowx&Dqx#O&Ao#O#P&Ee#P;'S&Ao;'S;=`&Fv;=`<%l&Ao<%lO&Ao,e&FyP;=`<%l&Ao0m&GPP;=`<%l&3bFy&Ga`&TS&WW&R,X&d!b&f#tOY&3bYZ8lZ]&3b]^8l^r&3brs&4nsw&3bwx&>Ox#O&3b#O#P&>z#P#o&3b#o#p&@g#p;'S&3b;'S;=`&F|;=`<%l&0Z<%lO&3bFy&HfP;=`<%l&0ZFy&Hta&^7[&TS&R,X&d!bOY&0ZYZ)mZ]&0Z]^)m^r&0Zrs&Iysw&0Zwx&1ox#O&0Z#O#P&2s#P#o&0Z#o#p&@g#p#q&0Z#q#r&3b#r;'S&0Z;'S;=`&Hc<%lO&0ZC{&JU_&^7[&TS&R,X&d!bOY&IyYZ,wZ]&Iy]^,w^w&Iywx&KTx#O&Iy#O#P&K}#P#o&Iy#o#p&:T#p#q&Iy#q#r&7O#r;'S&Iy;'S;=`&Mq<%lO&IyC{&K[Z&^7[&R,XOw,wwx.kx#O,w#O#P/}#P#o,w#o#p3n#p#q,w#q#r0l#r;'S,w;'S;=`7w<%lO,wC{&LSW&^7[O#o&Iy#o#p&7O#p#q&Iy#q#r&7O#r;'S&Iy;'S;=`⋘=`<%l&7O<%lO&IyC{&Lu^&TS&R,X&d!bOY&7OYZ0lZ]&7O]^0l^w&7Owx&8Qx#O&7O#O#P&8r#P#o&7O#o#p&:T#p;'S&7O;'S;=`&=x;=`<%l&Iy<%lO&7OC{&MtP;=`<%l&IyGk&NU]&^7[&WW&R,X&ap&f#tOr!1Zrs*ssw!1Zwx!V#P#o!=X#o#p!7s#p#q!=X#q#r!5x#r;'S!=X;'S;=`!?m<%lO!=XG{'*y]f,X&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx#O%T#O#P!?s#P#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%Tc![#O%T#O#P!?s#P#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy'=d_&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!Q%T!Q!['>c![#O%T#O#P!?s#P#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy'>ve!f,V&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!Q%T!Q!['>c![!l%T!l!m'@X!m#O%T#O#P!?s#P#R%T#R#S'>c#S#^%T#^#_'@X#_#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy'@l]!f,V&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx#O%T#O#P!?s#P#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TG{'Axa%iR&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!P%T!P!Q'B}!Q!_%T!_!`&)_!`#O%T#O#P!?s#P#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGz'Cb_%kQ&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!_%T!_!`&)_!`#O%T#O#P!?s#P#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy'Dtw!f,V&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!O%T!O!P'G_!P!Q%T!Q!['Ho![!d%T!d!e'Jw!e!g%T!g!h';e!h!l%T!l!m'@X!m!q%T!q!r'M}!r!z%T!z!{(!}!{#O%T#O#P!?s#P#R%T#R#S'Ho#S#U%T#U#V'Jw#V#X%T#X#Y';e#Y#^%T#^#_'@X#_#c%T#c#d'M}#d#l%T#l#m(!}#m#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy'Gp_&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!Q%T!Q!['9c![#O%T#O#P!?s#P#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy'ISk!f,V&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!O%T!O!P'G_!P!Q%T!Q!['Ho![!g%T!g!h';e!h!l%T!l!m'@X!m#O%T#O#P!?s#P#R%T#R#S'Ho#S#X%T#X#Y';e#Y#^%T#^#_'@X#_#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy'KYb&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!Q%T!Q!R'Lb!R!S'Lb!S#O%T#O#P!?s#P#R%T#R#S'Lb#S#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy'Lub!f,V&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!Q%T!Q!R'Lb!R!S'Lb!S#O%T#O#P!?s#P#R%T#R#S'Lb#S#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy'N`a&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!Q%T!Q!Y( e!Y#O%T#O#P!?s#P#R%T#R#S( e#S#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy( xa!f,V&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!Q%T!Q!Y( e!Y#O%T#O#P!?s#P#R%T#R#S( e#S#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy(#`e&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!Q%T!Q![($q![!c%T!c!i($q!i#O%T#O#P!?s#P#R%T#R#S($q#S#T%T#T#Z($q#Z#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TGy(%Ue!f,V&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!Q%T!Q![($q![!c%T!c!i($q!i#O%T#O#P!?s#P#R%T#R#S($q#S#T%T#T#Z($q#Z#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TMg(&z_y1s&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx!_%T!_!`('y!`#O%T#O#P!?s#P#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TS!u!}(3O!}#O%T#O#P!?s#P#R%T#R#S(3O#S#T%T#T#f(3O#f#g(>S#g#o(3O#o#p!Bu#p#q%T#q#r!@b#r$g%T$g;'S(3O;'S;=`(4v<%lO(3OGZ(7_a&^7[&TS&R,X&Z`&d!bOY!MYYZ'cZ]!MY]^'c^r!MYrs(8dsw!MYwx# vx#O!MY#O#P#@t#P#o!MY#o#p#E^#p#q!MY#q#r#Ac#r;'S!MY;'S;=`#G}<%lO!MYGZ(8q]&^7[&TS&R,X&Z`&d!bOr'crs(9jsw'cwx(kx#O'c#O#P!!u#P#o'c#o#p!*^#p#q'c#q#r!#d#r;'S'c;'S;=`!,a<%lO'cD](9wZ&^7[&TS&V,X&Z`&d!bOw!-kwx-sx#O!-k#O#P!.i#P#o!-k#o#p!(V#p#q!-k#q#r!&[#r;'S!-k;'S;=`!0P<%lO!-kGk(:wa&^7[&WW&R,X&ap&f#tOY&-cYZ!1ZZ]&-c]^!1Z^r&-crs&.ysw&-cwx(;|x#O&-c#O#P&N}#P#o&-c#o#p'%g#p#q&-c#q#r' l#r;'S&-c;'S;=`'(W<%lO&-cGk(V#P#o!=X#o#p!7s#p#q!=X#q#r!5x#r;'S!=X;'S;=`!?m<%lO!=XMg(>ie&^7[&TS&WW&Q&j&Z`&ap&d!b&f#t%m,XOr%Trs(7Qsw%Twx(:jx!Q%T!Q![(3O![!c%T!c!}(3O!}#O%T#O#P!?s#P#R%T#R#S(3O#S#T%T#T#o(3O#o#p!Bu#p#q%T#q#r!@b#r$g%T$g;'S(3O;'S;=`(4v<%lO(3OMg(@ai&^7[&TS&WW&Q&j&Z`&ap&d!b&f#t%m,XOr%Trs(BOsw%Twx(EYx!Q%T!Q![(3O![!c%T!c!t(3O!t!u(Hd!u!}(3O!}#O%T#O#P!?s#P#R%T#R#S(3O#S#T%T#T#f(3O#f#g(Hd#g#o(3O#o#p!Bu#p#q%T#q#r!@b#r$g%T$g;'S(3O;'S;=`(4v<%lO(3OGZ(B]]&^7[&TS&Z`&d!b&`,XOr'crs(CUsw'cwx(kx#O'c#O#P!!u#P#o'c#o#p!*^#p#q'c#q#r!#d#r;'S'c;'S;=`!,a<%lO'cGZ(Ca]&^7[&TS&Z`&d!bOr'crs(DYsw'cwx(kx#O'c#O#P!!u#P#o'c#o#p!*^#p#q'c#q#r!#d#r;'S'c;'S;=`!,a<%lO'cD](DgZ&^7[&TS&e,X&Z`&d!bOw!-kwx-sx#O!-k#O#P!.i#P#o!-k#o#p!(V#p#q!-k#q#r!&[#r;'S!-k;'S;=`!0P<%lO!-kGk(Eg]&^7[&WW&ap&f#t&Y,XOr!1Zrs*ssw!1Zwx(F`x#O!1Z#O#P!2c#P#o!1Z#o#p!9z#p#q!1Z#q#r!3Q#r;'S!1Z;'S;=`!;}<%lO!1ZGk(Fk]&^7[&WW&ap&f#tOr!1Zrs*ssw!1Zwx(Gdx#O!1Z#O#P!2c#P#o!1Z#o#p!9z#p#q!1Z#q#r!3Q#r;'S!1Z;'S;=`!;}<%lO!1ZFT(GqZ&^7[&WW&c,X&ap&f#tOr!=XrsMks#O!=X#O#P!>V#P#o!=X#o#p!7s#p#q!=X#q#r!5x#r;'S!=X;'S;=`!?m<%lO!=XMg(Hye&^7[&TS&WW&Q&j&Z`&ap&d!b&f#t%m,XOr%Trs(BOsw%Twx(EYx!Q%T!Q![(3O![!c%T!c!}(3O!}#O%T#O#P!?s#P#R%T#R#S(3O#S#T%T#T#o(3O#o#p!Bu#p#q%T#q#r!@b#r$g%T$g;'S(3O;'S;=`(4v<%lO(3OMg(Jqm&^7[&TS&WW&Q&j&Z`&ap&d!b&f#t%m,XOr%Trs(7Qsw%Twx(:jx!Q%T!Q![(3O![!c%T!c!h(3O!h!i(Hd!i!t(3O!t!u(>S!u!}(3O!}#O%T#O#P!?s#P#R%T#R#S(3O#S#T%T#T#U(3O#U#V(>S#V#Y(3O#Y#Z(Hd#Z#o(3O#o#p!Bu#p#q%T#q#r!@b#r$g%T$g;'S(3O;'S;=`(4v<%lO(3OG{(MP]!V,X&^7[&TS&WW&Z`&ap&d!b&f#tOr%Trs&_sw%Twx!0Vx#O%T#O#P!?s#P#o%T#o#p!Bu#p#q%T#q#r!@b#r;'S%T;'S;=`!Dz<%lO%TXO[O]||-1}],tokenPrec:7129}),b=new B,y=new Set(["Script","Body","FunctionDefinition","ClassDefinition","LambdaExpression","ForStatement","MatchClause"]);function $(O){return(r,o,S)=>{if(S)return!1;let l=r.node.getChild("VariableName");return l&&o(l,O),!0}}const cO={FunctionDefinition:$("function"),ClassDefinition:$("class"),ForStatement(O,r,o){if(o){for(let S=O.node.firstChild;S;S=S.nextSibling)if(S.name=="VariableName")r(S,"variable");else if(S.name=="in")break}},ImportStatement(O,r){var o,S;let{node:l}=O,P=((o=l.firstChild)===null||o===void 0?void 0:o.name)=="from";for(let s=l.getChild("import");s;s=s.nextSibling)s.name=="VariableName"&&((S=s.nextSibling)===null||S===void 0?void 0:S.name)!="as"&&r(s,P?"variable":"namespace")},AssignStatement(O,r){for(let o=O.node.firstChild;o;o=o.nextSibling)if(o.name=="VariableName")r(o,"variable");else if(o.name==":"||o.name=="AssignOp")break},ParamList(O,r){for(let o=null,S=O.node.firstChild;S;S=S.nextSibling)S.name=="VariableName"&&(!o||!/\*|AssignOp/.test(o.name))&&r(S,"variable"),o=S},CapturePattern:$("variable"),AsPattern:$("variable"),__proto__:null};function _(O,r){let o=b.get(r);if(o)return o;let S=[],l=!0;function P(s,t){let R=O.sliceString(s.from,s.to);S.push({label:R,type:t})}return r.cursor(I.IncludeAnonymous).iterate(s=>{if(s.name){let t=cO[s.name];if(t&&t(s,P,l)||!l&&y.has(s.name))return!1;l=!1}else if(s.to-s.from>8192){for(let t of _(O,s.node))S.push(t);return!1}}),b.set(r,S),S}const X=/^[\w\xa1-\uffff][\w\d\xa1-\uffff]*$/,U=["String","FormatString","Comment","PropertyName"];function fO(O){let r=h(O.state).resolveInner(O.pos,-1);if(U.indexOf(r.name)>-1)return null;let o=r.name=="VariableName"||r.to-r.from<20&&X.test(O.state.sliceDoc(r.from,r.to));if(!o&&!O.explicit)return null;let S=[];for(let l=r;l;l=l.parent)y.has(l.name)&&(S=S.concat(_(O.state.doc,l)));return{options:S,from:o?r.from:O.pos,validFor:X}}const yO=["__annotations__","__builtins__","__debug__","__doc__","__import__","__name__","__loader__","__package__","__spec__","False","None","True"].map(O=>({label:O,type:"constant"})).concat(["ArithmeticError","AssertionError","AttributeError","BaseException","BlockingIOError","BrokenPipeError","BufferError","BytesWarning","ChildProcessError","ConnectionAbortedError","ConnectionError","ConnectionRefusedError","ConnectionResetError","DeprecationWarning","EOFError","Ellipsis","EncodingWarning","EnvironmentError","Exception","FileExistsError","FileNotFoundError","FloatingPointError","FutureWarning","GeneratorExit","IOError","ImportError","ImportWarning","IndentationError","IndexError","InterruptedError","IsADirectoryError","KeyError","KeyboardInterrupt","LookupError","MemoryError","ModuleNotFoundError","NameError","NotADirectoryError","NotImplemented","NotImplementedError","OSError","OverflowError","PendingDeprecationWarning","PermissionError","ProcessLookupError","RecursionError","ReferenceError","ResourceWarning","RuntimeError","RuntimeWarning","StopAsyncIteration","StopIteration","SyntaxError","SyntaxWarning","SystemError","SystemExit","TabError","TimeoutError","TypeError","UnboundLocalError","UnicodeDecodeError","UnicodeEncodeError","UnicodeError","UnicodeTranslateError","UnicodeWarning","UserWarning","ValueError","Warning","ZeroDivisionError"].map(O=>({label:O,type:"type"}))).concat(["bool","bytearray","bytes","classmethod","complex","float","frozenset","int","list","map","memoryview","object","range","set","staticmethod","str","super","tuple","type"].map(O=>({label:O,type:"class"}))).concat(["abs","aiter","all","anext","any","ascii","bin","breakpoint","callable","chr","compile","delattr","dict","dir","divmod","enumerate","eval","exec","exit","filter","format","getattr","globals","hasattr","hash","help","hex","id","input","isinstance","issubclass","iter","len","license","locals","max","min","next","oct","open","ord","pow","print","property","quit","repr","reversed","round","setattr","slice","sorted","sum","vars","zip"].map(O=>({label:O,type:"function"}))),_O=[Q("def ${name}(${params}):\n ${}",{label:"def",detail:"function",type:"keyword"}),Q("for ${name} in ${collection}:\n ${}",{label:"for",detail:"loop",type:"keyword"}),Q("while ${}:\n ${}",{label:"while",detail:"loop",type:"keyword"}),Q("try:\n ${}\nexcept ${error}:\n ${}",{label:"try",detail:"/ except block",type:"keyword"}),Q(`if \${}:
+
+`,{label:"if",detail:"block",type:"keyword"}),Q("if ${}:\n ${}\nelse:\n ${}",{label:"if",detail:"/ else block",type:"keyword"}),Q("class ${name}:\n def __init__(self, ${params}):\n ${}",{label:"class",detail:"definition",type:"keyword"}),Q("import ${module}",{label:"import",detail:"statement",type:"keyword"}),Q("from ${module} import ${names}",{label:"from",detail:"import",type:"keyword"})],UO=G(U,A(yO.concat(_O)));function Y(O,r){let o=O.lineIndent(r.from),S=O.lineAt(O.pos,-1),l=S.from+S.text.length;return/^\s*($|#)/.test(S.text)&&O.node.too?null:o+O.unit}const n=g.define({name:"python",parser:YO.configure({props:[k.add({Body:O=>{var r;return(r=Y(O,O.node))!==null&&r!==void 0?r:O.continue()},IfStatement:O=>/^\s*(else:|elif )/.test(O.textAfter)?O.baseIndent:O.continue(),TryStatement:O=>/^\s*(except |finally:|else:)/.test(O.textAfter)?O.baseIndent:O.continue(),"TupleExpression ComprehensionExpression ParamList ArgList ParenthesizedExpression":T({closing:")"}),"DictionaryExpression DictionaryComprehensionExpression SetExpression SetComprehensionExpression":T({closing:"}"}),"ArrayExpression ArrayComprehensionExpression":T({closing:"]"}),"String FormatString":()=>null,Script:O=>{if(O.pos+/\s*/.exec(O.textAfter)[0].length>=O.node.to){let r=null;for(let o=O.node,S=o.to;o=o.lastChild,!(!o||o.to!=S);)o.type.name=="Body"&&(r=o);if(r){let o=Y(O,r);if(o!=null)return o}}return O.continue()}}),z.add({"ArrayExpression DictionaryExpression SetExpression TupleExpression":v,Body:(O,r)=>({from:O.from+1,to:O.to-(O.to==r.doc.length?0:1)})})]}),languageData:{closeBrackets:{brackets:["(","[","{","'",'"',"'''",'"""'],stringPrefixes:["f","fr","rf","r","u","b","br","rb","F","FR","RF","R","U","B","BR","RB"]},commentTokens:{line:"#"},indentOnInput:/^\s*([\}\]\)]|else:|elif |except |finally:)$/}});function uO(){return new j(n,[n.data.of({autocomplete:fO}),n.data.of({autocomplete:UO})])}export{UO as globalCompletion,fO as localCompletionSource,uO as python,n as pythonLanguage};
diff --git a/docs/assets/index-193f1bc2.js b/docs/assets/index-193f1bc2.js
new file mode 100644
index 00000000..b194166c
--- /dev/null
+++ b/docs/assets/index-193f1bc2.js
@@ -0,0 +1,3337 @@
+import{u as m,r as t,j as n,I as c,b as u}from"./index-46a25777.js";const o=`> Use it online: [Go](https://codesandbox.io/s/elated-khorana-65jmr)
+
+## 🔖 MdPreview Props
+
+This is the props of \`MdPreview\`, which is also part of \`MdEditor\`:
+
+### 📃 modelValue
+
+- **type**: \`string\`
+- **default**: \`''\`
+
+ Markdown content.
+
+ \`\`\`jsx
+
+ \`\`\`
+
+---
+
+### 🛍 theme
+
+- **type**: \`'light' | 'dark'\`
+- **default**: \`'light'\`
+
+ Editor's theme.
+
+ \`\`\`jsx
+
+ \`\`\`
+
+---
+
+### 🎀 className
+
+- **type**: \`string\`
+- **default**: \`''\`
+
+ ...
+
+---
+
+### 🔤 language
+
+- **type**: \`string\`
+- **default**: \`'zh-CN'\`
+
+ Build-in language('zh-CN', 'en-US').
+
+ You can install the existing language also: [md-editor-extension](https://github.com/imzbf/md-editor-extension). Refer to extension library for the usage and the way to contribute~
+
+---
+
+### 🎲 editorId
+
+- **type**: \`string\`
+- **default**: \`'md-editor-rt'\`
+
+ Editor's id, also the html id, it is used when there are two or more editor and server render.
+
+---
+
+### 🔢 showCodeRowNumber
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Show row number for code block or not.
+
+---
+
+### 🔦 previewTheme
+
+- **type**: \`'default' | 'github' | 'vuepress' | 'mk-cute' | 'smart-blue' | 'cyanosis'\`
+- **default**: \`'default'\`
+
+ Preview themes.
+
+ Custom:
+
+ 1. Write css
+
+ \`\`\`css
+ .xxx-theme {
+ color: red;
+ }
+ \`\`\`
+
+ 2. Set \`previewTheme\`
+
+ \`\`\`jsx
+
+ \`\`\`
+
+ For more, refer to [markdown-theme](https://github.com/imzbf/markdown-theme).
+
+---
+
+### 🎅🏻 style
+
+- **type**: \`CSSProperties\`
+- **default**: \`{}\`
+
+ Editor inline style.
+
+---
+
+### ☝️ noMermaid
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ do not want to use \`mermaid\`, set it to \`true\`.
+
+ \`\`\`jsx
+
+ \`\`\`
+
+---
+
+### ❌ noKatex
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Do not want to use \`katex\`, set it to \`true\`.
+
+---
+
+### 🦉 codeTheme
+
+- **type**: \`'atom'|'a11y'|'github'|'gradient'|'kimbie'|'paraiso'|'qtcreator'|'stackoverflow'\`
+- **default**: \`'atom'\`
+
+ Highlight code css name. Get Them from \`highlight.js\`.
+
+ Custom:
+
+ 1. Config \`editorExtensions\`
+
+ \`\`\`js
+ import { config } from 'md-editor-rt';
+
+ config({
+ editorExtensions: {
+ highlight: {
+ css: {
+ atom: {
+ light:
+ 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-light.min.css',
+ dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-dark.min.css'
+ },
+ xxx: {
+ light:
+ 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-light.css',
+ dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-dark.css'
+ }
+ }
+ }
+ }
+ });
+ \`\`\`
+
+ 2. Set \`codeTheme\`
+
+ \`\`\`jsx
+
+ \`\`\`
+
+---
+
+### 🎱 mdHeadingId
+
+- **type**: \`(text: string, level: number, index: number) => string\`
+- **default**: \`(text) => text\`
+
+ Title \`ID\` generator.
+
+ \`\`\`jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const mdHeadingId = (_text, _level, index) => \`heading-\${index}\`;
+
+ export default () => {
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 🐣 sanitize
+
+- **type**: \`(html: string) => string\`
+- **default**: \`(html) => html\`
+
+ Sanitize the html, prevent XSS. When you can be sure that your content is OK, ignore this.
+
+ \`sanitize-html\` example:
+
+ \`\`\`jsx
+ import sanitizeHtml from 'sanitize-html';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const sanitize = (html) => sanitizeHtml(html);
+
+ export default () => {
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 🤞🏼 noIconfont
+
+- **type**: \`boolean\`
+- **default**:\`true\`
+
+ Not append iconfont script, [download](https://at.alicdn.com/t/c/font_2605852_u82y61ve02.js) and import it by yourself.
+
+ \`\`\`jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ import '/assets/iconfont.js';
+
+ export default () => {
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 💅 formatCopiedText
+
+- **type**: \`(text: string) => string\`
+- **default**: \`(text) => text\`
+
+ Format copied code
+
+ \`\`\`jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const formatCopiedText = (text: string) => {
+ return \`\${text} - from md-editor-rt\`;
+ };
+
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 🛁 codeStyleReverse
+
+- **type**: \`boolean\`
+- **default**: \`true\`
+
+ Code style will be reversed to dark while code block of the theme has a dark background.
+
+---
+
+### 🧼 codeStyleReverseList
+
+- **type**: \`Array\`
+- **default**: \`['default', 'mk-cute']\`
+
+ Themes to be reversed.
+
+---
+
+### 🕊 noHighlight
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ never highlight code
+
+---
+
+### 🕊 noImgZoomIn
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Enable the function of enlarging images.
+
+---
+
+## 🔩 MdEditor Props
+
+Except for the same as \`MdPreview\`:
+
+### 💻 pageFullscreen
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Screenfull in web page.
+
+---
+
+### 📱 preview
+
+- **type**: \`boolean\`
+- **default**: \`true\`
+
+ Preview content in editor.
+
+---
+
+### 📀 htmlPreview
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Preview html in editor. Set \`preview\` to \`false\` when \`htmlPreview\` is \`true\`.
+
+---
+
+### 🧱 toolbars
+
+- **type**: \`Array\`
+- **default**: \`[all]\`
+
+ Show contents of toolbar.
+
+ You can sort the toolbar as you like, split tools by \`'-'\`, the left and right toolbars are divided by \`'='\`!
+
+ _[all]_
+
+ \`\`\`js
+ [
+ 'bold',
+ 'underline',
+ 'italic',
+ '-',
+ 'strikeThrough',
+ 'sub',
+ 'sup',
+ 'quote',
+ 'unorderedList',
+ 'orderedList',
+ 'task',
+ '-',
+ 'codeRow',
+ 'code',
+ 'link',
+ 'image',
+ 'table',
+ 'mermaid',
+ 'katex',
+ '-',
+ 'revoke',
+ 'next',
+ 'save',
+ '=',
+ 'pageFullscreen',
+ 'fullscreen',
+ 'preview',
+ 'htmlPreview',
+ 'catalog',
+ 'github'
+ ];
+ \`\`\`
+
+---
+
+### 🧱 toolbarsExclude
+
+- **type**: \`Array\`
+- **default**: \`[]\`
+
+ Don't show some item of toolbars, all keys.
+
+---
+
+### 💪 defToolbars
+
+- **type**: \`Array\`
+- **default**: \`[]\`
+
+ Custom toolbar in \`DropdownToolbar\`, \`NormalToolbar\` or \`ModalToolbar\`. To display them, put index of \`defToolbars\` into \`toolbars\`(this is not standard).
+
+ \`\`\`jsx
+ import { MdEditor, NormalToolbar } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const handler = () => {
+ console.log('NormalToolbar clicked!');
+ };
+
+ export default () => {
+ return (
+
+
+
+ }
+ />
+ ]}
+ />
+ );
+ };
+ \`\`\`
+
+ ![NormalToolbar](https://imzbf.github.io/md-editor-rt/imgs/normal-toolbar.gif)
+
+ ![DropdownToolbar](https://imzbf.github.io/md-editor-rt/imgs/dropdown-toolbar.gif)
+
+ For more info, Get **Internal Components** heading. Get source code of **mark**, **emoji** and **modal preview** at [docs](https://github.com/imzbf/md-editor-rt/tree/docs/src/components) branch.
+
+---
+
+### 🪒 noPrettier
+
+- **type**: \`boolean\`
+- **default**: \`true\`
+
+ Use prettier to beautify content or not.
+
+---
+
+### 🤏 tabWidth
+
+- **type**: \`number\`
+- **default**: \`2\`
+
+ One tab eq some space.
+
+---
+
+### 📅 tableShape
+
+- **type**: \`[number, number]\`
+- **default**: \`[6, 4]\`
+
+ Preset the size of the table, [columns, rows].
+
+ \`\`\`jsx
+
+ \`\`\`
+
+ ![Preview](https://imzbf.github.io/md-editor-rt/imgs/20211216165424.png)
+
+---
+
+### 🪧 placeholder
+
+- **type**: \`string\`
+- **default**: \`''\`
+
+ em-\\_-!
+
+---
+
+### 🦶 footers
+
+- **type**: \`Array<'markdownTotal' \\| '=' \\| 'scrollSwitch' \\| number>\`
+- **default**: \`['markdownTotal', '=', 'scrollSwitch']\`
+
+ Show contents of footer, they are divided by \`'='\`. Set it to [] to hidden footer.
+
+---
+
+### 🦿 defFooters
+
+- **type**: \`Array\`
+- **default**: \`[]\`
+
+ Custom footer.
+
+ [Get](https://github.com/imzbf/md-editor-rt/blob/docs/src/pages/Preview/index.tsx) example code.
+
+---
+
+### ⛵️ scrollAuto
+
+- **type**: \`boolean\`
+- **default**: \`true\`
+
+ Scroll default setting.
+
+---
+
+### 🥹 noUploadImg
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Not show the entrance to upload pictures
+
+ \`\`\`jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 🔬 autoFocus
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Same as \`autofocus\` in native textarea.
+
+---
+
+### 🔩 disabled
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Same as \`disabled\` in native textarea.
+
+---
+
+### 🔒 readOnly
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Same as \`readonly\` in native textarea.
+
+---
+
+### 📏 maxLength
+
+- **type**: \`number\`
+- **default**: \`\`
+
+ Same as \`maxlength\` in native textarea.
+
+---
+
+### 📥 autoDetectCode
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ Auto detect the type of pasted code, only support that copied from \`vscode\`.
+
+---
+
+### 📝 completions
+
+- **type**: \`Array\`
+- **default**: \`[]\`
+
+ Additional completion sources.
+
+ \`\`\`tsx
+ import { useMemo, useState } from 'react';
+ import { CompletionSource } from '@codemirror/autocomplete';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const [t, s] = useState('');
+
+ const completions = useMemo>(() => {
+ return [
+ (context) => {
+ const word = context.matchBefore(/@\\w*/);
+
+ if (word === null || (word.from == word.to && context.explicit)) {
+ return null;
+ }
+
+ return {
+ from: word.from,
+ options: [
+ {
+ label: '@imzbf',
+ type: 'text'
+ }
+ ]
+ };
+ }
+ ];
+ }, []);
+
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 📥 showToolbarName
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ Show toolbar name or not
+
+![](https://imzbf.github.io/md-editor-rt/imgs/showToolbarName.jpg)
+
+---
+
+## 🧵 MdPreview Events
+
+### 🚁 onHtmlChanged
+
+- **type**: \`(h: string) => void\`
+
+ Compile markdown successful event, you can use it to get the html code.
+
+---
+
+### 🗒 onGetCatalog
+
+- **type**: \`(list: HeadList[]) => void\`
+
+ Get catalogue of article.
+
+---
+
+## 🪢 MdEditor Events
+
+Except for the same as \`MdPreview\`:
+
+### 📞 onChange
+
+- **type**: \`(v: string) => void\`
+
+ Content changed event(bind to \`oninput\` of \`textarea\`).
+
+---
+
+### 💾 onSave
+
+- **type**: \`(v: string, h: Promise) => void\`
+
+ Saving content event, \`ctrl+s\` and clicking button will trigger it.
+
+ \`\`\`jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ return (
+ {
+ console.log(v);
+
+ h.then((html) => {
+ console.log(html);
+ });
+ }}
+ />
+ );
+ };
+ \`\`\`
+
+---
+
+### 📸 onUploadImg
+
+- **type**: \`(files: Array, callback: (urls: Array) => void) => void\`
+
+ Uploading picture event, when picture is uploading the modal will not close, please provide right urls to the callback function.
+
+\`\`\`jsx
+import axios from 'axios';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+const onUploadImg = async (files, callback) => {
+ const res = await Promise.all(
+ files.map((file) => {
+ return new Promise((rev, rej) => {
+ const form = new FormData();
+ form.append('file', file);
+
+ axios
+ .post('/api/img/upload', form, {
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+ .then((res) => rev(res))
+ .catch((error) => rej(error));
+ });
+ })
+ );
+
+ callback(res.map((item) => item.data.url));
+};
+
+export default () => {
+ return ;
+};
+\`\`\`
+
+---
+
+### 💀 onError
+
+- **type**: \`(err: { name: 'Cropper' \\| 'fullscreen' \\| 'prettier' \\| 'overlength'; message: string }) => void\`
+
+ Run-Time error event, only be called when \`Cropper\`, \`fullscreen\`, \`prettier\` is not loaded. And content exceeds the length limit error.
+
+ \`\`\`jsx
+ const onError = (err) => {
+ alert(err.message);
+ };
+
+ export default () => ;
+ \`\`\`
+
+---
+
+### 🐾 onBlur
+
+- **type**: \`(event: FocusEvent) => void\`
+
+ Textarea has lost focus.
+
+ \`\`\`jsx
+ const onBlur = (err) => {
+ console.log('onBlur', e);
+ };
+
+ export default () => ;
+ \`\`\`
+
+---
+
+### 🔖 onFocus
+
+- **type**: \`(event: FocusEvent) => void\`
+
+ Textarea has received focus.
+
+---
+
+### 🔖 onInput
+
+- **type**: \`(event: Event) => void\`
+
+ Element gets input.
+
+---
+
+## 🤱🏼 Expose
+
+After 2.5.0, Editor exposes several methods on the instance, used to get or change the internal status of the editor.
+
+\`\`\`jsx
+import React, { useState, useEffect, useRef } from 'react';
+import { MdEditor, ExposeParam } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('#Hello Editor');
+
+ const editorRef = useRef();
+
+ useEffect(() => {
+ editorRef.current?.on('catalog', console.log);
+ }, []);
+
+ return ;
+};
+\`\`\`
+
+### 👂🏼 on
+
+Get the internal state of the editor, including pageFullscreen, fullscreen, preview, htmlPreview, catalog, etc.
+
+- pageFullscreen
+
+ \`\`\`js
+ editorRef.current?.on('pageFullscreen', (status) => console.log(status));
+ \`\`\`
+
+- fullscreen
+ \`\`\`js
+ editorRef.current?.on('fullscreen', (status) => console.log(status));
+ \`\`\`
+- preview
+ \`\`\`js
+ editorRef.current?.on('preview', (status) => console.log(status));
+ \`\`\`
+- htmlPreview
+ \`\`\`js
+ editorRef.current?.on('htmlPreview', (status) => console.log(status));
+ \`\`\`
+- catalog
+ \`\`\`js
+ editorRef.current?.on('catalog', (status) => console.log(status));
+ \`\`\`
+
+---
+
+### 💻 togglePageFullscreen
+
+Toggle status of fullscreen within the page.
+
+\`\`\`js
+editorRef.current?.togglePageFullscreen(true);
+\`\`\`
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 🖥 toggleFullscreen
+
+Toggle status of fullscreen widthin browser.
+
+\`\`\`js
+editorRef.current?.toggleFullscreen(true);
+\`\`\`
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 📖 togglePreview
+
+Toggle status of preview.
+
+\`\`\`js
+editorRef.current?.togglePreview(true);
+\`\`\`
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 📼 toggleHtmlPreview
+
+Toggle status of htmlPreview.
+
+\`\`\`js
+editorRef.current?.toggleHtmlPreview(true);
+\`\`\`
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 🧬 toggleCatalog
+
+Toggle status of catalog.
+
+\`\`\`js
+editorRef.current?.toggleCatalog(true);
+\`\`\`
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 💾 triggerSave
+
+\`\`\`js
+editorRef.current?.triggerSave();
+\`\`\`
+
+---
+
+### 💉 insert
+
+Manually insert content into textarea.
+
+\`\`\`js
+/**
+ * @params selectedText
+ */
+editorRef.current?.insert((selectedText) => {
+ /**
+ * @return targetValue Content to be inserted
+ * @return select Automatically select content
+ * @return deviationStart Start position of the selected content
+ * @return deviationEnd End position of the selected content
+ */
+ return {
+ targetValue: \`\${selectedText}\`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+});
+\`\`\`
+
+---
+
+### 🎯 focus
+
+Focus on the textarea.
+
+\`\`\`ts
+import type { FocusOption } from 'md-editor-rt';
+
+const option: FocusOption | undefined = 'start';
+
+// Cursor position when focusing on textarea, default: position when it last lost focus
+editorRef.current?.focus(option);
+\`\`\`
+
+\`\`\`ts
+type FocusOption =
+ | 'start'
+ | 'end'
+ | {
+ // Start position, default cursor position
+ rangeAnchor?: number;
+ // End position, default cursor position
+ rangeHead?: number;
+ // Cursor position
+ cursorPos: number;
+ };
+\`\`\`
+
+---
+
+## 💴 Config Editor
+
+Use \`config(option: ConfigOption)\` to reconfigure \`markdown-it\` and so on.
+
+### 🦪 codeMirrorExtensions
+
+Customize new extensions based on theme and default extensions f codeMirror.
+
+Example: Editor does not render the line number of textarea by default, this extension needs to be manually added
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+import { lineNumbers } from '@codemirror/view';
+
+config({
+ codeMirrorExtensions(_theme, extensions) {
+ return [...extensions, lineNumbers()];
+ }
+});
+\`\`\`
+
+---
+
+### 🍤 markdownItConfig
+
+Customize extensions, attributes of \`markdown-it\`, etc.
+
+Example: Use \`markdown-it-anchor\` to render a hyperlink symbol to the right of the title
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+import ancher from 'markdown-it-anchor';
+
+config({
+ markdownItConfig(mdit) {
+ mdit.use(ancher, {
+ permalink: true
+ });
+ }
+});
+\`\`\`
+
+---
+
+### 🍤 markdownItPlugins
+
+Select and add built-in plugins to \`markdown-it\`.
+
+Example: Modify the class name of the image.
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+
+config({
+ markdownItPlugins(plugins) {
+ return plugins.map((p) => {
+ if (p.type === 'image') {
+ return {
+ ...p,
+ options: {
+ ...p.options,
+ classes: 'my-class'
+ }
+ };
+ }
+
+ return p;
+ });
+ }
+});
+\`\`\`
+
+---
+
+### 🍙 editorConfig
+
+Add more languages, reset \`mermaid\` template or delay rendering time
+
+#### 🍚 languageUserDefined
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ languageUserDefined: {
+ 'en-US': {
+ toolbarTips: {
+ bold: 'bold',
+ underline: 'underline',
+ italic: 'italic',
+ strikeThrough: 'strikeThrough',
+ title: 'title',
+ sub: 'subscript',
+ sup: 'superscript',
+ quote: 'quote',
+ unorderedList: 'unordered list',
+ orderedList: 'ordered list',
+ codeRow: 'inline code',
+ code: 'block-level code',
+ link: 'link',
+ image: 'image',
+ table: 'table',
+ mermaid: 'mermaid',
+ katex: 'formula',
+ revoke: 'revoke',
+ next: 'undo revoke',
+ save: 'save',
+ prettier: 'prettier',
+ pageFullscreen: 'fullscreen in page',
+ fullscreen: 'fullscreen',
+ preview: 'preview',
+ htmlPreview: 'html preview',
+ catalog: 'catalog',
+ github: 'source code'
+ },
+ titleItem: {
+ h1: 'Lv1 Heading',
+ h2: 'Lv2 Heading',
+ h3: 'Lv3 Heading',
+ h4: 'Lv4 Heading',
+ h5: 'Lv5 Heading',
+ h6: 'Lv6 Heading'
+ },
+ imgTitleItem: {
+ link: 'Add Img Link',
+ upload: 'Upload Img',
+ clip2upload: 'Clip Upload'
+ },
+ linkModalTips: {
+ linkTitle: 'Add Link',
+ imageTitle: 'Add Image',
+ descLabel: 'Desc:',
+ descLabelPlaceHolder: 'Enter a description...',
+ urlLabel: 'Link:',
+ urlLabelPlaceHolder: 'Enter a link...',
+ buttonOK: 'OK'
+ },
+ clipModalTips: {
+ title: 'Crop Image',
+ buttonUpload: 'Upload'
+ },
+ copyCode: {
+ text: 'Copy',
+ successTips: 'Copied!',
+ failTips: 'Copy failed!'
+ },
+ mermaid: {
+ flow: 'flow',
+ sequence: 'sequence',
+ gantt: 'gantt',
+ class: 'class',
+ state: 'state',
+ pie: 'pie',
+ relationship: 'relationship',
+ journey: 'journey'
+ },
+ katex: {
+ inline: 'inline',
+ block: 'block'
+ },
+ footer: {
+ markdownTotal: 'Word Count',
+ scrollAuto: 'Scroll Auto'
+ }
+ }
+ }
+ }
+});
+\`\`\`
+
+#### 🍘 mermaidTemplate
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // mermaid template
+ mermaidTemplate: {
+ flow: \`flow tempalte\`,
+ sequence: \`sequence template\`,
+ gantt: \`gantt template\`,
+ class: \`class template\`,
+ state: \`state template\`,
+ pie: \`pie template\`,
+ relationship: \`relationship template\`,
+ journey: \`journey template\`
+ }
+ }
+});
+\`\`\`
+
+#### 🍥 renderDelay
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // delay rendering time(ms)
+ renderDelay: 0
+ }
+});
+\`\`\`
+
+---
+
+### 🥠 editorExtensions
+
+Config some dependency libraries, like highlight..
+
+\`\`\`typescript
+import { config } from 'md-editor-rt';
+
+config({
+ editorExtensions: { iconfont: 'https://xxx.cc' }
+});
+\`\`\`
+
+
+ [EditorExtensions]
+
+\`\`\`ts
+export interface EditorExtensions {
+ highlight?: {
+ instance?: any;
+ js?: string;
+ css?: {
+ [key: string]: {
+ light: string;
+ dark: string;
+ };
+ };
+ };
+ prettier?: {
+ // >= 2.2.0
+ prettierInstance?: any;
+ parserMarkdownInstance?: any;
+
+ standaloneJs?: string;
+ parserMarkdownJs?: string;
+ };
+ cropper?: {
+ instance?: any;
+ js?: string;
+ css?: string;
+ };
+ iconfont?: string;
+ screenfull?: {
+ instance?: any;
+ js?: string;
+ };
+ mermaid?: {
+ instance?: any;
+ js?: string;
+ };
+ katex?: {
+ instance?: any;
+ js?: string;
+ css?: string;
+ };
+}
+\`\`\`
+
+
+
+---
+
+## 🪡 Shortcut Keys
+
+!!! warning Pay attention
+
+Shortcut keys are only available when the textarea has received focus!
+
+!!!
+
+| key | function | description |
+| --- | --- | --- |
+| TAB | insert space | Insert space, the length eq \`tabWidth\`, default: 2, support multiline |
+| SHIFT + TAB | delete space, setting is the same as Tab | |
+| CTRL + C | copy | When selected, copy the selected content. When not selected, copy the content of the current line |
+| CTRL + X | shear | When selected, cut the selected content. When not selected, cut the current line |
+| CTRL + D | delete | When selected, delete the selected content. When not selected, delete the current line |
+| CTRL + S | save | Trigger \`onSave\` event |
+| CTRL + B | bold text | \`**bold**\` |
+| CTRL + U | underline | \`underline \` |
+| CTRL + I | italic | \`*italic*\` |
+| CTRL + 1-6 | h1-h6 | \`# title\` |
+| CTRL + ↑ | superscript | \`superscript \` |
+| CTRL + ↓ | subscript | \`subscript \` |
+| CTRL + O | ordered list | \`1. ordered list\` |
+| CTRL + L | link | \`[link](https://github.com/imzbf/md-editor-rt)\` |
+| CTRL + Z | withdraw | Withdraw history in editor, not the function of system |
+| CTRL + SHIFT + S | line-through | \`~line-through~\` |
+| CTRL + SHIFT + U | unordered list | \`- unordered list\` |
+| CTRL + SHIFT + C | code block | |
+| CTRL + SHIFT + I | picture | \`![picture](https://imzbf.cc)\` |
+| CTRL + SHIFT + Z | forward | Forward history in editor, not the function of system |
+| CTRL + SHIFT + F | Beautify | |
+| CTRL + ALT + C | code row | |
+| CTRL + SHIFT + ALT + T | table | \`\\|table\\|\` |
+
+## 🪤 Internal components
+
+On-demand import, eg: \`import { DropdownToolbar } from 'md-editor-rt'\`.
+
+After \`v4.3.0\`, \`insert\` will be automatically injected into the component by the editor.
+
+### 🐣 NormalToolbar
+
+- **props**
+
+ - \`title\`: \`string\`, not necessary, title of toolbar.
+ - \`trigger\`: \`ReactNode\`, necessary, it is usually an icon, which is displayed on the toolbar.
+
+- **events**
+
+ - \`onClick\`: \`(e: MouseEvent) => void\`, necessary.
+
+usage:
+
+\`\`\`jsx
+import { useState } from 'react';
+import { MdEditor, NormalToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * \`insert\` will be automatically injected into the component by the editor
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ return (
+
+
+
+ }
+ onClick={() => {
+ insert((selectedText) => {
+ /**
+ * @return targetValue Content to be inserted
+ * @return select Automatically select content
+ * @return deviationStart Start position of the selected content
+ * @return deviationEnd End position of the selected content
+ */
+ return {
+ targetValue: \`==\${selectedText}==\`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ key="mark-toolbar"
+ />
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+\`\`\`
+
+[MarkExtension Source Code](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/MarkExtension/index.tsx)
+
+---
+
+### 🐼 DropdownToolbar
+
+- **props**
+
+ - \`title\`: \`string\`, not necessary, title of toolbar.
+ - \`visible\`: \`boolean\`, necessary.
+ - \`trigger\`: \`ReactNode\`, necessary, it is usually an icon, which is displayed on the toolbar.
+ - \`overlay\`: \`ReactNode\`, necessary, content of dropdown box.
+
+- **events**
+
+ - \`onChange\`: \`(visible: boolean) => void\`, necessary.
+
+usage:
+
+\`\`\`jsx
+import { useState } from 'react';
+import { MdEditor, DropdownToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * \`insert\` will be automatically injected into the component by the editor
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ const [visible, setVisible] = useState(false);
+
+ return (
+
+ {
+ insert((selectedText) => {
+ /**
+ * @return targetValue Content to be inserted
+ * @return select Automatically select content
+ * @return deviationStart Start position of the selected content
+ * @return deviationEnd End position of the selected content
+ */
+ return {
+ targetValue: \`==\${selectedText}==\`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ >
+ option 1
+
+ option 2
+
+ }
+ trigger={
+
+
+
+ }
+ key="emoji-toolbar"
+ />
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+\`\`\`
+
+[EmojiExtension Source Code](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/EmojiExtension/index.tsx)
+
+---
+
+### 🦉 ModalToolbar
+
+- **props**
+
+ - \`title\`: \`string\`, not necessary, title of toolbar.
+ - \`modalTitle\`: \`ReactNode\`, not necessary, title of the Modal.
+ - \`visible\`: \`boolean\`, necessary, visibility of Modal.
+ - \`width\`: \`string\`, not necessary, width of Modal, default \`auto\`.
+ - \`height\`: \`string\`, same as \`width\`.
+ - \`showAdjust\`: \`boolean\`, not necessary, visibility of fullscreen button.
+ - \`isFullscreen\`: \`boolean\`, necessary when \`showAdjust = true\`, status of fullscreen.
+ - \`trigger\`: \`ReactNode\`, necessary, it is usually an icon, which is displayed on the toolbar.
+ - \`children\`: \`ReactNode\`, necessary, content of Modal.
+
+- **events**
+
+ - \`onClick\`: \`() => void\`, necessary.
+ - \`onClose\`: \`() => void\`, necessary, close event.
+ - \`onAdjust\`: \`(val: boolean) => void\`, fullscreen button click event.
+
+\`\`\`jsx
+import { useState } from 'react';
+import { MdEditor, ModalToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * \`insert\` will be automatically injected into the component by the editor
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ const [visible, setVisible] = useState(false);
+ const [isFullscreen, setIsFullscreen] = useState(false);
+
+ return (
+ {
+ setVisible(true);
+ }}
+ onClose={() => {
+ setVisible(false);
+ }}
+ onAdjust={() => {
+ setIsFullscreen((i) => !i);
+ }}
+ trigger={
+
+
+
+ }
+ >
+
+ {
+ insert((selectedText) => {
+ /**
+ * @return targetValue Content to be inserted
+ * @return select Automatically select content
+ * @return deviationStart Start position of the selected content
+ * @return deviationEnd End position of the selected content
+ */
+ return {
+ targetValue: \`==\${selectedText}==\`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ >
+ click me
+
+
+
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+\`\`\`
+
+[ReadExtension Source Code](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/ReadExtension/index.tsx)
+
+---
+
+### 🐻 MdCatalog
+
+- **props**
+
+ - \`editorId\`: \`string\`, necessary, editor's \`editorId\`, used to register listening events.
+ - \`className\`: \`string\`, not necessary.
+ - \`mdHeadingId\`: \`mdHeadingId\`, not necessary, same as editor.
+ - \`scrollElement\`: \`string | HTMLElement\`, not necessary, it is an element selector when its type is string. When using \`MdPreview\`, it is usually set to \`document.documentElement\`.
+ - \`theme\`: 'light' | 'dark', not necessary, provide it when you want to change theme online, it is the same as Editor \`theme\`.
+ - \`offsetTop\`: \`number\`, not necessary, highlight current item of catalogs when title is \`offsetTop\` pixels from the top, default 20.
+ - \`scrollElementOffsetTop\`: \`number\`, not necessary, offsetTop of the scroll container,default 0.
+
+- **events**
+
+ - \`onClick\`: \`(e: MouseEvent, t: TocItem) => void\`, not necessary.
+
+usage:
+
+\`\`\`jsx
+import { MdPreview, MdCatalog } from 'md-editor-rt';
+import 'md-editor-rt/lib/preview.css';
+
+const editorId = 'my-editor';
+
+export default () => {
+ const [state] = useState({
+ text: '# heading',
+ scrollElement: document.documentElement
+ });
+
+ return (
+ <>
+ {/* Ensure that the editorId is the same */}
+
+
+ >
+ );
+};
+\`\`\`
+
+---
+
+### 🛸 MdModal
+
+It is usually used in conjunction with \`DropdownToolbar\`.
+
+- **props**
+
+ - \`title\`: \`ReactNode\`, not necessary, title of Modal.
+ - \`visible\`: \`boolean\`, necessary, visibility of Modal.
+ - \`width\`: \`string\`, not necessary, width of Modal, default \`auto\`.
+ - \`height\`: \`string\`, same as \`width\`.
+ - \`showAdjust\`: \`boolean\`, not necessary, visibility of fullscreen button.
+ - \`isFullscreen\`: \`boolean\`, necessary when \`showAdjust = true\`, status of fullscreen.
+ - \`children\`: \`ReactNode\`, necessary, content of Modal.
+ - \`className\`: \`string\`, not necessary.
+ - \`style\`: \`CSSProperties\`, not necessary.
+
+- **events**
+
+ - \`onClose\`: \`() => void\`, necessary, close event.
+ - \`onAdjust\`: \`(val: boolean) => void\`, fullscreen button click event.
+
+\`\`\`jsx
+import { useState } from 'react';
+import { MdEditor, DropdownToolbar, MdModal } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+/**
+ * \`insert\` will be automatically injected into the component by the editor
+ */
+const MyToolbar = () => {
+ const [visible, setVisible] = useState(false);
+ const [mVisible, setMvisible] = useState(false);
+
+ return (
+
+ {
+ setMvisible(true);
+ }}
+ >
+ option 1
+
+ option 2
+
+ }
+ trigger={
+
+
+
+ }
+ key="modal-toolbar"
+ >
+ {
+ setMvisible(false);
+ }}
+ >
+ Content, Content
+
+
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+\`\`\`
+
+---
+
+## ✍️ Edit This Page
+
+[doc-en-US](https://github.com/imzbf/md-editor-rt/blob/dev-docs/public/doc-en-US.md)
+
+\`\`\`
+
+\`\`\`
+`,r=`> 在线尝试示例:[传送门](https://codesandbox.io/s/elated-khorana-65jmr)。
+
+## 🔖 MdPreview Props
+
+这是预览组件\`MdPreview\`的\`Props\`,它们同样也是\`MdEditor\`的:
+
+### 📃 modelValue
+
+- **类型**:\`string\`
+- **默认值**:\`''\`
+
+ 编辑的内容。
+
+ \`\`\`jsx
+
+ \`\`\`
+
+---
+
+### 🛍 theme
+
+- **类型**:\`'light' | 'dark'\`
+- **默认值**:\`'light'\`
+
+ 编辑器主题。
+
+ \`\`\`jsx
+
+ \`\`\`
+
+---
+
+### 🎀 className
+
+- **类型**:\`string\`
+- **默认值**:\`''\`
+
+ ...
+
+---
+
+### 🔤 language
+
+- **类型**:\`string\`
+- **默认值**:\`'zh-CN'\`
+
+ 内置中英文(\`'zh-CN'\`, \`'en-US'\`),可自行扩展其他语言,同时可覆盖内置的中英文。
+
+ 你也可以使用现成的扩展语言:[md-editor-extension](https://github.com/imzbf/md-editor-extension)。使用及贡献方式见扩展库文档~
+
+---
+
+### 🎲 editorId
+
+- **类型**:\`string\`
+- **默认值**:\`'md-editor-rt'\`
+
+ 编辑器唯一标识,非必须项,服务端渲染时,防止产生服务端与客户端渲染内容不一致错误提示,以及单页面多编辑器时做区别。
+
+---
+
+### 🔢 showCodeRowNumber
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 代码块是否显示行号。
+
+---
+
+### 🔦 previewTheme
+
+- **类型**:\`'default' | 'github' | 'vuepress' | 'mk-cute' | 'smart-blue' | 'cyanosis'\`
+- **默认值**:\`'default'\`
+
+ 预览内容主题,支持自定义。
+
+ 主题自定义方式:
+
+ 1. 编辑 css
+
+ \`\`\`css
+ .xxx-theme {
+ color: red;
+ }
+ \`\`\`
+
+ 2. 设置\`previewTheme\`
+
+ \`\`\`jsx
+
+ \`\`\`
+
+ 参考[markdown-theme](https://github.com/imzbf/markdown-theme)项目。
+
+---
+
+### 🎅🏻 style
+
+- **类型**:\`CSSProperties\`
+- **默认值**:\`{}\`
+
+ 编辑器内联样式。
+
+---
+
+### ☝️ noMermaid
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 如果你不希望使用图表展示内容,可以设置关闭。
+
+\`\`\`jsx
+
+\`\`\`
+
+---
+
+### ❌ noKatex
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 如果你不希望使用数学公式展示内容,可以设置关闭。
+
+\`\`\`jsx
+
+\`\`\`
+
+---
+
+### 🦉 codeTheme
+
+- **类型**:\`'atom'|'a11y'|'github'|'gradient'|'kimbie'|'paraiso'|'qtcreator'|'stackoverflow'\`
+- **默认值**:\`'atom'\`
+
+ 代码块高亮样式名称。
+
+ 你可以添加自己的样式,把该属性设置为你想要的即可,方式如下:
+
+ 1. 配置样式链接
+
+ \`\`\`js
+ import { config } from 'md-editor-rt';
+
+ config({
+ editorExtensions: {
+ highlight: {
+ css: {
+ atom: {
+ light:
+ 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-light.min.css',
+ dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-dark.min.css'
+ },
+ xxx: {
+ light:
+ 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-light.css',
+ dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-dark.css'
+ }
+ }
+ }
+ }
+ });
+ \`\`\`
+
+ 2. 设置\`codeTheme\`
+
+ \`\`\`jsx
+
+ \`\`\`
+
+---
+
+### 🎱 mdHeadingId
+
+- **类型**:\`(text: string, level: number, index: number) => string\`
+- **默认值**:\`(text) => text\`
+
+ 构造标题\`ID\`的生成方式。
+
+ \`\`\`jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const mdHeadingId = (_text, _level, index) => \`heading-\${index}\`;
+
+ export default () => {
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 🐣 sanitize
+
+- **类型**:\`(html: string) => string\`
+- **默认值**:\`(html) => html\`
+
+ 在每次生成 html 后,通过该方法移除危险内容,比如 xss 相关,当你很确定你的内容不会出现类似情况时,不必设置它。
+
+ 使用\`sanitize-html\`演示
+
+ \`\`\`jsx
+ import sanitizeHtml from 'sanitize-html';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const sanitize = (html) => sanitizeHtml(html);
+
+ export default () => {
+ return ;
+ };
+ \`\`\`
+
+ > 为什么不内置到编辑器:由于类似编辑器大多属于自行处理文本,自身即可确认内容是否安全,并不需要该功能。
+
+---
+
+### 🤞🏼 noIconfont
+
+- **类型**:\`boolean\`
+- **默认值**:\`true\`
+
+ 不插入 iconfont 链接,你可以[下载](https://at.alicdn.com/t/c/font_2605852_u82y61ve02.js)到本地自行引入。
+
+ \`\`\`jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ import '/assets/iconfont.js';
+
+ export default () => {
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 💅 formatCopiedText
+
+- **类型**:\`(text: string) => string\`
+- **默认值**:\`(text) => text\`
+
+ 格式化复制代码
+
+ \`\`\`jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const formatCopiedText = (text: string) => {
+ return \`\${text} - from md-editor-rt\`;
+ };
+
+ export default () => {
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 🛁 codeStyleReverse
+
+- **类型**:\`boolean\`
+- **默认值**:\`true\`
+
+ 某些预览主题的代码模块背景是暗色系,将这个属性设置为 true,会自动在该主题下的 light 模式下使用暗色系的代码风格。
+
+---
+
+### 🧼 codeStyleReverseList
+
+- **类型**:\`Array\`
+- **默认值**:\`['default', 'mk-cute']\`
+
+ 需要自动调整的预览主题,已默认包含 default、mk-cute。
+
+---
+
+### 🕊 noHighlight
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 不高亮代码,也不会加载相应的扩展库
+
+---
+
+### 🕊 noImgZoomIn
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 是否关闭编辑器默认的放大功能(\`^4.4.0\`)
+
+---
+
+## 🔩 MdEditor Props
+
+除去和\`MdPreivew\`相同的以外:
+
+### 💻 pageFullscreen
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 页面内全屏。
+
+---
+
+### 📱 preview
+
+- **类型**:\`boolean\`
+- **默认值**:\`true\`
+
+ 是否显示预览。
+
+---
+
+### 📀 htmlPreview
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 是否显示 html 预览。当设置为\`true\`时,需要将\`preview\`设置为\`false\`
+
+ \`\`\`jsx
+
+ \`\`\`
+
+---
+
+### 🧱 toolbars
+
+- **类型**:\`Array\`
+- **默认值**:\`[all]\`
+
+ 选择性展示工具栏,可选内容见下方。
+
+ 你可以随意排序工具栏,通过\`'-'\`分割两个工具,通过\`'='\`实现左右放置!
+
+ _[all]_
+
+ \`\`\`js
+ [
+ 'bold',
+ 'underline',
+ 'italic',
+ '-',
+ 'strikeThrough',
+ 'sub',
+ 'sup',
+ 'quote',
+ 'unorderedList',
+ 'orderedList',
+ 'task',
+ '-',
+ 'codeRow',
+ 'code',
+ 'link',
+ 'image',
+ 'table',
+ 'mermaid',
+ 'katex',
+ '-',
+ 'revoke',
+ 'next',
+ 'save',
+ '=',
+ 'pageFullscreen',
+ 'fullscreen',
+ 'preview',
+ 'htmlPreview',
+ 'catalog',
+ 'github'
+ ];
+
+ // 对应功能名称
+ [
+ '加粗',
+ '下划线',
+ '斜体',
+ '删除线',
+ '下标',
+ '上标',
+ '引用',
+ '无序列表',
+ '有序列表',
+ '任务',
+ '行内代码',
+ '块级代码',
+ '链接',
+ '图片',
+ '表格',
+ '图表',
+ '公式',
+ '后退一步',
+ '前进一步',
+ '保存',
+ '页面内全屏',
+ '屏幕全屏',
+ '内容预览',
+ 'html代码预览',
+ '目录',
+ '源码地址'
+ ];
+ \`\`\`
+
+---
+
+### 🧱 toolbarsExclude
+
+- **类型**:\`Array\`
+- **默认值**:\`[]\`
+
+ 选择性不展示工具栏,内容同上。
+
+---
+
+### 💪 defToolbars
+
+- **类型**:\`Array\`
+- **默认值**:\`[]\`
+
+ 自定义工具栏插槽,通过使用内置的\`NormalToolbar\`普通点击触发事件组件,\`DropdownToolbar\`下拉点击触发事件组件,和\`ModalToolbar\`弹窗组件进行扩展。将\`defToolbars\`插槽中的组件下标穿插在\`toolbars\`实现展示(这并不规范)
+
+ \`\`\`jsx
+ import { MdEditor, NormalToolbar } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const handler = () => {
+ console.log('NormalToolbar clicked!');
+ };
+
+ export default () => {
+ return (
+
+
+
+ }
+ />
+ ]}
+ />
+ );
+ };
+ \`\`\`
+
+ ![普通扩展工具栏](https://imzbf.github.io/md-editor-rt/imgs/normal-toolbar.gif)
+
+ ![下拉扩展工具栏](https://imzbf.github.io/md-editor-rt/imgs/dropdown-toolbar.gif)
+
+ 扩展组件属性参考**内置组件**,使用示例参见[文档分支](https://github.com/imzbf/md-editor-rt/tree/docs/src/components),提供**标记**、**表情**和**弹窗预览**扩展组件。
+
+---
+
+### 🪒 noPrettier
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 是否启用 prettier 优化 md 内容。
+
+---
+
+### 🤏 tabWidth
+
+- **类型**:\`number\`
+- **默认值**:\`2\`
+
+ 编辑器一个 TAB 键等于空格数。
+
+---
+
+### 📅 tableShape
+
+- **类型**:\`[number, number]\`
+- **默认值**:\`[6, 4]\`
+
+ 标题栏添加表格时,预设待选表格大小,第一个代表最大列数,第二个代表最大行数。
+
+\`\`\`jsx
+
+\`\`\`
+
+![表格预设大小预览](https://imzbf.github.io/md-editor-rt/imgs/20211216165424.png)
+
+---
+
+### 🪧 placeholder
+
+- **类型**:\`string\`
+- **默认值**:\`''\`
+
+ 啊这-\\_-!
+
+---
+
+### 🦶 footers
+
+- **类型**:\`Array<'markdownTotal' | '=' | 'scrollSwitch' | number>\`
+- **默认值**:\`['markdownTotal', '=', 'scrollSwitch']\`
+
+ 页脚显示内容,\`'='\`左右分割,设置为\`[]\`不显示页脚。
+
+---
+
+### 🦿 defFooters
+
+- **类型**:\`Array\`
+- **默认值**:\`[]\`
+
+ 自定义扩展页脚。
+
+ 示例代码见[文档页源码](https://github.com/imzbf/md-editor-rt/blob/docs/src/pages/Preview/index.tsx)。
+
+---
+
+### ⛵️ scrollAuto
+
+- **类型**:\`boolean\`
+- **默认值**:\`true\`
+
+ 默认左右同步滚动状态。
+
+---
+
+### 🥹 noUploadImg
+
+- **type**: \`boolean\`
+- **default**: \`false\`
+
+ 工具栏不显示上传图片入口。
+
+ \`\`\`jsx
+
+ \`\`\`
+
+---
+
+### 🔬 autoFocus
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 原生属性,文本区域自动获得焦点。
+
+---
+
+### 🔩 disabled
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 原生属性,禁用文本区域。
+
+---
+
+### 🔒 readOnly
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 原生属性,文本区域为只读。
+
+---
+
+### 📏 maxLength
+
+- **类型**:\`number\`
+- **默认值**:\`\`
+
+ 原生属性,文本区域允许的最大字符数。
+
+---
+
+### 📥 autoDetectCode
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 是否启用自动识别粘贴代码类别,目前仅支持从\`vscode\`复制的内容。
+
+---
+
+### 📝 completions
+
+- **类型**:\`Array\`
+- **默认值**:\`[]\`
+
+ 添加额外的输入自动完成来源。
+
+ \`\`\`tsx
+ import { useMemo, useState } from 'react';
+ import { CompletionSource } from '@codemirror/autocomplete';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const [t, s] = useState('');
+
+ const completions = useMemo>(() => {
+ return [
+ (context) => {
+ const word = context.matchBefore(/@\\w*/);
+
+ if (word === null || (word.from == word.to && context.explicit)) {
+ return null;
+ }
+
+ return {
+ from: word.from,
+ options: [
+ {
+ label: '@imzbf',
+ type: 'text'
+ }
+ ]
+ };
+ }
+ ];
+ }, []);
+
+ return ;
+ };
+ \`\`\`
+
+---
+
+### 📥 showToolbarName
+
+- **类型**:\`boolean\`
+- **默认值**:\`false\`
+
+ 是否在工具栏下面显示对应的文字名称
+
+![](https://imzbf.github.io/md-editor-rt/imgs/showToolbarName.jpg)
+
+---
+
+## 🧵 MdPreview 绑定事件
+
+### 🚁 onHtmlChanged
+
+- **类型**:\`(h: string) => void\`
+
+ html 变化回调事件,用于获取预览 html 代码。
+
+---
+
+### 🗒 onGetCatalog
+
+- **类型**:\`(list: HeadList[]) => void\`
+
+ 动态获取\`markdown\`目录。
+
+---
+
+## 🪢 MdEditor 绑定事件
+
+除去和\`MdPreivew\`相同的以外:
+
+### 📞 onChange
+
+- **类型**:\`(v: string) => void\`
+
+ 内容变化事件(当前与\`textare\`的\`oninput\`事件绑定,每输入一个单字即会触发)。
+
+---
+
+### 💾 onSave
+
+- **类型**:\`(v: string, h: Promise) => void\`
+
+ 保存事件,快捷键与保存按钮均会触发。
+
+ \`\`\`jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ return (
+ {
+ console.log(v);
+
+ h.then((html) => {
+ console.log(html);
+ });
+ }}
+ />
+ );
+ };
+ \`\`\`
+
+---
+
+### 📸 onUploadImg
+
+- **类型**:\`(files: Array, callback: (urls: Array) => void) => void\`
+
+ 上传图片事件,弹窗会等待上传结果,务必将上传后的 urls 作为 callback 入参回传。
+
+\`\`\`jsx
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+import axios from 'axios';
+
+const onUploadImg = async (files, callback) => {
+ const res = await Promise.all(
+ files.map((file) => {
+ return new Promise((rev, rej) => {
+ const form = new FormData();
+ form.append('file', file);
+
+ axios
+ .post('/api/img/upload', form, {
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+ .then((res) => rev(res))
+ .catch((error) => rej(error));
+ });
+ })
+ );
+
+ callback(res.map((item) => item.data.url));
+};
+
+export default () => {
+ return ;
+};
+\`\`\`
+
+---
+
+### 💀 onError
+
+- **类型**:\`(err: { name: 'Cropper' \\| 'fullscreen' \\| 'prettier' \\| 'overlength'; message: string }) => void\`
+
+ 捕获执行错误事件,目前支持\`Cropper\`、\`fullscreen\`、\`prettier\`实例未加载完成操作,以及输入内容超出限制长度的错误。
+
+ \`\`\`jsx
+ const onError = (err) => {
+ alert(err.message);
+ };
+
+ export default () => ;
+ \`\`\`
+
+---
+
+### 🐾 onBlur
+
+- **类型**:\`(event: FocusEvent) => void\`
+
+ 输入框失去焦点时触发事件。
+
+ \`\`\`jsx
+ const onBlur = (err) => {
+ console.log('onBlur', e);
+ };
+
+ export default () => ;
+ \`\`\`
+
+---
+
+### 🔖 onFocus
+
+- **类型**:\`(event: FocusEvent) => void\`
+
+ 输入框获得焦点时触发事件。
+
+---
+
+### 🔖 onInput
+
+- **类型**:\`(event: Event) => void\`
+
+ 输入框键入内容事件。
+
+---
+
+## 🤱🏼 实例暴露
+
+2.5.0 版本之后,编辑器暴露了若干方法在组件实例上,用来快捷监听编辑器内部状态或对调整内部状态。
+
+\`\`\`jsx
+import React, { useState, useEffect, useRef } from 'react';
+import { MdEditor, ExposeParam } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('#Hello Editor');
+
+ const editorRef = useRef();
+
+ useEffect(() => {
+ editorRef.current?.on('catalog', console.log);
+ }, []);
+
+ return ;
+};
+\`\`\`
+
+### 👂🏼 on
+
+监听编辑器内部状态,包括:屏幕全屏、浏览器全屏、预览文本、预览 html、目录等。
+
+- pageFullscreen
+
+ \`\`\`js
+ editorRef.value?.on('pageFullscreen', (status) => console.log(status));
+ \`\`\`
+
+- fullscreen
+ \`\`\`js
+ editorRef.value?.on('fullscreen', (status) => console.log(status));
+ \`\`\`
+- preview
+ \`\`\`js
+ editorRef.value?.on('preview', (status) => console.log(status));
+ \`\`\`
+- htmlPreview
+ \`\`\`js
+ editorRef.value?.on('htmlPreview', (status) => console.log(status));
+ \`\`\`
+- catalog
+ \`\`\`js
+ editorRef.value?.on('catalog', (status) => console.log(status));
+ \`\`\`
+
+---
+
+### 💻 togglePageFullscreen
+
+切换页面内全屏。
+
+\`\`\`js
+editorRef.value?.togglePageFullscreen(true);
+\`\`\`
+
+> 不设置入参切换为相反状态
+
+---
+
+### 🖥 toggleFullscreen
+
+切换屏幕全屏。
+
+\`\`\`js
+editorRef.value?.toggleFullscreen(true);
+\`\`\`
+
+> 不设置入参切换为相反状态
+
+---
+
+### 📖 togglePreview
+
+切换是否显示预览。
+
+\`\`\`js
+editorRef.value?.togglePreview(true);
+\`\`\`
+
+> 不设置入参切换为相反状态
+
+---
+
+### 📼 toggleHtmlPreview
+
+切换是否显示 html 预览。
+
+\`\`\`js
+editorRef.value?.toggleHtmlPreview(true);
+\`\`\`
+
+> 不设置入参切换为相反状态
+
+---
+
+### 🧬 toggleCatalog
+
+切换是否显示目录。
+
+\`\`\`js
+editorRef.value?.toggleCatalog(true);
+\`\`\`
+
+> 不设置入参切换为相反状态
+
+---
+
+### 💾 triggerSave
+
+触发保存。
+
+\`\`\`js
+editorRef.value?.triggerSave();
+\`\`\`
+
+---
+
+### 💉 insert
+
+手动向文本框插入内容。
+
+\`\`\`js
+/**
+ * @params selectedText 选中的内容
+ */
+editorRef.value?.insert((selectedText) => {
+ /**
+ * @return targetValue 待插入内容
+ * @return select 插入后是否自动选中内容
+ * @return deviationStart 插入后选中内容鼠标开始位置
+ * @return deviationEnd 插入后选中内容鼠标结束位置
+ */
+ return {
+ targetValue: \`\${selectedText}\`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+});
+\`\`\`
+
+---
+
+### 🎯 focus
+
+手动聚焦输入框。
+
+\`\`\`ts
+import type { FocusOption } from 'md-editor-rt';
+
+const option: FocusOption | undefined = 'start';
+
+// 聚焦时光标的位置,不提供默认上次失焦时的位置
+editorRef.current?.focus(option);
+\`\`\`
+
+\`\`\`ts
+type FocusOption =
+ | 'start'
+ | 'end'
+ | {
+ // 选中的开始位置,默认光标位置
+ rangeAnchor?: number;
+ // 选中的结束位置,默认光标位置
+ rangeHead?: number;
+ // 光标的位置
+ cursorPos: number;
+ };
+\`\`\`
+
+---
+
+## 💴 配置编辑器
+
+使用\`config(option: ConfigOption)\`方法,可以对构建实例进行定制。
+
+### 🦪 codeMirrorExtensions
+
+根据主题和内部默认的 codeMirror 扩展自定义新的扩展。
+
+使用示例:编辑器默认不显示输入框的行号,需要手动添加扩展
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+import { lineNumbers } from '@codemirror/view';
+
+config({
+ codeMirrorExtensions(_theme, extensions) {
+ return [...extensions, lineNumbers()];
+ }
+});
+\`\`\`
+
+---
+
+### 🍤 markdownItConfig
+
+自定义 markdown-it 核心库扩展、属性等。
+
+使用示例:配置使用\`markdown-it-anchor\`并在标题右侧显示一个超链接符号
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+import ancher from 'markdown-it-anchor';
+
+config({
+ markdownItConfig(mdit) {
+ mdit.use(ancher, {
+ permalink: true
+ });
+ }
+});
+\`\`\`
+
+---
+
+### 🍤 markdownItPlugins
+
+挑选、新增 markdown-it 核心库已预设的扩展。
+
+使用示例:修改图片的类名
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+
+config({
+ markdownItPlugins(plugins) {
+ return plugins.map((p) => {
+ if (p.type === 'image') {
+ return {
+ ...p,
+ options: {
+ ...p.options,
+ classes: 'my-class'
+ }
+ };
+ }
+
+ return p;
+ });
+ }
+});
+\`\`\`
+
+---
+
+### 🍙 editorConfig
+
+编辑器常规配置,语言、\`mermaid\`默认模板、渲染延迟:
+
+#### 🍚 languageUserDefined
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // 语言
+ languageUserDefined: {
+ 'my-lang': {
+ toolbarTips: {
+ bold: '加粗',
+ underline: '下划线',
+ italic: '斜体',
+ strikeThrough: '删除线',
+ title: '标题',
+ sub: '下标',
+ sup: '上标',
+ quote: '引用',
+ unorderedList: '无序列表',
+ orderedList: '有序列表',
+ codeRow: '行内代码',
+ code: '块级代码',
+ link: '链接',
+ image: '图片',
+ table: '表格',
+ mermaid: 'mermaid图',
+ katex: '公式',
+ revoke: '后退',
+ next: '前进',
+ save: '保存',
+ prettier: '美化',
+ pageFullscreen: '浏览器全屏',
+ fullscreen: '屏幕全屏',
+ preview: '预览',
+ htmlPreview: 'html代码预览',
+ catalog: '目录',
+ github: '源码地址'
+ },
+ titleItem: {
+ h1: '一级标题',
+ h2: '二级标题',
+ h3: '三级标题',
+ h4: '四级标题',
+ h5: '五级标题',
+ h6: '六级标题'
+ },
+ imgTitleItem: {
+ link: '添加链接',
+ upload: '上传图片',
+ clip2upload: '裁剪上传'
+ },
+ linkModalTips: {
+ linkTitle: '添加链接',
+ imageTitle: '添加图片',
+ descLabel: '链接描述:',
+ descLabelPlaceHolder: '请输入描述...',
+ urlLabel: '链接地址:',
+ urlLabelPlaceHolder: '请输入链接...',
+ buttonOK: '确定'
+ },
+ clipModalTips: {
+ title: '裁剪图片上传',
+ buttonUpload: '上传'
+ },
+ copyCode: {
+ text: '复制代码',
+ successTips: '已复制!',
+ failTips: '复制失败!'
+ },
+ mermaid: {
+ flow: '流程图',
+ sequence: '时序图',
+ gantt: '甘特图',
+ class: '类图',
+ state: '状态图',
+ pie: '饼图',
+ relationship: '关系图',
+ journey: '旅程图'
+ },
+ katex: {
+ inline: '行内公式',
+ block: '块级公式'
+ },
+ footer: {
+ markdownTotal: '字数',
+ scrollAuto: '同步滚动'
+ }
+ }
+ }
+ }
+});
+\`\`\`
+
+#### 🍘 mermaidTemplate
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // mermaid模板
+ mermaidTemplate: {
+ // 流程图
+ flow: \`flow tempalte\`,
+ // 时序图
+ sequence: \`sequence template\`,
+ // 甘特图
+ gantt: \`gantt template\`,
+ // 类图
+ class: \`class template\`,
+ // 状态图
+ state: \`state template\`,
+ // 饼图
+ pie: \`pie template\`,
+ // 关系图
+ relationship: \`relationship template\`,
+ // 旅程图
+ journey: \`journey template\`
+ }
+ }
+});
+\`\`\`
+
+#### 🍥 renderDelay
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // 输入渲染延迟(ms)
+ renderDelay: 0
+ }
+});
+\`\`\`
+
+---
+
+### 🥠 editorExtensions
+
+类型如下,用于配置编辑器内部的扩展
+
+\`\`\`js
+import { config } from 'md-editor-rt';
+
+config({
+ editorExtensions: { iconfont: 'https://xxx.cc' }
+});
+\`\`\`
+
+
+ [EditorExtensions]
+
+\`\`\`ts
+export interface EditorExtensions {
+ highlight?: {
+ instance?: any;
+ js?: string;
+ css?: {
+ [key: string]: {
+ light: string;
+ dark: string;
+ };
+ };
+ };
+ prettier?: {
+ // >= 2.2.0
+ prettierInstance?: any;
+ parserMarkdownInstance?: any;
+
+ standaloneJs?: string;
+ parserMarkdownJs?: string;
+ };
+ cropper?: {
+ instance?: any;
+ js?: string;
+ css?: string;
+ };
+ iconfont?: string;
+ screenfull?: {
+ instance?: any;
+ js?: string;
+ };
+ mermaid?: {
+ instance?: any;
+ js?: string;
+ };
+ katex?: {
+ instance?: any;
+ js?: string;
+ css?: string;
+ };
+}
+\`\`\`
+
+
+
+---
+
+## 🪡 快捷键
+
+主要以\`CTRL\`搭配对应功能英文单词首字母,冲突项添加\`SHIFT\`,再冲突替换为\`ALT\`。
+
+!!! warning 注意事项
+
+快捷键仅在输入框获取到焦点时可用!
+
+!!!
+
+| 键位 | 功能 | 说明 |
+| --- | --- | --- |
+| TAB | 空格 | 通过\`tabWidth\`属性预设 TAB 键位新增空格长度,默认 2,支持多行 |
+| SHIFT + TAB | 取消空格 | 同上,一次取消两个空格,支持多行 |
+| CTRL + C | 复制 | 选中时复制选中内容,未选中时复制当前行内容 |
+| CTRL + X | 剪切 | 选中时剪切选中内容,未选中时剪切当前行 |
+| CTRL + D | 删除 | 选中时删除选中内容,未选中时删除当前行 |
+| CTRL + S | 保存 | 触发编辑器的\`onSave\`回调 |
+| CTRL + B | 加粗 | \`**加粗**\` |
+| CTRL + U | 下划线 | \`下划线 \` |
+| CTRL + I | 斜体 | \`*斜体*\` |
+| CTRL + 1-6 | 1-6 级标题 | \`# 标题\` |
+| CTRL + ↑ | 上角标 | \`上角标 \` |
+| CTRL + ↓ | 下角标 | \`下角标 \` |
+| CTRL + O | 有序列表 | \`1. 有序列表\` |
+| CTRL + L | 链接 | \`[链接](https://imzbf.cc)\` |
+| CTRL + Z | 撤回 | 触发编辑器内内容撤回,与系统无关 |
+| CTRL + SHIFT + S | 删除线 | \`~删除线~\` |
+| CTRL + SHIFT + U | 无序列表 | \`- 无序列表\` |
+| CTRL + SHIFT + C | 块级代码 | 多行代码块 |
+| CTRL + SHIFT + I | 图片链接 | \`![图片](https://imzbf.cc)\` |
+| CTRL + SHIFT + Z | 前进一步 | 触发编辑器内内容前进,与系统无关 |
+| CTRL + SHIFT + F | 美化内容 | |
+| CTRL + ALT + C | 行内代码 | 行内代码块 |
+| CTRL + SHIFT + ALT + T | 表格 | \`\\|表格\\|\` |
+
+## 🪤 内置组件
+
+按需引用编辑器的扩展组件,例如:\`import { DropdownToolbar } from 'md-editor-rt'\`。
+
+在\`v4.3.0\`以后, \`insert\`方法会由编辑器自动向组件的组件注入。
+
+### 🐣 NormalToolbar
+
+- **props**
+
+ - \`title\`: \`string\`,非必须,作为工具栏上的 hover 提示。
+ - \`trigger\`: \`ReactNode\`,必须,通常是个图标,用来展示在工具栏上。
+
+- **events**
+
+ - \`onClick\`: \`(e: MouseEvent) => void\`,必须,点击事件。
+
+\`\`\`jsx
+import { useState } from 'react';
+import { MdEditor, NormalToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * \`insert\`方法会由编辑器自动向组件的组件注入。
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ return (
+
+
+
+ }
+ onClick={() => {
+ insert((selectedText) => {
+ /**
+ * @return targetValue 待插入内容
+ * @return select 插入后是否自动选中内容
+ * @return deviationStart 插入后选中内容鼠标开始位置
+ * @return deviationEnd 插入后选中内容鼠标结束位置
+ */
+ return {
+ targetValue: \`==\${selectedText}==\`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ key="mark-toolbar"
+ />
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+\`\`\`
+
+[标记组件的源码](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/MarkExtension/index.tsx)
+
+---
+
+### 🐼 DropdownToolbar
+
+- **props**
+
+ - \`title\`: \`string\`,非必须,作为工具栏上的 hover 提示。
+ - \`visible\`: \`boolean\`,必须,下拉状态。
+ - \`trigger\`: \`ReactNode\`,必须,通常是个图标,用来展示在工具栏上。
+ - \`overlay\`: \`ReactNode\`,必须,下拉框中的内容。
+
+- **events**
+
+ - \`onChange\`: \`(visible: boolean) => void\`,必须,状态变化事件。
+
+\`\`\`jsx
+import { useState } from 'react';
+import { MdEditor, DropdownToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * \`insert\`方法会由编辑器自动向组件的组件注入。
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ const [visible, setVisible] = useState(false);
+
+ return (
+
+ {
+ insert((selectedText) => {
+ /**
+ * @return targetValue 待插入内容
+ * @return select 插入后是否自动选中内容
+ * @return deviationStart 插入后选中内容鼠标开始位置
+ * @return deviationEnd 插入后选中内容鼠标结束位置
+ */
+ return {
+ targetValue: \`==\${selectedText}==\`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ >
+ option 1
+
+ option 2
+
+ }
+ trigger={
+
+
+
+ }
+ key="emoji-toolbar"
+ />
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+\`\`\`
+
+[Emoji 组件的源码](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/EmojiExtension/index.tsx)
+
+---
+
+### 🦉 ModalToolbar
+
+- **props**
+
+ - \`title\`: \`string\`,非必须,作为工具栏上的 hover 提示。
+ - \`modalTitle\`: \`ReactNode\`,非必须,弹窗的标题。
+ - \`visible\`: \`boolean\`,必须,弹窗显示状态。
+ - \`width\`: \`string\`,非必须,弹窗宽度,默认\`auto\`。
+ - \`height\`:\`string\`,同\`width\`。
+ - \`showAdjust\`: \`boolean\`,非必须,是否显示弹窗全屏按钮。
+ - \`isFullscreen\`: \`boolean\`,显示全屏按钮时必须,弹窗全屏状态。
+ - \`trigger\`: \`ReactNode\`,必须,通常是个图标,用来展示在工具栏上。
+ - \`children\`: \`ReactNode\`,必须,弹窗中的内容。
+
+- **events**
+
+ - \`onClick\`: \`() => void\`,必须,工具栏点击事件。
+ - \`onClose\`:\`() => void\`,必须,弹窗点击关闭事件。
+ - \`onAdjust\`:\`(val: boolean) => void\`,弹窗全屏按钮点击事件。
+
+\`\`\`jsx
+import { useState } from 'react';
+import { MdEditor, ModalToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * \`insert\`方法会由编辑器自动向组件的组件注入。
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ const [visible, setVisible] = useState(false);
+ const [isFullscreen, setIsFullscreen] = useState(false);
+
+ return (
+ {
+ setVisible(true);
+ }}
+ onClose={() => {
+ setVisible(false);
+ }}
+ onAdjust={() => {
+ setIsFullscreen((i) => !i);
+ }}
+ trigger={
+
+
+
+ }
+ >
+
+ {
+ insert((selectedText) => {
+ /**
+ * @return targetValue 待插入内容
+ * @return select 插入后是否自动选中内容
+ * @return deviationStart 插入后选中内容鼠标开始位置
+ * @return deviationEnd 插入后选中内容鼠标结束位置
+ */
+ return {
+ targetValue: \`==\${selectedText}==\`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ >
+ click me
+
+
+
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+\`\`\`
+
+[阅读组件的源码](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/ReadExtension/index.tsx)
+
+---
+
+### 🐻 MdCatalog
+
+- **props**
+
+ - \`editorId\`: \`string\`,必须,对应编辑器的\`editorId\`,在内部注册目录变化监听事件。
+ - \`className\`: \`string\`,非必须,目录组件最外层类名。
+ - \`mdHeadingId\`: \`mdHeadingId\`,非必须,特殊化编辑器标题的算法,与编辑器相同。
+ - \`scrollElement\`: \`string | HTMLElement\`,非必须,为字符时应是一个元素选择器。仅预览模式中,整页滚动时,设置为\`document.documentElement\`。
+ - \`theme\`: \`'light' | 'dark'\`,非必须,当需要切换主题时提供,同编辑器的\`theme\`。
+ - \`offsetTop\`: \`number\`,非必须,标题距离顶部该像素时高亮当前目录项,默认 20 像素。
+ - \`scrollElementOffsetTop\`: \`number\`,非必须,滚动区域的固定顶部高度,默认 0。
+
+- **events**
+
+ - \`onClick\`: \`(e: MouseEvent, t: TocItem) => void\`,非必须,导航点击事件。
+
+> \`scrollElement\`说明:仅预览下,该元素必须已定位的并且支持滚动。
+
+\`\`\`jsx
+import { MdPreview, MdCatalog } from 'md-editor-rt';
+import 'md-editor-rt/lib/preview.css';
+
+const editorId = 'my-editor';
+
+export default () => {
+ const [state] = useState({
+ text: '# 标题',
+ scrollElement: document.documentElement
+ });
+
+ return (
+ <>
+ {/* 保证editorId是相同的 */}
+
+
+ >
+ );
+};
+\`\`\`
+
+---
+
+### 🛸 MdModal
+
+编辑器内部的弹窗组件,它通常配合下拉工具栏组件使用。
+
+- **props**
+
+ - \`title\`: \`ReactNode\`,非必须,弹窗标题栏。
+ - \`visible\`: \`boolean\`,必须,弹窗显示状态。
+ - \`width\`: \`string\`,非必须,弹窗宽度,默认\`auto\`。
+ - \`height\`: \`string\`,同\`width\`。
+ - \`showAdjust\`: \`boolean\`,非必须,是否显示弹窗全屏按钮。
+ - \`isFullscreen\`: \`boolean\`,显示全屏按钮时必须,弹窗全屏状态。
+ - \`children\`: \`ReactNode\`,非必须,弹窗显示的内容。
+ - \`className\`: \`string\`,非必须,类名。
+ - \`style\`: \`CSSProperties\`,非必须,样式。
+
+- **events**
+
+ - \`onClose\`: \`() => void\`,必须,弹窗点击关闭事件。
+ - \`onAdjust\`: \`(val: boolean) => void\`,弹窗全屏按钮点击事件。
+
+\`\`\`jsx
+import { useState } from 'react';
+import { MdEditor, DropdownToolbar, MdModal } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+/**
+ * \`insert\`方法会由编辑器自动向组件的组件注入。
+ */
+const MyToolbar = () => {
+ const [visible, setVisible] = useState(false);
+ const [mVisible, setMvisible] = useState(false);
+
+ return (
+
+ {
+ setMvisible(true);
+ }}
+ >
+ option 1
+
+ option 2
+
+ }
+ trigger={
+
+
+
+ }
+ key="emoji-toolbar"
+ >
+ {
+ setMvisible(false);
+ }}
+ >
+ Content, Content
+
+
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+\`\`\`
+
+---
+
+## ✍️ 编辑此页面
+
+[doc-zh-CN](https://github.com/imzbf/md-editor-rt/blob/dev-docs/public/doc-zh-CN.md)
+`,i="doc-preview",g=()=>{const e=m(d=>d),[s,l]=t.useState(()=>e.lang==="zh-CN"?r:o),a=()=>{l(e.lang==="en-US"?o:r)};return t.useEffect(a,[e.lang]),n.jsx("div",{className:"container",children:n.jsxs("div",{className:"doc",children:[n.jsx(c,{editorId:i,modelValue:s}),n.jsx(u,{editorId:i})]})})};export{g as default};
diff --git a/docs/assets/index-22368e14.js b/docs/assets/index-22368e14.js
new file mode 100644
index 00000000..40200137
--- /dev/null
+++ b/docs/assets/index-22368e14.js
@@ -0,0 +1 @@
+import{L as O,i as o,y as r,h as n,z as s,s as t,t as e,k as a,m as Q}from"./index-46a25777.js";const $={__proto__:null,anyref:34,dataref:34,eqref:34,externref:34,i31ref:34,funcref:34,i8:34,i16:34,i32:34,i64:34,f32:34,f64:34},P=Q.deserialize({version:14,states:"!^Q]QPOOOqQPO'#CbOOQO'#Cd'#CdOOQO'#Cl'#ClOOQO'#Ch'#ChQ]QPOOOOQO,58|,58|OxQPO,58|OOQO-E6f-E6fOOQO1G.h1G.h",stateData:"!P~O_OSPOSQOS~OTPOVROXROYROZROaQO~OSUO~P]OSXO~P]O",goto:"xaPPPPPPbPbPPPhPPPrXROPTVQTOQVPTWTVXSOPTV",nodeNames:"⚠ LineComment BlockComment Module ) ( App Identifier Type Keyword Number String",maxTerm:17,nodeProps:[["openedBy",4,"("],["closedBy",5,")"],["group",-6,6,7,8,9,10,11,"Expression"]],skippedNodes:[0,1,2],repeatNodeCount:1,tokenData:"/Q~R^XY}YZ}]^}pq}rs!Stu!qxy&Vyz'S{|'X}!O'X!Q!R'b!R![)_!]!^,{#T#o-^~!SO_~~!VTOr!Srs!fs#O!S#O#P!k#P~!S~!kOZ~~!nPO~!S~!tiqr$cst$ctu$cuv$cvw$cwx$cz{$c{|$c}!O$c!O!P$c!P!Q$c!Q![$c![!]$c!^!_$c!_!`$c!`!a$c!a!b$c!b!c$c!c!}$c#Q#R$c#R#S$c#S#T$c#T#o$c#p#q$c#r#s$c~$hiV~qr$cst$ctu$cuv$cvw$cwx$cz{$c{|$c}!O$c!O!P$c!P!Q$c!Q![$c![!]$c!^!_$c!_!`$c!`!a$c!a!b$c!b!c$c!c!}$c#Q#R$c#R#S$c#S#T$c#T#o$c#p#q$c#r#s$c~&[PT~!]!^&_~&bRO!]&_!]!^&k!^~&_~&nTOy&_yz&}z!]&_!]!^&k!^~&_~'SOQ~~'XOS~~'[Q!Q!R'b!R![)_~'gUY~!O!P'y!Q![)_!g!h(j#R#S)s#X#Y(j#l#m)y~(ORY~!Q![(X!g!h(j#X#Y(j~(^SY~!Q![(X!g!h(j#R#S)X#X#Y(j~(mR{|(v}!O(v!Q![(|~(yP!Q![(|~)RQY~!Q![(|#R#S(v~)[P!Q![(X~)dTY~!O!P'y!Q![)_!g!h(j#R#S)s#X#Y(j~)vP!Q![)_~)|R!Q![*V!c!i*V#T#Z*V~*[VY~!O!P*q!Q![*V!c!i*V!r!s+n#R#S)y#T#Z*V#d#e+n~*vTY~!Q![+V!c!i+V!r!s+n#T#Z+V#d#e+n~+[UY~!Q![+V!c!i+V!r!s+n#R#S,o#T#Z+V#d#e+n~+qT{|,Q}!O,Q!Q![,^!c!i,^#T#Z,^~,TR!Q![,^!c!i,^#T#Z,^~,cSY~!Q![,^!c!i,^#R#S,Q#T#Z,^~,rR!Q![+V!c!i+V#T#Z+V~-OP!]!^-R~-WQP~OY-RZ~-R~-ciX~qr-^st-^tu-^uv-^vw-^wx-^z{-^{|-^}!O-^!O!P-^!P!Q-^!Q![-^![!]-^!^!_-^!_!`-^!`!a-^!a!b-^!b!c-^!c!}-^#Q#R-^#R#S-^#S#T-^#T#o-^#p#q-^#r#s-^",tokenizers:[0],topRules:{Module:[0,3]},specialized:[{term:9,get:c=>$[c]||-1}],tokenPrec:0}),i=O.define({name:"wast",parser:P.configure({props:[o.add({App:r({closing:")",align:!1})}),n.add({App:s,BlockComment(c){return{from:c.from+2,to:c.to-2}}}),t({Keyword:e.keyword,Type:e.typeName,Number:e.number,String:e.string,Identifier:e.variableName,LineComment:e.lineComment,BlockComment:e.blockComment,"( )":e.paren})]}),languageData:{commentTokens:{line:";;",block:{open:"(;",close:";)"}},closeBrackets:{brackets:["(",'"']}}});function p(){return new a(i)}export{p as wast,i as wastLanguage};
diff --git a/docs/assets/index-26d6e00c.js b/docs/assets/index-26d6e00c.js
new file mode 100644
index 00000000..c7c86be3
--- /dev/null
+++ b/docs/assets/index-26d6e00c.js
@@ -0,0 +1,31 @@
+import{u as h,r as e,j as i,I as a}from"./index-46a25777.js";const s=`## About md-editor-rt
+
+![](https://img.shields.io/github/stars/imzbf/md-editor-rt?style=social) ![](https://img.shields.io/npm/dm/md-editor-rt) ![](https://img.shields.io/bundlephobia/min/md-editor-rt) ![](https://img.shields.io/github/license/imzbf/md-editor-rt) ![](https://img.shields.io/github/package-json/v/imzbf/md-editor-rt) ![](https://img.shields.io/badge/ssr-%3E1.6.0-brightgreen)
+
+Markdown editor for react, developed in jsx and typescript, dark theme, beautify content by prettier, render articles directly, paste or clip the picture and upload it...
+
+## Same Series
+
+- For vue3, [md-editor-v3](https://github.com/imzbf/md-editor-v3)
+
+## Connect
+
+1. Email:zbfcqtl@gmail.com
+2. Github issue:[github issues](https://github.com/imzbf/md-editor-rt/issues)
+
+I'm not proficient in English, please help me correct wrong grammars.
+`,r=`## 关于 md-editor-rt
+
+![](https://img.shields.io/github/stars/imzbf/md-editor-rt?style=social) ![](https://img.shields.io/npm/dm/md-editor-rt) ![](https://img.shields.io/bundlephobia/min/md-editor-rt) ![](https://img.shields.io/github/license/imzbf/md-editor-rt) ![](https://img.shields.io/github/package-json/v/imzbf/md-editor-rt) ![](https://img.shields.io/badge/ssr-%3E1.6.0-brightgreen)
+
+Markdown 编辑器,react 版本,使用 jsx 和 typescript 语法开发,支持切换主题,支持 prettier 美化文本,支持图片粘贴上传,裁剪上传,支持在 tsx 项目使用。
+
+## 同系列
+
+- vue3 版本,[md-editor-v3](https://github.com/imzbf/md-editor-v3)
+
+## 反馈联系
+
+1. 邮箱:zbfcqtl@gmail.com
+2. issue 管理:[github issues](https://github.com/imzbf/md-editor-rt/issues)
+`,c=()=>{const t=h(m=>m),[d,n]=e.useState(()=>t.lang==="zh-CN"?r:s),o=()=>{n(t.lang==="en-US"?s:r)};return e.useEffect(o,[t.lang]),i.jsx("div",{className:"container",children:i.jsx("div",{className:"doc",children:i.jsx(a,{editorId:"md-about",modelValue:d})})})};export{c as default};
diff --git a/docs/assets/index-270e1636.js b/docs/assets/index-270e1636.js
new file mode 100644
index 00000000..86cdc120
--- /dev/null
+++ b/docs/assets/index-270e1636.js
@@ -0,0 +1 @@
+import{s as r,t as O,m as e,L as s,i as X,f as P,x as S,y as t,h as Z,z as l,k as Y}from"./index-46a25777.js";const o=r({null:O.null,instanceof:O.operatorKeyword,this:O.self,"new super assert open to with void":O.keyword,"class interface extends implements enum var":O.definitionKeyword,"module package import":O.moduleKeyword,"switch while for if else case default do break continue return try catch finally throw":O.controlKeyword,["requires exports opens uses provides public private protected static transitive abstract final strictfp synchronized native transient volatile throws"]:O.modifier,IntegerLiteral:O.integer,FloatingPointLiteral:O.float,"StringLiteral TextBlock":O.string,CharacterLiteral:O.character,LineComment:O.lineComment,BlockComment:O.blockComment,BooleanLiteral:O.bool,PrimitiveType:O.standard(O.typeName),TypeName:O.typeName,Identifier:O.variableName,"MethodName/Identifier":O.function(O.variableName),Definition:O.definition(O.variableName),ArithOp:O.arithmeticOperator,LogicOp:O.logicOperator,BitOp:O.bitwiseOperator,CompareOp:O.compareOperator,AssignOp:O.definitionOperator,UpdateOp:O.updateOperator,Asterisk:O.punctuation,Label:O.labelName,"( )":O.paren,"[ ]":O.squareBracket,"{ }":O.brace,".":O.derefOperator,", ;":O.separator}),n={__proto__:null,true:34,false:34,null:42,void:46,byte:48,short:48,int:48,long:48,char:48,float:48,double:48,boolean:48,extends:62,super:64,class:76,this:78,new:84,public:100,protected:102,private:104,abstract:106,static:108,final:110,strictfp:112,default:114,synchronized:116,native:118,transient:120,volatile:122,throws:150,implements:160,interface:166,enum:176,instanceof:236,open:265,module:267,requires:272,transitive:274,exports:276,to:278,opens:280,uses:282,provides:284,with:286,package:290,import:294,if:306,else:308,while:312,for:316,var:323,assert:330,switch:334,case:340,do:344,break:348,continue:352,return:356,throw:362,try:366,catch:370,finally:378},q=e.deserialize({version:14,states:"#!hQ]QPOOO&tQQO'#H[O(xQQO'#CbOOQO'#Cb'#CbO)PQPO'#CaO)XOSO'#CpOOQO'#Ha'#HaOOQO'#Cu'#CuO*tQPO'#D_O+_QQO'#HkOOQO'#Hk'#HkO-sQQO'#HfO-zQQO'#HfOOQO'#Hf'#HfOOQO'#He'#HeO0OQPO'#DUO0]QPO'#GlO3TQPO'#D_O3[QPO'#DzO)PQPO'#E[O3}QPO'#E[OOQO'#DV'#DVO5]QQO'#H_O7dQQO'#EeO7kQPO'#EdO7pQPO'#EfOOQO'#H`'#H`O5sQQO'#H`O8sQQO'#FgO8zQPO'#EwO9PQPO'#E|O9PQPO'#FOOOQO'#H_'#H_OOQO'#HW'#HWOOQO'#Gf'#GfOOQO'#HV'#HVO:aQPO'#FhOOQO'#HU'#HUOOQO'#Ge'#GeQ]QPOOOOQO'#Hq'#HqO:fQPO'#HqO:kQPO'#D{O:kQPO'#EVO:kQPO'#EQO:sQPO'#HnO;UQQO'#EfO)PQPO'#C`O;^QPO'#C`O)PQPO'#FbO;cQPO'#FdO;nQPO'#FjO;nQPO'#FmO:kQPO'#FrO;sQPO'#FoO9PQPO'#FvO;nQPO'#FxO]QPO'#F}O;xQPO'#GPOyOSO,59[OOQO,59[,59[OOQO'#Hg'#HgO?jQPO,59eO@lQPO,59yOOQO-E:d-E:dO)PQPO,58zOA`QPO,58zO)PQPO,5;|OAeQPO'#DQOAjQPO'#DQOOQO'#Gi'#GiOBjQQO,59jOOQO'#Dm'#DmODRQPO'#HsOD]QPO'#DlODkQPO'#HrODsQPO,5<^ODxQPO,59^OEcQPO'#CxOOQO,59c,59cOEjQPO,59bOGrQQO'#H[OJVQQO'#CbOJmQPO'#D_OKrQQO'#HkOLSQQO,59pOLZQPO'#DvOLiQPO'#HzOLqQPO,5:`OLvQPO,5:`OM^QPO,5;mOMiQPO'#IROMtQPO,5;dOMyQPO,5=WOOQO-E:j-E:jOOQO,5:f,5:fO! aQPO,5:fO! hQPO,5:vO! mQPO,5<^O)PQPO,5:vO:kQPO,5:gO:kQPO,5:qO:kQPO,5:lO:kQPO,5<^O!!^QPO,59qO9PQPO,5:}O!!eQPO,5;QO9PQPO,59TO!!sQPO'#DXOOQO,5;O,5;OOOQO'#El'#ElOOQO'#En'#EnO9PQPO,5;UO9PQPO,5;UO9PQPO,5;UO9PQPO,5;UO9PQPO,5;UO9PQPO,5;UO9PQPO,5;eOOQO,5;h,5;hOOQO,5],5>]O!%SQPO,5:gO!%bQPO,5:qO!%jQPO,5:lO!%uQPO,5>YOLZQPO,5>YO! {QPO,59UO!&QQQO,58zO!&YQQO,5;|O!&bQQO,5_O!.ZQPO,5:WO:kQPO'#GnO!.bQPO,5>^OOQO1G1x1G1xOOQO1G.x1G.xO!.{QPO'#CyO!/kQPO'#HkO!/uQPO'#CzO!0TQPO'#HjO!0]QPO,59dOOQO1G.|1G.|OEjQPO1G.|O!0sQPO,59eO!1QQQO'#H[O!1cQQO'#CbOOQO,5:b,5:bO:kQPO,5:cOOQO,5:a,5:aO!1tQQO,5:aOOQO1G/[1G/[O!1yQPO,5:bO!2[QPO'#GqO!2oQPO,5>fOOQO1G/z1G/zO!2wQPO'#DvO!3YQPO'#D_O!3aQPO1G/zO!!zQPO'#GoO!3fQPO1G1XO9PQPO1G1XO:kQPO'#GwO!3nQPO,5>mOOQO1G1O1G1OOOQO1G0Q1G0QO!3vQPO'#E]OOQO1G0b1G0bO!4gQPO1G1xO! hQPO1G0bO!%SQPO1G0RO!%bQPO1G0]O!%jQPO1G0WOOQO1G/]1G/]O!4lQQO1G.pO7kQPO1G0jO)PQPO1G0jO:sQPO'#HnO!6`QQO1G.pOOQO1G.p1G.pO!6eQQO1G0iOOQO1G0l1G0lO!6lQPO1G0lO!6wQQO1G.oO!7_QQO'#HoO!7lQPO,59sO!8{QQO1G0pO!:dQQO1G0pO!;rQQO1G0pO!UOOQO1G/O1G/OOOQO7+$h7+$hOOQO1G/{1G/{O#1TQQO1G/{OOQO1G/}1G/}O#1YQPO1G/{OOQO1G/|1G/|O:kQPO1G/}OOQO,5=],5=]OOQO-E:o-E:oOOQO7+%f7+%fOOQO,5=Z,5=ZOOQO-E:m-E:mO9PQPO7+&sOOQO7+&s7+&sOOQO,5=c,5=cOOQO-E:u-E:uO#1_QPO'#EUO#1mQPO'#EUOOQO'#Gu'#GuO#2UQPO,5:wOOQO,5:w,5:wOOQO7+'d7+'dOOQO7+%|7+%|OOQO7+%m7+%mO!AYQPO7+%mO!A_QPO7+%mO!AgQPO7+%mOOQO7+%w7+%wO!BVQPO7+%wOOQO7+%r7+%rO!CUQPO7+%rO!CZQPO7+%rOOQO7+&U7+&UOOQO'#Ee'#EeO7kQPO7+&UO7kQPO,5>YO#2uQPO7+$[OOQO7+&T7+&TOOQO7+&W7+&WO9PQPO'#GjO#3TQPO,5>ZOOQO1G/_1G/_O9PQPO7+&kO#3`QQO,59eO#4cQPO'#DrO! pQPO'#DrO#4nQPO'#HwO#4vQPO,5:]O#5aQQO'#HgO#5|QQO'#CuO! mQPO'#HvO#6lQPO'#DpO#6vQPO'#HvO#7XQPO'#DpO#7aQPO'#IPO#7fQPO'#E`OOQO'#Hp'#HpOOQO'#Gk'#GkO#7nQPO,59vOOQO,59v,59vO#7uQPO'#HqOOQO,5:h,5:hO#9]QPO'#H|OOQO'#EP'#EPOOQO,5:i,5:iO#9hQPO'#EYO:kQPO'#EYO#9yQPO'#H}O#:UQPO,5:sO! mQPO'#HvO!!zQPO'#HvO#:^QPO'#DpOOQO'#Gs'#GsO#:eQPO,5:oOOQO,5:o,5:oOOQO,5:n,5:nOOQO,5;S,5;SO#;_QQO,5;SO#;fQPO,5;SOOQO-E:t-E:tOOQO7+&X7+&XOOQO7+)`7+)`O#;mQQO7+)`OOQO'#Gz'#GzO#=ZQPO,5;rOOQO,5;r,5;rO#=bQPO'#FXO)PQPO'#FXO)PQPO'#FXO)PQPO'#FXO#=pQPO7+'UO#=uQPO7+'UOOQO7+'U7+'UO]QPO7+'[O#>QQPO1G1{O! mQPO1G1{O#>`QQO1G1wO!!sQPO1G1wO#>gQPO1G1wO#>nQQO7+'hOOQO'#G}'#G}O#>uQPO,5|QPO'#HqO9PQPO'#F{O#?UQPO7+'oO#?ZQPO,5=OO! mQPO,5=OO#?`QPO1G2iO#@iQPO1G2iOOQO1G2i1G2iOOQO-E:|-E:|OOQO7+'z7+'zO!2[QPO'#G^OpOOQO1G.n1G.nOOQO<X,5>XOOQO,5=S,5=SOOQO-E:f-E:fO#EjQPO7+%gOOQO7+%g7+%gOOQO7+%i7+%iOOQO<cOOQO1G/w1G/wO#IfQPO'#HsO#ImQPO,59xO#IrQPO,5>bO! mQPO,59xO#I}QPO,5:[O#7fQPO,5:zO! mQPO,5>bO!!zQPO,5>bO#7aQPO,5>kOOQO,5:[,5:[OLvQPO'#DtOOQO,5>k,5>kO#JVQPO'#EaOOQO,5:z,5:zO#MWQPO,5:zO!!zQPO'#DxOOQO-E:i-E:iOOQO1G/b1G/bOOQO,5:y,5:yO!!zQPO'#GrO#M]QPO,5>hOOQO,5:t,5:tO#MhQPO,5:tO#MvQPO,5:tO#NXQPO'#GtO#NoQPO,5>iO#NzQPO'#EZOOQO1G0_1G0_O$ RQPO1G0_O! mQPO,5:pOOQO-E:q-E:qOOQO1G0Z1G0ZOOQO1G0n1G0nO$ WQQO1G0nOOQO<oOOQO1G1Y1G1YO$%uQPO'#FTOOQO,5=e,5=eOOQO-E:w-E:wO$%zQPO'#GmO$&XQPO,5>aOOQO1G/u1G/uOOQO<sAN>sO!AYQPOAN>sOOQOAN>xAN>xOOQOAN?[AN?[O7kQPOAN?[O$&pQPO,5:_OOQO1G/x1G/xOOQO,5=[,5=[OOQO-E:n-E:nO$&{QPO,5>eOOQO1G/d1G/dOOQO1G3|1G3|O$'^QPO1G/dOOQO1G/v1G/vOOQO1G0f1G0fO#MWQPO1G0fO#7aQPO'#HyO$'cQPO1G3|O! mQPO1G3|OOQO1G4V1G4VOK^QPO'#DvOJmQPO'#D_OOQO,5:{,5:{O$'nQPO,5:{O$'nQPO,5:{O$'uQQO'#H_O$'|QQO'#H`O$(WQQO'#EbO$(cQPO'#EbOOQO,5:d,5:dOOQO,5=^,5=^OOQO-E:p-E:pOOQO1G0`1G0`O$(kQPO1G0`OOQO,5=`,5=`OOQO-E:r-E:rO$(yQPO,5:uOOQO7+%y7+%yOOQO7+&Y7+&YOOQO1G1_1G1_O$)QQQO1G1_OOQO-E:y-E:yO$)YQQO'#IWO$)TQPO1G1_O$ mQPO1G1_O)PQPO1G1_OOQOAN@[AN@[O$)eQQO<rO$,cQPO7+&yO$,hQQO'#IXOOQOAN@mAN@mO$,sQQOAN@mOOQOAN@iAN@iO$,zQPOAN@iO$-PQQO<sOOQOG26XG26XOOQOG26TG26TOOQO<bPPP>hP@|PPPAv2vPCoPPDjPEaEgPPPPPPPPPPPPFpGXPJ_JgJqKZKaKgMVMZMZMcPMrNx! k! uP!![NxP!!b!!l!!{!#TP!#r!#|!$SNx!$V!$]EaEa!$a!$k!$n2v!&Y2v2v!(RP.^P!(VP!(vPPPPPP.^P.^!)d.^PP.^P.^PP.^!*x!+SPP!+Y!+cPPPPPPPP&}P&}PP!+g!+g!+z!+gPP!+gP!+gP!,e!,hP!+g!-O!+gP!+gP!-R!-UP!+gP!+gP!+gP!+gP!+g!+gP!+gP!-YP!-`!-c!-iP!+g!-u!-x!.Q!.d!2a!2g!2m!3s!3y!4T!5X!5_!5e!5o!5u!5{!6R!6X!6_!6e!6k!6q!6w!6}!7T!7Z!7e!7k!7u!7{PPP!8R!+g!8vP!a!]!^!?q!^!_!@_!_!`!Ax!`!a!Bl!a!b!DY!b!c!Dx!c!}!Kt!}#O!MQ#O#P%Q#P#Q!Mn#Q#R!N[#R#S4e#S#T%Q#T#o4e#o#p# O#p#q# l#q#r##U#r#s##r#s#y%Q#y#z'f#z$f%Q$f$g'f$g#BY%Q#BY#BZ'f#BZ$IS%Q$IS$I_'f$I_$I|%Q$I|$JO'f$JO$JT%Q$JT$JU'f$JU$KV%Q$KV$KW'f$KW&FU%Q&FU&FV'f&FV;'S%Q;'S;=`&s<%lO%QS%VV&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QS%qO&WSS%tVOY&ZYZ%lZr&Zrs&ys;'S&Z;'S;=`'`<%lO&ZS&^VOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QS&vP;=`<%l%QS&|UOY&ZYZ%lZr&Zs;'S&Z;'S;=`'`<%lO&ZS'cP;=`<%l&Z_'mk&WS%wZOX%QXY'fYZ)bZ^'f^p%Qpq'fqr%Qrs%qs#y%Q#y#z'f#z$f%Q$f$g'f$g#BY%Q#BY#BZ'f#BZ$IS%Q$IS$I_'f$I_$I|%Q$I|$JO'f$JO$JT%Q$JT$JU'f$JU$KV%Q$KV$KW'f$KW&FU%Q&FU&FV'f&FV;'S%Q;'S;=`&s<%lO%Q_)iY&WS%wZX^*Xpq*X#y#z*X$f$g*X#BY#BZ*X$IS$I_*X$I|$JO*X$JT$JU*X$KV$KW*X&FU&FV*XZ*^Y%wZX^*Xpq*X#y#z*X$f$g*X#BY#BZ*X$IS$I_*X$I|$JO*X$JT$JU*X$KV$KW*X&FU&FV*XV+TX#sP&WSOY%QYZ%lZr%Qrs%qs!_%Q!_!`+p!`;'S%Q;'S;=`&s<%lO%QU+wV#_Q&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QT,aXOY,|YZ%lZr,|rs3Ys#O,|#O#P2d#P;'S,|;'S;=`3S<%lO,|T-PXOY-lYZ%lZr-lrs.^s#O-l#O#P.x#P;'S-l;'S;=`2|<%lO-lT-qX&WSOY-lYZ%lZr-lrs.^s#O-l#O#P.x#P;'S-l;'S;=`2|<%lO-lT.cVcPOY&ZYZ%lZr&Zrs&ys;'S&Z;'S;=`'`<%lO&ZT.}V&WSOY-lYZ/dZr-lrs1]s;'S-l;'S;=`2|<%lO-lT/iW&WSOY0RZr0Rrs0ns#O0R#O#P0s#P;'S0R;'S;=`1V<%lO0RP0UWOY0RZr0Rrs0ns#O0R#O#P0s#P;'S0R;'S;=`1V<%lO0RP0sOcPP0vTOY0RYZ0RZ;'S0R;'S;=`1V<%lO0RP1YP;=`<%l0RT1`XOY,|YZ%lZr,|rs1{s#O,|#O#P2d#P;'S,|;'S;=`3S<%lO,|T2QUcPOY&ZYZ%lZr&Zs;'S&Z;'S;=`'`<%lO&ZT2gVOY-lYZ/dZr-lrs1]s;'S-l;'S;=`2|<%lO-lT3PP;=`<%l-lT3VP;=`<%l,|T3_VcPOY&ZYZ%lZr&Zrs3ts;'S&Z;'S;=`'`<%lO&ZT3yR&USXY4SYZ4`pq4SP4VRXY4SYZ4`pq4SP4eO&VP_4la%}Z&WSOY%QYZ%lZr%Qrs%qst%Qtu4eu!Q%Q!Q![4e![!c%Q!c!}4e!}#R%Q#R#S4e#S#T%Q#T#o4e#o;'S%Q;'S;=`&s<%lO%QU5xX#gQ&WSOY%QYZ%lZr%Qrs%qs!_%Q!_!`6e!`;'S%Q;'S;=`&s<%lO%QU6lV#]Q&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QV7YZ&lR&WSOY%QYZ%lZr%Qrs%qsv%Qvw7{w!_%Q!_!`6e!`;'S%Q;'S;=`&s<%lO%QU8SV#aQ&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QT8nZ&WSOY9aYZ%lZr9ars:Xsw9awx%Qx#O9a#O#Pt<%lO9aT9fZ&WSOY9aYZ%lZr9ars:Xsw9awx;sx#O9a#O#P t<%lO9aT:[ZOY:}YZ%lZr:}rs>zsw:}wx?px#O:}#O#P@[#P;'S:};'S;=`@t<%lO:}T;QZOY9aYZ%lZr9ars:Xsw9awx;sx#O9a#O#P t<%lO9aT;zVbP&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QTt<%lO9aT=QW&WSOY=jZw=jwx>Vx#O=j#O#P>[#P;'S=j;'S;=`>n<%lO=jP=mWOY=jZw=jwx>Vx#O=j#O#P>[#P;'S=j;'S;=`>n<%lO=jP>[ObPP>_TOY=jYZ=jZ;'S=j;'S;=`>n<%lO=jP>qP;=`<%l=jT>wP;=`<%l9aT>}ZOY:}YZ%lZr:}rs=jsw:}wx?px#O:}#O#P@[#P;'S:};'S;=`@t<%lO:}T?uVbPOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QT@_VOY9aYZ<{Zr9ars:Xs;'S9a;'S;=`>t<%lO9aT@wP;=`<%l:}_ARVZZ&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QVAoVYR&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QVB_X$YP&WS#fQOY%QYZ%lZr%Qrs%qs!_%Q!_!`6e!`;'S%Q;'S;=`&s<%lO%QVCRZ#eR&WSOY%QYZ%lZr%Qrs%qs{%Q{|Ct|!_%Q!_!`6e!`;'S%Q;'S;=`&s<%lO%QVC{V#qR&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QVDiVqR&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QVEV[#eR&WSOY%QYZ%lZr%Qrs%qs}%Q}!OCt!O!_%Q!_!`6e!`!aE{!a;'S%Q;'S;=`&s<%lO%QVFSV&vR&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_FpZWY&WSOY%QYZ%lZr%Qrs%qs!O%Q!O!PGc!P!Q%Q!Q![Hq![;'S%Q;'S;=`&s<%lO%QVGhX&WSOY%QYZ%lZr%Qrs%qs!O%Q!O!PHT!P;'S%Q;'S;=`&s<%lO%QVH[V&oR&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QTHxc&WS`POY%QYZ%lZr%Qrs%qs!Q%Q!Q![Hq![!f%Q!f!gJT!g!hJq!h!iJT!i#R%Q#R#SNk#S#W%Q#W#XJT#X#YJq#Y#ZJT#Z;'S%Q;'S;=`&s<%lO%QTJ[V&WS`POY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QTJv]&WSOY%QYZ%lZr%Qrs%qs{%Q{|Ko|}%Q}!OKo!O!Q%Q!Q![La![;'S%Q;'S;=`&s<%lO%QTKtX&WSOY%QYZ%lZr%Qrs%qs!Q%Q!Q![La![;'S%Q;'S;=`&s<%lO%QTLhc&WS`POY%QYZ%lZr%Qrs%qs!Q%Q!Q![La![!f%Q!f!gJT!g!h%Q!h!iJT!i#R%Q#R#SMs#S#W%Q#W#XJT#X#Y%Q#Y#ZJT#Z;'S%Q;'S;=`&s<%lO%QTMxZ&WSOY%QYZ%lZr%Qrs%qs!Q%Q!Q![La![#R%Q#R#SMs#S;'S%Q;'S;=`&s<%lO%QTNpZ&WSOY%QYZ%lZr%Qrs%qs!Q%Q!Q![Hq![#R%Q#R#SNk#S;'S%Q;'S;=`&s<%lO%Q_! j]&WS#fQOY%QYZ%lZr%Qrs%qsz%Qz{!!c{!P%Q!P!Q!)U!Q!_%Q!_!`6e!`;'S%Q;'S;=`&s<%lO%Q_!!hX&WSOY!!cYZ!#TZr!!crs!$psz!!cz{!&O{;'S!!c;'S;=`!'d<%lO!!c_!#YT&WSOz!#iz{!#{{;'S!#i;'S;=`!$j<%lO!#iZ!#lTOz!#iz{!#{{;'S!#i;'S;=`!$j<%lO!#iZ!$OVOz!#iz{!#{{!P!#i!P!Q!$e!Q;'S!#i;'S;=`!$j<%lO!#iZ!$jOQZZ!$mP;=`<%l!#i_!$sXOY!%`YZ!#TZr!%`rs!'jsz!%`z{!(Y{;'S!%`;'S;=`!)O<%lO!%`_!%cXOY!!cYZ!#TZr!!crs!$psz!!cz{!&O{;'S!!c;'S;=`!'d<%lO!!c_!&TZ&WSOY!!cYZ!#TZr!!crs!$psz!!cz{!&O{!P!!c!P!Q!&v!Q;'S!!c;'S;=`!'d<%lO!!c_!&}V&WSQZOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_!'gP;=`<%l!!c_!'mXOY!%`YZ!#TZr!%`rs!#isz!%`z{!(Y{;'S!%`;'S;=`!)O<%lO!%`_!(]ZOY!!cYZ!#TZr!!crs!$psz!!cz{!&O{!P!!c!P!Q!&v!Q;'S!!c;'S;=`!'d<%lO!!c_!)RP;=`<%l!%`_!)]V&WSPZOY!)UYZ%lZr!)Urs!)rs;'S!)U;'S;=`!*x<%lO!)U_!)wVPZOY!*^YZ%lZr!*^rs!+Os;'S!*^;'S;=`!,R<%lO!*^_!*cVPZOY!)UYZ%lZr!)Urs!)rs;'S!)U;'S;=`!*x<%lO!)U_!*{P;=`<%l!)U_!+TVPZOY!*^YZ%lZr!*^rs!+js;'S!*^;'S;=`!,R<%lO!*^Z!+oSPZOY!+jZ;'S!+j;'S;=`!+{<%lO!+jZ!,OP;=`<%l!+j_!,UP;=`<%l!*^T!,`u&WS_POY%QYZ%lZr%Qrs%qs!O%Q!O!P!.s!P!Q%Q!Q![!0P![!d%Q!d!e!3Z!e!f%Q!f!gJT!g!hJq!h!iJT!i!n%Q!n!o!1u!o!q%Q!q!r!5X!r!z%Q!z!{!7P!{#R%Q#R#S!2c#S#U%Q#U#V!3Z#V#W%Q#W#XJT#X#YJq#Y#ZJT#Z#`%Q#`#a!1u#a#c%Q#c#d!5X#d#l%Q#l#m!7P#m;'S%Q;'S;=`&s<%lO%QT!.za&WS`POY%QYZ%lZr%Qrs%qs!Q%Q!Q![Hq![!f%Q!f!gJT!g!hJq!h!iJT!i#W%Q#W#XJT#X#YJq#Y#ZJT#Z;'S%Q;'S;=`&s<%lO%QT!0Wi&WS_POY%QYZ%lZr%Qrs%qs!O%Q!O!P!.s!P!Q%Q!Q![!0P![!f%Q!f!gJT!g!hJq!h!iJT!i!n%Q!n!o!1u!o#R%Q#R#S!2c#S#W%Q#W#XJT#X#YJq#Y#ZJT#Z#`%Q#`#a!1u#a;'S%Q;'S;=`&s<%lO%QT!1|V&WS_POY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QT!2hZ&WSOY%QYZ%lZr%Qrs%qs!Q%Q!Q![!0P![#R%Q#R#S!2c#S;'S%Q;'S;=`&s<%lO%QT!3`Y&WSOY%QYZ%lZr%Qrs%qs!Q%Q!Q!R!4O!R!S!4O!S;'S%Q;'S;=`&s<%lO%QT!4V`&WS_POY%QYZ%lZr%Qrs%qs!Q%Q!Q!R!4O!R!S!4O!S!n%Q!n!o!1u!o#R%Q#R#S!3Z#S#`%Q#`#a!1u#a;'S%Q;'S;=`&s<%lO%QT!5^X&WSOY%QYZ%lZr%Qrs%qs!Q%Q!Q!Y!5y!Y;'S%Q;'S;=`&s<%lO%QT!6Q_&WS_POY%QYZ%lZr%Qrs%qs!Q%Q!Q!Y!5y!Y!n%Q!n!o!1u!o#R%Q#R#S!5X#S#`%Q#`#a!1u#a;'S%Q;'S;=`&s<%lO%QT!7U_&WSOY%QYZ%lZr%Qrs%qs!O%Q!O!P!8T!P!Q%Q!Q![!:c![!c%Q!c!i!:c!i#T%Q#T#Z!:c#Z;'S%Q;'S;=`&s<%lO%QT!8Y]&WSOY%QYZ%lZr%Qrs%qs!Q%Q!Q![!9R![!c%Q!c!i!9R!i#T%Q#T#Z!9R#Z;'S%Q;'S;=`&s<%lO%QT!9Wc&WSOY%QYZ%lZr%Qrs%qs!Q%Q!Q![!9R![!c%Q!c!i!9R!i!r%Q!r!sJq!s#R%Q#R#S!8T#S#T%Q#T#Z!9R#Z#d%Q#d#eJq#e;'S%Q;'S;=`&s<%lO%QT!:ji&WS_POY%QYZ%lZr%Qrs%qs!O%Q!O!P!hX#oR&WSOY%QYZ%lZr%Qrs%qs![%Q![!]!?T!];'S%Q;'S;=`&s<%lO%QV!?[V&tR&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QV!?xV!PR&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_!@fY&]Z&WSOY%QYZ%lZr%Qrs%qs!^%Q!^!_!AU!_!`+p!`;'S%Q;'S;=`&s<%lO%QU!A]X#hQ&WSOY%QYZ%lZr%Qrs%qs!_%Q!_!`6e!`;'S%Q;'S;=`&s<%lO%QV!BPX!bR&WSOY%QYZ%lZr%Qrs%qs!_%Q!_!`+p!`;'S%Q;'S;=`&s<%lO%QV!BsY&[R&WSOY%QYZ%lZr%Qrs%qs!_%Q!_!`+p!`!a!Cc!a;'S%Q;'S;=`&s<%lO%QU!CjY#hQ&WSOY%QYZ%lZr%Qrs%qs!_%Q!_!`6e!`!a!AU!a;'S%Q;'S;=`&s<%lO%Q_!DcV&`X#nQ&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_!EPX%{Z&WSOY%QYZ%lZr%Qrs%qs#]%Q#]#^!El#^;'S%Q;'S;=`&s<%lO%QV!EqX&WSOY%QYZ%lZr%Qrs%qs#b%Q#b#c!F^#c;'S%Q;'S;=`&s<%lO%QV!FcX&WSOY%QYZ%lZr%Qrs%qs#h%Q#h#i!GO#i;'S%Q;'S;=`&s<%lO%QV!GTX&WSOY%QYZ%lZr%Qrs%qs#X%Q#X#Y!Gp#Y;'S%Q;'S;=`&s<%lO%QV!GuX&WSOY%QYZ%lZr%Qrs%qs#f%Q#f#g!Hb#g;'S%Q;'S;=`&s<%lO%QV!HgX&WSOY%QYZ%lZr%Qrs%qs#Y%Q#Y#Z!IS#Z;'S%Q;'S;=`&s<%lO%QV!IXX&WSOY%QYZ%lZr%Qrs%qs#T%Q#T#U!It#U;'S%Q;'S;=`&s<%lO%QV!IyX&WSOY%QYZ%lZr%Qrs%qs#V%Q#V#W!Jf#W;'S%Q;'S;=`&s<%lO%QV!JkX&WSOY%QYZ%lZr%Qrs%qs#X%Q#X#Y!KW#Y;'S%Q;'S;=`&s<%lO%QV!K_V&rR&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_!K{a&PZ&WSOY%QYZ%lZr%Qrs%qst%Qtu!Ktu!Q%Q!Q![!Kt![!c%Q!c!}!Kt!}#R%Q#R#S!Kt#S#T%Q#T#o!Kt#o;'S%Q;'S;=`&s<%lO%Q_!MXVuZ&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QV!MuVsR&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QU!NcX#cQ&WSOY%QYZ%lZr%Qrs%qs!_%Q!_!`6e!`;'S%Q;'S;=`&s<%lO%QV# VV}R&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q_# uZ&|X#cQ&WSOY%QYZ%lZr%Qrs%qs!_%Q!_!`6e!`#p%Q#p#q#!h#q;'S%Q;'S;=`&s<%lO%QU#!oV#dQ&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QV##]V|R&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%QT##yV#tP&WSOY%QYZ%lZr%Qrs%qs;'S%Q;'S;=`&s<%lO%Q",tokenizers:[0,1,2,3],topRules:{Program:[0,3]},dynamicPrecedences:{27:1,230:-1,241:-1},specialized:[{term:229,get:Q=>n[Q]||-1}],tokenPrec:7067}),c=s.define({name:"java",parser:q.configure({props:[X.add({IfStatement:P({except:/^\s*({|else\b)/}),TryStatement:P({except:/^\s*({|catch|finally)\b/}),LabeledStatement:S,SwitchBlock:Q=>{let $=Q.textAfter,a=/^\s*\}/.test($),i=/^\s*(case|default)\b/.test($);return Q.baseIndent+(a?0:i?1:2)*Q.unit},Block:t({closing:"}"}),BlockComment:()=>null,Statement:P({except:/^{/})}),Z.add({["Block SwitchBlock ClassBody ElementValueArrayInitializer ModuleBody EnumBody ConstructorBody InterfaceBody ArrayInitializer"]:l,BlockComment(Q){return{from:Q.from+2,to:Q.to-2}}})]}),languageData:{commentTokens:{line:"//",block:{open:"/*",close:"*/"}},indentOnInput:/^\s*(?:case |default:|\{|\})$/}});function W(){return new Y(c)}export{W as java,c as javaLanguage};
diff --git a/docs/assets/index-3d8e5894.js b/docs/assets/index-3d8e5894.js
new file mode 100644
index 00000000..f7011195
--- /dev/null
+++ b/docs/assets/index-3d8e5894.js
@@ -0,0 +1,146 @@
+import{c as ce,n as Me,r as P,q as Mt,d as Pt,v as pt,l as kt,A as qt,g as vt,j as S,u as Pe,_ as Ut,a as It,B as Lt}from"./index-46a25777.js";const Ft=e=>ce("div",{className:`${Me}-toolbar-item`,title:e.title,onClick:e.onClick,children:e.trigger}),Bt=e=>{const{editorId:t}=P.useContext(Mt);return ce(Pt,{relative:`#${t}-toolbar-wrapper`,visible:e.visible,onChange:e.onChange,overlay:e.overlay,children:pt("div",{className:`${Me}-toolbar-item`,title:e.title||"",children:[e.trigger,e.children]})})},Ht=e=>{const{width:t="auto",height:r="auto"}=e;return pt(kt,{children:[ce("div",{className:`${Me}-toolbar-item`,title:e.title,onClick:e.onClick,children:e.trigger}),ce(qt,{width:t,height:r,title:e.modalTitle,visible:e.visible,onClose:e.onClose,showAdjust:e.showAdjust,isFullscreen:e.isFullscreen,onAdjust:i=>{e.onAdjust instanceof Function&&e.onAdjust(i)},children:e.children})]})};var ke={exports:{}},yt=function(t,r){return function(){for(var n=new Array(arguments.length),s=0;s"u"}function Wt(e){return e!==null&&!de(e)&&e.constructor!==null&&!de(e.constructor)&&typeof e.constructor.isBuffer=="function"&&e.constructor.isBuffer(e)}var gt=Q("ArrayBuffer");function Yt(e){var t;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?t=ArrayBuffer.isView(e):t=e&&e.buffer&>(e.buffer),t}function Vt(e){return typeof e=="string"}function Jt(e){return typeof e=="number"}function wt(e){return e!==null&&typeof e=="object"}function ue(e){if(Ue(e)!=="object")return!1;var t=Object.getPrototypeOf(e);return t===null||t===Object.prototype}var Xt=Q("Date"),Qt=Q("File"),Zt=Q("Blob"),Kt=Q("FileList");function Le(e){return qe.call(e)==="[object Function]"}function Gt(e){return wt(e)&&Le(e.pipe)}function er(e){var t="[object FormData]";return e&&(typeof FormData=="function"&&e instanceof FormData||qe.call(e)===t||Le(e.toString)&&e.toString()===t)}var tr=Q("URLSearchParams");function rr(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}function nr(){return typeof navigator<"u"&&(navigator.product==="ReactNative"||navigator.product==="NativeScript"||navigator.product==="NS")?!1:typeof window<"u"&&typeof document<"u"}function Fe(e,t){if(!(e===null||typeof e>"u"))if(typeof e!="object"&&(e=[e]),Ie(e))for(var r=0,i=e.length;r0;)s=i[n],a[s]||(t[s]=e[s],a[s]=!0);e=Object.getPrototypeOf(e)}while(e&&(!r||r(e,t))&&e!==Object.prototype);return t}function ur(e,t,r){e=String(e),(r===void 0||r>e.length)&&(r=e.length),r-=t.length;var i=e.indexOf(t,r);return i!==-1&&i===r}function lr(e){if(!e)return null;var t=e.length;if(de(t))return null;for(var r=new Array(t);t-- >0;)r[t]=e[t];return r}var cr=function(e){return function(t){return e&&t instanceof e}}(typeof Uint8Array<"u"&&Object.getPrototypeOf(Uint8Array)),A={isArray:Ie,isArrayBuffer:gt,isBuffer:Wt,isFormData:er,isArrayBufferView:Yt,isString:Vt,isNumber:Jt,isObject:wt,isPlainObject:ue,isUndefined:de,isDate:Xt,isFile:Qt,isBlob:Zt,isFunction:Le,isStream:Gt,isURLSearchParams:tr,isStandardBrowserEnv:nr,forEach:Fe,merge:Ne,extend:ir,trim:rr,stripBOM:sr,inherits:ar,toFlatObject:or,kindOf:Ue,kindOfTest:Q,endsWith:ur,toArray:lr,isTypedArray:cr,isFileList:Kt},K=A;function ze(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var Et=function(t,r,i){if(!r)return t;var n;if(i)n=i(r);else if(K.isURLSearchParams(r))n=r.toString();else{var s=[];K.forEach(r,function(d,y){d===null||typeof d>"u"||(K.isArray(d)?y=y+"[]":d=[d],K.forEach(d,function(h){K.isDate(h)?h=h.toISOString():K.isObject(h)&&(h=JSON.stringify(h)),s.push(ze(y)+"="+ze(h))}))}),n=s.join("&")}if(n){var a=t.indexOf("#");a!==-1&&(t=t.slice(0,a)),t+=(t.indexOf("?")===-1?"?":"&")+n}return t},dr=A;function fe(){this.handlers=[]}fe.prototype.use=function(t,r,i){return this.handlers.push({fulfilled:t,rejected:r,synchronous:i?i.synchronous:!1,runWhen:i?i.runWhen:null}),this.handlers.length-1};fe.prototype.eject=function(t){this.handlers[t]&&(this.handlers[t]=null)};fe.prototype.forEach=function(t){dr.forEach(this.handlers,function(i){i!==null&&t(i)})};var fr=fe,hr=A,mr=function(t,r){hr.forEach(t,function(n,s){s!==r&&s.toUpperCase()===r.toUpperCase()&&(t[r]=n,delete t[s])})},xt=A;function ee(e,t,r,i,n){Error.call(this),this.message=e,this.name="AxiosError",t&&(this.code=t),r&&(this.config=r),i&&(this.request=i),n&&(this.response=n)}xt.inherits(ee,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code,status:this.response&&this.response.status?this.response.status:null}}});var bt=ee.prototype,$t={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED"].forEach(function(e){$t[e]={value:e}});Object.defineProperties(ee,$t);Object.defineProperty(bt,"isAxiosError",{value:!0});ee.from=function(e,t,r,i,n,s){var a=Object.create(bt);return xt.toFlatObject(e,a,function(d){return d!==Error.prototype}),ee.call(a,e.message,t,r,i,n),a.name=e.name,s&&Object.assign(a,s),a};var re=ee,St={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},k=A;function pr(e,t){t=t||new FormData;var r=[];function i(s){return s===null?"":k.isDate(s)?s.toISOString():k.isArrayBuffer(s)||k.isTypedArray(s)?typeof Blob=="function"?new Blob([s]):Buffer.from(s):s}function n(s,a){if(k.isPlainObject(s)||k.isArray(s)){if(r.indexOf(s)!==-1)throw Error("Circular reference detected in "+a);r.push(s),k.forEach(s,function(d,y){if(!k.isUndefined(d)){var g=a?a+"."+y:y,h;if(d&&!a&&typeof d=="object"){if(k.endsWith(y,"{}"))d=JSON.stringify(d);else if(k.endsWith(y,"[]")&&(h=k.toArray(d))){h.forEach(function(f){!k.isUndefined(f)&&t.append(g,i(f))});return}}n(d,g)}}),r.pop()}else t.append(a,i(s))}return n(e),t}var Rt=pr,ye,We;function vr(){if(We)return ye;We=1;var e=re;return ye=function(r,i,n){var s=n.config.validateStatus;!n.status||!s||s(n.status)?r(n):i(new e("Request failed with status code "+n.status,[e.ERR_BAD_REQUEST,e.ERR_BAD_RESPONSE][Math.floor(n.status/100)-4],n.config,n.request,n))},ye}var ge,Ye;function yr(){if(Ye)return ge;Ye=1;var e=A;return ge=e.isStandardBrowserEnv()?function(){return{write:function(i,n,s,a,o,d){var y=[];y.push(i+"="+encodeURIComponent(n)),e.isNumber(s)&&y.push("expires="+new Date(s).toGMTString()),e.isString(a)&&y.push("path="+a),e.isString(o)&&y.push("domain="+o),d===!0&&y.push("secure"),document.cookie=y.join("; ")},read:function(i){var n=document.cookie.match(new RegExp("(^|;\\s*)("+i+")=([^;]*)"));return n?decodeURIComponent(n[3]):null},remove:function(i){this.write(i,"",Date.now()-864e5)}}}():function(){return{write:function(){},read:function(){return null},remove:function(){}}}(),ge}var gr=function(t){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t)},wr=function(t,r){return r?t.replace(/\/+$/,"")+"/"+r.replace(/^\/+/,""):t},Er=gr,xr=wr,Ct=function(t,r){return t&&!Er(r)?xr(t,r):r},we,Ve;function br(){if(Ve)return we;Ve=1;var e=A,t=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];return we=function(i){var n={},s,a,o;return i&&e.forEach(i.split(`
+`),function(y){if(o=y.indexOf(":"),s=e.trim(y.substr(0,o)).toLowerCase(),a=e.trim(y.substr(o+1)),s){if(n[s]&&t.indexOf(s)>=0)return;s==="set-cookie"?n[s]=(n[s]?n[s]:[]).concat([a]):n[s]=n[s]?n[s]+", "+a:a}}),n},we}var Ee,Je;function $r(){if(Je)return Ee;Je=1;var e=A;return Ee=e.isStandardBrowserEnv()?function(){var r=/(msie|trident)/i.test(navigator.userAgent),i=document.createElement("a"),n;function s(a){var o=a;return r&&(i.setAttribute("href",o),o=i.href),i.setAttribute("href",o),{href:i.href,protocol:i.protocol?i.protocol.replace(/:$/,""):"",host:i.host,search:i.search?i.search.replace(/^\?/,""):"",hash:i.hash?i.hash.replace(/^#/,""):"",hostname:i.hostname,port:i.port,pathname:i.pathname.charAt(0)==="/"?i.pathname:"/"+i.pathname}}return n=s(window.location.href),function(o){var d=e.isString(o)?s(o):o;return d.protocol===n.protocol&&d.host===n.host}}():function(){return function(){return!0}}(),Ee}var xe,Xe;function he(){if(Xe)return xe;Xe=1;var e=re,t=A;function r(i){e.call(this,i??"canceled",e.ERR_CANCELED),this.name="CanceledError"}return t.inherits(r,e,{__CANCEL__:!0}),xe=r,xe}var be,Qe;function Sr(){return Qe||(Qe=1,be=function(t){var r=/^([-+\w]{1,25})(:?\/\/|:)/.exec(t);return r&&r[1]||""}),be}var $e,Ze;function Ke(){if(Ze)return $e;Ze=1;var e=A,t=vr(),r=yr(),i=Et,n=Ct,s=br(),a=$r(),o=St,d=re,y=he(),g=Sr();return $e=function(f){return new Promise(function(F,U){var V=f.data,J=f.headers,X=f.responseType,q;function ae(){f.cancelToken&&f.cancelToken.unsubscribe(q),f.signal&&f.signal.removeEventListener("abort",q)}e.isFormData(V)&&e.isStandardBrowserEnv()&&delete J["Content-Type"];var p=new XMLHttpRequest;if(f.auth){var I=f.auth.username||"",ne=f.auth.password?unescape(encodeURIComponent(f.auth.password)):"";J.Authorization="Basic "+btoa(I+":"+ne)}var B=n(f.baseURL,f.url);p.open(f.method.toUpperCase(),i(B,f.params,f.paramsSerializer),!0),p.timeout=f.timeout;function C(){if(p){var _="getAllResponseHeaders"in p?s(p.getAllResponseHeaders()):null,m=!X||X==="text"||X==="json"?p.responseText:p.response,l={data:m,status:p.status,statusText:p.statusText,headers:_,config:f,request:p};t(function(v){F(v),ae()},function(v){U(v),ae()},l),p=null}}if("onloadend"in p?p.onloadend=C:p.onreadystatechange=function(){!p||p.readyState!==4||p.status===0&&!(p.responseURL&&p.responseURL.indexOf("file:")===0)||setTimeout(C)},p.onabort=function(){p&&(U(new d("Request aborted",d.ECONNABORTED,f,p)),p=null)},p.onerror=function(){U(new d("Network Error",d.ERR_NETWORK,f,p,p)),p=null},p.ontimeout=function(){var m=f.timeout?"timeout of "+f.timeout+"ms exceeded":"timeout exceeded",l=f.transitional||o;f.timeoutErrorMessage&&(m=f.timeoutErrorMessage),U(new d(m,l.clarifyTimeoutError?d.ETIMEDOUT:d.ECONNABORTED,f,p)),p=null},e.isStandardBrowserEnv()){var x=(f.withCredentials||a(B))&&f.xsrfCookieName?r.read(f.xsrfCookieName):void 0;x&&(J[f.xsrfHeaderName]=x)}"setRequestHeader"in p&&e.forEach(J,function(m,l){typeof V>"u"&&l.toLowerCase()==="content-type"?delete J[l]:p.setRequestHeader(l,m)}),e.isUndefined(f.withCredentials)||(p.withCredentials=!!f.withCredentials),X&&X!=="json"&&(p.responseType=f.responseType),typeof f.onDownloadProgress=="function"&&p.addEventListener("progress",f.onDownloadProgress),typeof f.onUploadProgress=="function"&&p.upload&&p.upload.addEventListener("progress",f.onUploadProgress),(f.cancelToken||f.signal)&&(q=function(_){p&&(U(!_||_&&_.type?new y:_),p.abort(),p=null)},f.cancelToken&&f.cancelToken.subscribe(q),f.signal&&(f.signal.aborted?q():f.signal.addEventListener("abort",q))),V||(V=null);var H=g(B);if(H&&["http","https","file"].indexOf(H)===-1){U(new d("Unsupported protocol "+H+":",d.ERR_BAD_REQUEST,f));return}p.send(V)})},$e}var Se,Ge;function Rr(){return Ge||(Ge=1,Se=null),Se}var T=A,et=mr,tt=re,Cr=St,Or=Rt,Tr={"Content-Type":"application/x-www-form-urlencoded"};function rt(e,t){!T.isUndefined(e)&&T.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}function Ar(){var e;return(typeof XMLHttpRequest<"u"||typeof process<"u"&&Object.prototype.toString.call(process)==="[object process]")&&(e=Ke()),e}function Dr(e,t,r){if(T.isString(e))try{return(t||JSON.parse)(e),T.trim(e)}catch(i){if(i.name!=="SyntaxError")throw i}return(r||JSON.stringify)(e)}var me={transitional:Cr,adapter:Ar(),transformRequest:[function(t,r){if(et(r,"Accept"),et(r,"Content-Type"),T.isFormData(t)||T.isArrayBuffer(t)||T.isBuffer(t)||T.isStream(t)||T.isFile(t)||T.isBlob(t))return t;if(T.isArrayBufferView(t))return t.buffer;if(T.isURLSearchParams(t))return rt(r,"application/x-www-form-urlencoded;charset=utf-8"),t.toString();var i=T.isObject(t),n=r&&r["Content-Type"],s;if((s=T.isFileList(t))||i&&n==="multipart/form-data"){var a=this.env&&this.env.FormData;return Or(s?{"files[]":t}:t,a&&new a)}else if(i||n==="application/json")return rt(r,"application/json"),Dr(t);return t}],transformResponse:[function(t){var r=this.transitional||me.transitional,i=r&&r.silentJSONParsing,n=r&&r.forcedJSONParsing,s=!i&&this.responseType==="json";if(s||n&&T.isString(t)&&t.length)try{return JSON.parse(t)}catch(a){if(s)throw a.name==="SyntaxError"?tt.from(a,tt.ERR_BAD_RESPONSE,this,null,this.response):a}return t}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:Rr()},validateStatus:function(t){return t>=200&&t<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};T.forEach(["delete","get","head"],function(t){me.headers[t]={}});T.forEach(["post","put","patch"],function(t){me.headers[t]=T.merge(Tr)});var Be=me,_r=A,jr=Be,Nr=function(t,r,i){var n=this||jr;return _r.forEach(i,function(a){t=a.call(n,t,r)}),t},Re,nt;function Ot(){return nt||(nt=1,Re=function(t){return!!(t&&t.__CANCEL__)}),Re}var it=A,Ce=Nr,Mr=Ot(),Pr=Be,kr=he();function Oe(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new kr}var qr=function(t){Oe(t),t.headers=t.headers||{},t.data=Ce.call(t,t.data,t.headers,t.transformRequest),t.headers=it.merge(t.headers.common||{},t.headers[t.method]||{},t.headers),it.forEach(["delete","get","head","post","put","patch","common"],function(n){delete t.headers[n]});var r=t.adapter||Pr.adapter;return r(t).then(function(n){return Oe(t),n.data=Ce.call(t,n.data,n.headers,t.transformResponse),n},function(n){return Mr(n)||(Oe(t),n&&n.response&&(n.response.data=Ce.call(t,n.response.data,n.response.headers,t.transformResponse))),Promise.reject(n)})},M=A,Tt=function(t,r){r=r||{};var i={};function n(g,h){return M.isPlainObject(g)&&M.isPlainObject(h)?M.merge(g,h):M.isPlainObject(h)?M.merge({},h):M.isArray(h)?h.slice():h}function s(g){if(M.isUndefined(r[g])){if(!M.isUndefined(t[g]))return n(void 0,t[g])}else return n(t[g],r[g])}function a(g){if(!M.isUndefined(r[g]))return n(void 0,r[g])}function o(g){if(M.isUndefined(r[g])){if(!M.isUndefined(t[g]))return n(void 0,t[g])}else return n(void 0,r[g])}function d(g){if(g in r)return n(t[g],r[g]);if(g in t)return n(void 0,t[g])}var y={url:a,method:a,data:a,baseURL:o,transformRequest:o,transformResponse:o,paramsSerializer:o,timeout:o,timeoutMessage:o,withCredentials:o,adapter:o,responseType:o,xsrfCookieName:o,xsrfHeaderName:o,onUploadProgress:o,onDownloadProgress:o,decompress:o,maxContentLength:o,maxBodyLength:o,beforeRedirect:o,transport:o,httpAgent:o,httpsAgent:o,cancelToken:o,socketPath:o,responseEncoding:o,validateStatus:d};return M.forEach(Object.keys(t).concat(Object.keys(r)),function(h){var f=y[h]||s,$=f(h);M.isUndefined($)&&f!==d||(i[h]=$)}),i},Te,st;function At(){return st||(st=1,Te={version:"0.27.2"}),Te}var Ur=At().version,Y=re,He={};["object","boolean","number","function","string","symbol"].forEach(function(e,t){He[e]=function(i){return typeof i===e||"a"+(t<1?"n ":" ")+e}});var at={};He.transitional=function(t,r,i){function n(s,a){return"[Axios v"+Ur+"] Transitional option '"+s+"'"+a+(i?". "+i:"")}return function(s,a,o){if(t===!1)throw new Y(n(a," has been removed"+(r?" in "+r:"")),Y.ERR_DEPRECATED);return r&&!at[a]&&(at[a]=!0,console.warn(n(a," has been deprecated since v"+r+" and will be removed in the near future"))),t?t(s,a,o):!0}};function Ir(e,t,r){if(typeof e!="object")throw new Y("options must be an object",Y.ERR_BAD_OPTION_VALUE);for(var i=Object.keys(e),n=i.length;n-- >0;){var s=i[n],a=t[s];if(a){var o=e[s],d=o===void 0||a(o,s,e);if(d!==!0)throw new Y("option "+s+" must be "+d,Y.ERR_BAD_OPTION_VALUE);continue}if(r!==!0)throw new Y("Unknown option "+s,Y.ERR_BAD_OPTION)}}var Lr={assertOptions:Ir,validators:He},Dt=A,Fr=Et,ot=fr,ut=qr,pe=Tt,Br=Ct,_t=Lr,G=_t.validators;function te(e){this.defaults=e,this.interceptors={request:new ot,response:new ot}}te.prototype.request=function(t,r){typeof t=="string"?(r=r||{},r.url=t):r=t||{},r=pe(this.defaults,r),r.method?r.method=r.method.toLowerCase():this.defaults.method?r.method=this.defaults.method.toLowerCase():r.method="get";var i=r.transitional;i!==void 0&&_t.assertOptions(i,{silentJSONParsing:G.transitional(G.boolean),forcedJSONParsing:G.transitional(G.boolean),clarifyTimeoutError:G.transitional(G.boolean)},!1);var n=[],s=!0;this.interceptors.request.forEach(function($){typeof $.runWhen=="function"&&$.runWhen(r)===!1||(s=s&&$.synchronous,n.unshift($.fulfilled,$.rejected))});var a=[];this.interceptors.response.forEach(function($){a.push($.fulfilled,$.rejected)});var o;if(!s){var d=[ut,void 0];for(Array.prototype.unshift.apply(d,n),d=d.concat(a),o=Promise.resolve(r);d.length;)o=o.then(d.shift(),d.shift());return o}for(var y=r;n.length;){var g=n.shift(),h=n.shift();try{y=g(y)}catch(f){h(f);break}}try{o=ut(y)}catch(f){return Promise.reject(f)}for(;a.length;)o=o.then(a.shift(),a.shift());return o};te.prototype.getUri=function(t){t=pe(this.defaults,t);var r=Br(t.baseURL,t.url);return Fr(r,t.params,t.paramsSerializer)};Dt.forEach(["delete","get","head","options"],function(t){te.prototype[t]=function(r,i){return this.request(pe(i||{},{method:t,url:r,data:(i||{}).data}))}});Dt.forEach(["post","put","patch"],function(t){function r(i){return function(s,a,o){return this.request(pe(o||{},{method:t,headers:i?{"Content-Type":"multipart/form-data"}:{},url:s,data:a}))}}te.prototype[t]=r(),te.prototype[t+"Form"]=r(!0)});var Hr=te,Ae,lt;function zr(){if(lt)return Ae;lt=1;var e=he();function t(r){if(typeof r!="function")throw new TypeError("executor must be a function.");var i;this.promise=new Promise(function(a){i=a});var n=this;this.promise.then(function(s){if(n._listeners){var a,o=n._listeners.length;for(a=0;aunderline , _italic_, ~~line-through~~, superscript26 ,subscript[1] ,\`inline code\`,[link](https://imzbf.cc)
+
+> quote: I Have a Dream
+
+1. So even though we face the difficulties of today and tomorrow, I still have a dream.
+2. It is a dream deeply rooted in the American dream.
+3. I have a dream that one day this nation will rise up.
+
+- [ ] Friday
+- [ ] Saturday
+- [x] Sunday
+
+![Picture](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+
+## 🤗 Demo
+
+\`\`\`js
+import { defineComponent, ref } from 'vue';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default defineComponent({
+ name: 'MdEditor',
+ setup() {
+ const text = ref('');
+ return () => (
+ (text.value = v)} />
+ );
+ }
+});
+\`\`\`
+
+## 🖨 Text
+
+The Old Man and the Sea served to reinvigorate Hemingway's literary reputation and prompted a reexamination of his entire body of work.
+
+## 📈 Table
+
+| nickname | from |
+| -------- | ---------------- |
+| zhijian | ChongQing, China |
+
+## 📏 Formula
+
+Inline: $x+y^{2x}$
+
+$$
+\\sqrt[3]{x}
+$$
+
+## 🧬 Diagram
+
+\`\`\`mermaid
+flowchart TD
+ Start --> Stop
+\`\`\`
+
+## 🪄 Alert
+
+!!! note Supported Types
+
+note、abstract、info、tip、success、question、warning、failure、danger、bug、example、quote、hint、caution、error、attention
+
+!!!
+
+## ☘️ em...
+`,mt=`## 😲 md-editor-rt
+
+Markdown 编辑器,React 版本,使用 jsx 和 typescript 语法开发,支持切换主题、prettier 美化文本等。
+
+### 🤖 基本演示
+
+**加粗**,下划线 ,_斜体_,~~删除线~~,上标26 ,下标[1] ,\`inline code\`,[超链接](https://imzbf.cc)
+
+> 引用:《I Have a Dream》
+
+1. So even though we face the difficulties of today and tomorrow, I still have a dream.
+2. It is a dream deeply rooted in the American dream.
+3. I have a dream that one day this nation will rise up.
+
+- [ ] 周五
+- [ ] 周六
+- [x] 周天
+
+![图片](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+
+## 🤗 代码演示
+
+\`\`\`js
+import { defineComponent, ref } from 'vue';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default defineComponent({
+ name: 'MdEditor',
+ setup() {
+ const text = ref('');
+ return () => (
+ (text.value = v)} />
+ );
+ }
+});
+\`\`\`
+
+## 🖨 文本演示
+
+依照普朗克长度这项单位,目前可观测的宇宙的直径估计值(直径约 930 亿光年,即 8.8 × 1026 米)即为 5.4 × 1061 倍普朗克长度。而可观测宇宙体积则为 8.4 × 10184 立方普朗克长度(普朗克体积)。
+
+## 📈 表格演示
+
+| 昵称 | 来自 |
+| ---- | --------- |
+| 之间 | 中国-重庆 |
+
+## 📏 公式
+
+行内:$x+y^{2x}$
+
+$$
+\\sqrt[3]{x}
+$$
+
+## 🧬 图表
+
+\`\`\`mermaid
+flowchart TD
+ Start --> Stop
+\`\`\`
+
+## 🪄 提示
+
+!!! note 支持的类型
+
+note、abstract、info、tip、success、question、warning、failure、danger、bug、example、quote、hint、caution、error、attention
+
+!!!
+
+## ☘️ 占个坑@!
+`,tn=["😀","😃","😄","😁","😆","😅","😂","🤣","🥲","🤔","😊","😇","🙂","🙃","😉","😌","😍","🥰","😘","😗","😙","😚","😋","😛","😝","😜","🤪","🤨","🧐","🤓","😎","🥸","🤩","🥳","😏","😒","😞","😔","😟","😕","🙁","👻","😣","😖","😫","😩","🥺","😢","😭","😤","😠","😡","🤬","🤯","😳"];const rn=({insert:e=()=>{}})=>{const[t,r]=P.useState({visible:!1}),i=s=>{e(()=>({targetValue:s,select:!0,deviationStart:0,deviationEnd:0}))},n=s=>{r({visible:s})};return S.jsx(Bt,{title:"emoji",visible:t.visible,onChange:n,trigger:S.jsx("svg",{className:"md-editor-icon","aria-hidden":"true",children:S.jsx("use",{xlinkHref:"#icon-emoji"})}),overlay:S.jsx("div",{className:"emoji-container",children:S.jsx("ol",{className:"emojis",children:tn.map((s,a)=>S.jsx("li",{onClick:()=>{i(s)},children:s},`emoji-${a}`))})})})},nn=rn,sn=({insert:e=()=>{}})=>{const t=()=>{e(i=>({targetValue:`==${i}==`,select:!0,deviationStart:2,deviationEnd:-2}))};return S.jsx(Ft,{title:"mark",onClick:t,trigger:S.jsx("svg",{className:"md-editor-icon","aria-hidden":"true",children:S.jsx("use",{xlinkHref:"#icon-mark"})})})},an=sn,on=(e,t,r)=>`read-ex-heading-${r}`,un=e=>{const[t,r]=P.useState({visible:!1,modalFullscreen:!1}),i=Pe(n=>n);return S.jsx(Ht,{visible:t.visible,isFullscreen:t.modalFullscreen,showAdjust:!0,title:"弹窗预览",modalTitle:"编辑预览",width:"870px",height:"600px",onClick:()=>{r({...t,visible:!0})},onClose:()=>{r({...t,visible:!1})},onAdjust:()=>{r({...t,modalFullscreen:!t.modalFullscreen})},trigger:S.jsx("svg",{className:"md-editor-icon","aria-hidden":"true",children:S.jsx("use",{xlinkHref:"#icon-read"})}),children:S.jsx("div",{style:{height:"100%",padding:"20px",overflow:"auto"},children:S.jsx(Ut,{theme:i.theme,language:i.lang,previewTheme:i.previewTheme,codeTheme:i.codeTheme,editorId:"edit2preview",modelValue:e.mdText,mdHeadingId:on})})})},ln=un;var Nt={exports:{}};(function(e,t){(function(r,i){e.exports=i()})(It,function(){var r=1e3,i=6e4,n=36e5,s="millisecond",a="second",o="minute",d="hour",y="day",g="week",h="month",f="quarter",$="year",F="date",U="Invalid Date",V=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,J=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,X={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(m){var l=["th","st","nd","rd"],u=m%100;return"["+m+(l[(u-20)%10]||l[u]||l[0])+"]"}},q=function(m,l,u){var v=String(m);return!v||v.length>=l?m:""+Array(l+1-v.length).join(u)+m},ae={s:q,z:function(m){var l=-m.utcOffset(),u=Math.abs(l),v=Math.floor(u/60),c=u%60;return(l<=0?"+":"-")+q(v,2,"0")+":"+q(c,2,"0")},m:function m(l,u){if(l.date()1)return m(w[0])}else{var b=l.name;I[b]=l,c=b}return!v&&c&&(p=c),c||!v&&p},C=function(m,l){if(ne(m))return m.clone();var u=typeof l=="object"?l:{};return u.date=m,u.args=arguments,new H(u)},x=ae;x.l=B,x.i=ne,x.w=function(m,l){return C(m,{locale:l.$L,utc:l.$u,x:l.$x,$offset:l.$offset})};var H=function(){function m(u){this.$L=B(u.locale,null,!0),this.parse(u)}var l=m.prototype;return l.parse=function(u){this.$d=function(v){var c=v.date,E=v.utc;if(c===null)return new Date(NaN);if(x.u(c))return new Date;if(c instanceof Date)return new Date(c);if(typeof c=="string"&&!/Z$/i.test(c)){var w=c.match(V);if(w){var b=w[2]-1||0,O=(w[7]||"0").substring(0,3);return E?new Date(Date.UTC(w[1],b,w[3]||1,w[4]||0,w[5]||0,w[6]||0,O)):new Date(w[1],b,w[3]||1,w[4]||0,w[5]||0,w[6]||0,O)}}return new Date(c)}(u),this.$x=u.x||{},this.init()},l.init=function(){var u=this.$d;this.$y=u.getFullYear(),this.$M=u.getMonth(),this.$D=u.getDate(),this.$W=u.getDay(),this.$H=u.getHours(),this.$m=u.getMinutes(),this.$s=u.getSeconds(),this.$ms=u.getMilliseconds()},l.$utils=function(){return x},l.isValid=function(){return this.$d.toString()!==U},l.isSame=function(u,v){var c=C(u);return this.startOf(v)<=c&&c<=this.endOf(v)},l.isAfter=function(u,v){return C(u){const e=Pe(n=>n),[t,r]=P.useState(()=>je().format("YYYY/MM/DD HH:mm:ss")),i=P.useMemo(()=>{const n=e.lang,s=je().day();return`${t} ${dn[n][s>0?s-1:6]}`},[e.lang,t]);return P.useEffect(()=>{const n=setInterval(()=>{r(je().format("YYYY/MM/DD HH:mm:ss"))},1e3);return()=>{clearInterval(n)}},[]),S.jsx("span",{children:i})},hn=fn;const mn="editor-preview",vn=()=>{const[e]=P.useState(()=>!!localStorage.getItem("debug")),t=Pe(a=>a),[r,i]=P.useState(()=>t.lang==="zh-CN"?mt:ht),n=P.useRef();P.useEffect(()=>{t.lang==="zh-CN"?i(mt):i(ht)},[t.lang]);const s=P.useMemo(()=>{switch(t.lang){case"zh-CN":return"示例中的标记、emoji、预览和时间扩展组件源码:";default:return"Source code of mark, emoji, preview and time extension components in this page: "}},[t.lang]);return P.useEffect(()=>{var a,o,d,y,g;e&&((a=n.current)==null||a.on("catalog",h=>{console.log("catalog",h)}),(o=n.current)==null||o.on("fullscreen",h=>{console.log("fullscreen",h)}),(d=n.current)==null||d.on("htmlPreview",h=>{console.log("htmlPreview",h)}),(y=n.current)==null||y.on("pageFullscreen",h=>{console.log("pageFullscreen",h)}),(g=n.current)==null||g.on("preview",h=>{console.log("preview",h)}),window.editorInstance=n.current)},[e]),S.jsx("div",{className:"project-preview",children:S.jsxs("div",{className:"container",children:[S.jsx(Lt,{ref:n,theme:t.theme,previewTheme:t.previewTheme,codeTheme:t.codeTheme,modelValue:r,language:t.lang,editorId:mn,autoDetectCode:!0,defToolbars:[S.jsx(an,{},"mark-extension"),S.jsx(nn,{},"emoji-extension"),S.jsx(ln,{mdText:r},"read-extension")],onSave:(a,o)=>{console.log("v",a),o.then(d=>{console.log("h",d)})},toolbars:["bold","underline","italic","strikeThrough","-","title","sub","sup","quote","unorderedList","orderedList","task","-","codeRow","code","link","image","table","mermaid","katex",0,1,2,"-","revoke","next","save","=","prettier","pageFullscreen","fullscreen","preview","htmlPreview","catalog","github"],onChange:a=>i(a),onUploadImg:async(a,o)=>{const d=await Promise.all(a.map(y=>new Promise((g,h)=>{const f=new FormData;f.append("file",y),en.post("/api/img/upload",f,{headers:{"Content-Type":"multipart/form-data"}}).then($=>g($)).catch($=>h($))})));o(d.map(y=>y.data.url))},footers:["markdownTotal","=",0,"scrollSwitch"],defFooters:[S.jsx(hn,{},"time-now")]}),S.jsx("br",{}),S.jsxs("span",{className:"tips-text",children:[s,S.jsx("a",{href:"https://github.com/imzbf/md-editor-rt/tree/docs/src/components",target:"_blank",children:"components"})]})]})})};export{vn as default};
diff --git a/docs/assets/index-450f4a64.js b/docs/assets/index-450f4a64.js
new file mode 100644
index 00000000..5f71ba85
--- /dev/null
+++ b/docs/assets/index-450f4a64.js
@@ -0,0 +1,1519 @@
+import{u as l,r as t,j as n,I as c,b as p,e as u}from"./index-46a25777.js";const r=`## 😁 Basic Usage
+
+It has been developing iteratively, so update the latest version please. Publish logs: [releases](https://github.com/imzbf/md-editor-rt/releases)
+
+### 🤓 CDN
+
+Use production version in html directly:
+
+\`\`\`html
+
+
+
+
+
+
+
+
++
+
+```
+
+#### 🏄🏼♀️ ES Module
+
+```diff
+- import MdEditor from 'md-editor-rt';
+- const NormalToolbar = MdEditor.NormalToolbar;
+- const DropdownToolbar = MdEditor.DropdownToolbar;
+- const ModalToolbar = MdEditor.ModalToolbar;
+- const MdCatalog = MdEditor.MdCatalog;
++ import { MdEditor, NormalToolbar, DropdownToolbar, ModalToolbar, MdCatalog } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+```
+
+### 🔖 Props
+
+| name | description |
+| ----------- | --------------------------------- |
+| previewOnly | deleted, replace with `MdPreview` |
+
+### 🪤 Internal Components
+
+New component `MdPreview` and replacing the attribute `previewOnly`.
+
+```diff
+import React, { useState } from 'react';
+- import MdEditor from 'md-editor-rt';
++ import { MdPreview } from 'md-editor-rt';
+- import 'md-editor-rt/lib/style.css';
++ import 'md-editor-rt/lib/preview.css';
+
+export default () => {
+ const [text] = useState('hello md-editor-rt!');
+- return ;
++ return ;
+};
+```
+
+---
+
+## 🧙🏻♂️ Upgrade from 2.x to 3.x
+
+This is the content that 3.x is incompatible with version 2.x only.
+
+### 🤹🏼♂️ Grammar
+
+- Strikethrough
+
+ ```diff
+ - ~It is a dream deeply rooted in the American dream.~
+ + ~~It is a dream deeply rooted in the American dream.~~
+ ```
+
+### 🔩 Props
+
+| name | description |
+| --------------- | ----------------------- |
+| markedHeadingId | rename to `mdHeadingId` |
+| historyLength | deleted |
+
+### 🤿 Config
+
+```diff
+MdEditor.config({
+- markedRenderer: (renderer) => renderer,
+- markedExtensions: [],
+- markedOptions,
++ codeMirrorExtensions: (theme, extensions) => extensions,
++ markdownItConfig: (mdit) { }
+})
+```
+
+### 🎤 Shortcut Key
+
+| key | function | description |
+| -------- | -------- | ----------- |
+| CTRL + Q | quote | deleted |
+
+### 🪤 Component
+
+#### 🐻 MdCatalog
+
+- **props**
+
+ - `markedHeadingId`: deleted, use `mdHeadingId` instead of it
diff --git a/docs/contrast-en-US.md b/docs/contrast-en-US.md
new file mode 100644
index 00000000..fce22584
--- /dev/null
+++ b/docs/contrast-en-US.md
@@ -0,0 +1,35 @@
+## Upgrade from 1.x to 2.x
+
+This is the content that 2.x is incompatible with version 1.x only.
+
+## Props
+
+| name | description |
+| ------------------- | ---------------------------------------- |
+| editorClass | rename to `className` |
+| hljs | removed, use `MdEditor.config` to config |
+| highlightJs | the same |
+| highlightCss | the same |
+| languageUserDefined | the same |
+| prettier | rename to `noPrettier`, default `false` |
+| prettierCDN | removed, use `MdEditor.config` to config |
+| prettierMDCDN | the same |
+| cropperCss | the same |
+| cropperJs | the same |
+| iconfontJs | the same |
+| screenfull | the same |
+| screenfullJs | the same |
+| mermaid | the same |
+| mermaidJs | the same |
+| katex | the same |
+| katexJs | the same |
+| katexCss | the same |
+| extensions | the same |
+
+## Component
+
+- Catalog
+
+ `Editor.Catalog` is renamed to `Editor.MdCatalog`.
+
+ For more usage, refer to branch [docs](https://github.com/imzbf/md-editor-rt/tree/docs).
diff --git a/docs/contrast-zh-CN-3.md b/docs/contrast-zh-CN-3.md
new file mode 100644
index 00000000..04146edb
--- /dev/null
+++ b/docs/contrast-zh-CN-3.md
@@ -0,0 +1,104 @@
+## 🧙🏼 从 3.x 升级到 4.x
+
+### 🏄🏼 引用方式
+
+4.0 版本开始支持按需引用组件,不再默认导出编辑器。
+
+#### 🏄🏼♂️ 全局引用
+
+```diff
+-
++
+
+```
+
+#### 🏄🏼♀️ ES Module
+
+```diff
+- import MdEditor from 'md-editor-rt';
+- const NormalToolbar = MdEditor.NormalToolbar;
+- const DropdownToolbar = MdEditor.DropdownToolbar;
+- const ModalToolbar = MdEditor.ModalToolbar;
+- const MdCatalog = MdEditor.MdCatalog;
++ import { MdEditor, NormalToolbar, DropdownToolbar, ModalToolbar, MdCatalog } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+```
+
+### 🔖 Props
+
+| 名称 | 说明 |
+| ----------- | ------------------------------- |
+| previewOnly | 已移除,使用组件`MdPreview`替换 |
+
+### 🪤 内部组件
+
+新增`MdPreview`组件,替换原编辑器的`previewOnly`属性,可以减少代码体积。
+
+```diff
+import React, { useState } from 'react';
+- import MdEditor from 'md-editor-rt';
++ import { MdPreview } from 'md-editor-rt';
+- import 'md-editor-rt/lib/style.css';
++ import 'md-editor-rt/lib/preview.css';
+
+export default () => {
+ const [text] = useState('hello md-editor-rt!');
+- return ;
++ return ;
+};
+```
+
+---
+
+## 🧙🏻♂️ 从 2.x 升级到 3.x
+
+下面列举的是`3.x`不兼容`2.x`的内容,兼容内容不作展示。
+
+### 🤹🏼♂️ 语法
+
+- 删除线
+
+ ```diff
+ - ~It is a dream deeply rooted in the American dream.~
+ + ~~It is a dream deeply rooted in the American dream.~~
+ ```
+
+### 🔩 Props
+
+| 名称 | 说明 |
+| --------------- | ------------------- |
+| markedHeadingId | 修改为`mdHeadingId` |
+| historyLength | 已移除 |
+
+### 🤿 配置项
+
+```diff
+MdEditor.config({
+- markedRenderer: (renderer) => renderer,
+- markedExtensions: [],
+- markedOptions,
++ codeMirrorExtensions: (theme, extensions) => extensions,
++ markdownItConfig: (mdit) { }
+})
+```
+
+### 🎤 快捷键
+
+| 键位 | 功能 | 说明 |
+| -------- | -------- | ------ |
+| CTRL + Q | 添加引用 | 已移除 |
+
+### 🪤 内部组件
+
+#### 🐻 目录导航
+
+- **props**
+
+ - `markedHeadingId`: 已删除,使用`mdHeadingId`代替。
diff --git a/docs/contrast-zh-CN.md b/docs/contrast-zh-CN.md
new file mode 100644
index 00000000..9302fe58
--- /dev/null
+++ b/docs/contrast-zh-CN.md
@@ -0,0 +1,37 @@
+## 从 1.x 升级到 2.x
+
+下面列举的是`2.x`不兼容`1.x`的内容,兼容内容不作展示。
+
+## Props
+
+| 名称 | 说明 |
+| ------------------- | --------------------------------- |
+| editorClass | 修改为`className` |
+| hljs | 已移除,使用`MdEditor.config`配置 |
+| highlightJs | 同上 |
+| highlightCss | 同上 |
+| languageUserDefined | 同上 |
+| prettier | 修改为`noPrettier`,默认`false` |
+| prettierCDN | 已移除,使用`MdEditor.config`配置 |
+| prettierMDCDN | 同上 |
+| cropperCss | 同上 |
+| cropperJs | 同上 |
+| iconfontJs | 同上 |
+| screenfull | 同上 |
+| screenfullJs | 同上 |
+| mermaid | 同上 |
+| mermaidJs | 同上 |
+| katex | 同上 |
+| katexJs | 同上 |
+| katexCss | 同上 |
+| extensions | 同上 |
+
+## 内部组件
+
+全局注册名称统一为组件的名称。
+
+- 目录导航
+
+ `Editor.Catalog`组件名称修改为`Editor.MdCatalog`。
+
+ 更多请参考使用[docs](https://github.com/imzbf/md-editor-rt/tree/docs)分支。
diff --git a/docs/demo-en-US.md b/docs/demo-en-US.md
new file mode 100644
index 00000000..47cd331c
--- /dev/null
+++ b/docs/demo-en-US.md
@@ -0,0 +1,755 @@
+## 😁 Basic Usage
+
+It has been developing iteratively, so update the latest version please. Publish logs: [releases](https://github.com/imzbf/md-editor-rt/releases)
+
+### 🤓 CDN
+
+Use production version in html directly:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 🤖 Npm Install
+
+```shell [install:yarn]
+yarn add md-editor-rt
+```
+
+```shell [install:npm]
+npm install md-editor-rt
+```
+
+#### 🤓 Jsx Template
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ return ;
+};
+```
+
+#### 📖 Preview Only
+
+```jsx
+import React, { useState } from 'react';
+import { MdPreview, MdCatalog } from 'md-editor-rt';
+import 'md-editor-rt/lib/preview.css';
+
+export default () => {
+ const [id] = useState('preview-only');
+ const [scrollElement] = useState(document.documentElement);
+ const [text] = useState('hello md-editor-rt!');
+
+ return (
+ <>
+
+
+ >
+ );
+};
+```
+
+## 🥂 Api usage
+
+Usages of some APIs.
+
+### 🥶 Customize Shortcut Key
+
+Source code for built-in shortcut key configuration: [commands.ts](https://github.com/imzbf/md-editor-rt/blob/develop/packages/MdEditor/layouts/Content/codemirror/commands.ts). They have been added as extensions to `codemirror`.
+
+The basic principle of replacing or deleting shortcut keys is to find the corresponding extension, and handle it.
+
+In fact, The Second input parameter `extensions` of `codeMirrorExtensions` is an array, The first item in the array is the shortcut key extension. The third input parameter is the default shortcut key configuration.
+
+#### 💅 Modify Shortcut Key
+
+Change `Ctrl-b` to `Ctrl-m`
+
+```js
+import { config } from 'md-editor-rt';
+import { keymap } from '@codemirror/view';
+
+config({
+ // [keymap, minimalSetup, markdown, EditorView.lineWrapping, EditorView.updateListener, EditorView.domEventHandlers, oneDark??oneLight]
+ codeMirrorExtensions(theme, extensions, mdEditorCommands) {
+ const newExtensions = [...extensions];
+ // 1. Remove the default shortcut key extension first
+ newExtensions.shift();
+
+ // 2. Reference the source code for shortcut key configuration
+ // Find the location of the configuration item for CtrlB in mdEditorCommands
+ const CtrlB = mdEditorCommands[0];
+
+ // 3. Document for configuring shortcut keys of codemirror
+ // https://codemirror.net/docs/ref/#commands
+ const CtrlM = {
+ // We need the run method in CtrlB here
+ ...CtrlB,
+ key: 'Ctrl-m',
+ mac: 'Cmd-m'
+ };
+
+ // 4. Add the modified shortcut key to the array
+ const newMdEditorCommands = [
+ CtrlM,
+ ...mdEditorCommands.filter((i) => i.key !== 'Ctrl-b')
+ ];
+
+ newExtensions.push(keymap.of(newMdEditorCommands));
+
+ return newExtensions;
+ }
+});
+```
+
+#### ✂️ Delete Shortcut Key
+
+Disable all shortcut keys
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ // [keymap, minimalSetup, markdown, EditorView.lineWrapping, EditorView.updateListener, EditorView.domEventHandlers, oneDark??oneLight]
+ codeMirrorExtensions(theme, extensions) {
+ const newExtensions = [...extensions];
+ // 1. Remove default shortcut key extensions
+ newExtensions.shift();
+
+ // 2. Return extension list
+ return newExtensions;
+ }
+});
+```
+
+#### 💉 Add Shortcut Key
+
+If you want to insert content into the edit box, you need to use the `insert` method bound on the instance of editor, reference: [Insert content into the edit box](/md-editor-rt/ed-US/docs#%F0%9F%92%89%20insert).
+
+If you are not using `MdEditor.config` in the component where the editor is located, you are unable to obtain instance of editor at this time. You may need to use `EventBus`.
+
+Add shortcut key `Ctrl+m`, to insert a marking module into the editing box(`==mark==`)
+
+`index.ts`
+
+```js
+import { config } from 'md-editor-rt';
+import { keymap, KeyBinding } from '@codemirror/view';
+// If you used EventBus
+import bus from '@/utils/event-bus';
+
+config({
+ // [keymap, minimalSetup, markdown, EditorView.lineWrapping, EditorView.updateListener, EditorView.domEventHandlers, oneDark??oneLight]
+ codeMirrorExtensions(theme, extensions, mdEditorCommands) {
+ const newExtensions = [...extensions];
+ // 1. Remove the default shortcut key extension first
+ newExtensions.shift();
+
+ // 2. Create a new shortcut key configuration, reference: https://codemirror.net/docs/ref/#commands
+ const CtrlM: KeyBinding = {
+ key: 'Ctrl-m',
+ mac: 'Cmd-m',
+ run: () => {
+ bus.emit('insertMarkBlock');
+ return true;
+ }
+ };
+
+ // 4. Add a new shortcut key to the array
+ const newMdEditorCommands = [...mdEditorCommands, CtrlM];
+
+ newExtensions.push(keymap.of(newMdEditorCommands));
+
+ return newExtensions;
+ }
+});
+```
+
+Next, listening 'insertMarkBlock' in the component where the editor is located
+
+`App.tsx`
+
+```tsx
+import React, { useState, useRef, useEffect } from 'react';
+import { MdEditor, ExposeParam } from 'md-editor-rt';
+// If you used EventBus
+import bus from '@/utils/event-bus';
+
+const App = () => {
+ const [text] = useState('## md-editor-rt\n\n');
+ const mdEditorRef = useRef();
+
+ useEffect(() => {
+ bus.on('insertMarkBlock', () => {
+ mdEditorRef.current?.insert((selectedText) => {
+ return {
+ targetValue: `==${selectedText}==`,
+ select: true,
+ deviationStart: 2,
+ deviationEnd: -2
+ };
+ });
+ });
+ }, []);
+
+ return ;
+};
+```
+
+Attach: Simple version of `EventBus`
+
+```ts
+/* eslint-disable @typescript-eslint/ban-types */
+class EventBus {
+ private events: Map;
+
+ constructor() {
+ this.events = new Map();
+ }
+
+ on(eventName: string, fn: Function) {
+ if (!eventName) {
+ console.error('Get a wrong eventName');
+ return false;
+ }
+
+ if (!(fn instanceof Function)) {
+ console.error('Get a wrong callback');
+ return false;
+ }
+
+ const fns = this.events.get(eventName) || [];
+ fns.push(fn);
+ this.events.set(eventName, fns);
+ }
+
+ emit(eventName: string, ...args: any[]) {
+ this.events.get(eventName)?.forEach((fn) => {
+ fn(args);
+ });
+ }
+}
+
+export default new EventBus();
+```
+
+### 🍦 Change Theme
+
+Themes are divided into editor theme(`theme`), article preview theme(`previewTheme`) and code theme(`codeTheme`).
+
+#### 🍧 Editor Theme
+
+Support `light` and `dark` default.
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [theme] = useState('dark');
+ return ;
+};
+```
+
+#### 🍡 Preview Theme
+
+There are 6 kinds of themes: `default`, `github`, `vuepress`, `mk-cute`, `smart-blue` and `cyanosis`. It is useful When you want to show your article directly. Modify `previewTheme`.
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [previewTheme] = useState('github');
+ return ;
+};
+```
+
+- Custom
+
+ 1. Write `css` under the `xxx-theme` claa. `xxx` is the name of your theme, for more examples, refer to [markdown-theme](https://github.com/imzbf/markdown-theme).
+
+ _xxx.css_
+
+ ```css
+ .xxx-theme code {
+ color: red;
+ }
+ ```
+
+ 2. Import
+
+ ```js
+ import 'xxx.css';
+ ```
+
+ 3. Set `previewTheme`
+
+ ```jsx
+
+ ```
+
+#### 🎄 Code Theme
+
+There are 8 kinds of themes: `atom`, `a11y`, `github`, `gradient`, `kimbie`, `paraiso`,`qtcreator` and `stackoverflow`, they are all from [highlight.js](https://highlightjs.org/).
+
+- Usage
+
+ ```jsx
+ import React, { useState } from 'react';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [codeTheme] = useState('atom');
+ return ;
+ };
+ ```
+
+- Custom
+
+ 1. Find or Write your favorite theme, then config them:
+
+ ```js
+ import { config } from 'md-editor-rt';
+
+ config({
+ editorExtensions: {
+ highlight: {
+ css: {
+ xxxxx: {
+ light: 'https://unpkg.com/highlight.js@11.2.0/styles/xxxxx-light.css',
+ dark: 'https://unpkg.com/highlight.js@11.2.0/styles/xxxxx-dark.css'
+ },
+ yyyyy: {
+ light: 'https://unpkg.com/highlight.js@11.2.0/styles/xxxxx-light.css',
+ dark: 'https://unpkg.com/highlight.js@11.2.0/styles/xxxxx-dark.css'
+ }
+ }
+ }
+ }
+ });
+ ```
+
+ If some keys in object `css` are same as Editor's, Editor's whill be replaced.
+
+ 2. Set `codeTheme`
+
+ ```jsx
+
+ ```
+
+### 🛠 Config Extensions
+
+Extensions highlight, prettier, cropper, screenfull are import from `cdn`. When your project is running offline, replace urls of these extensions. Some Extensions support be injected in development environment.
+
+Example for `screenfull`:
+
+#### ⚰️ Inject Directly
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor, config } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+import screenfull from 'screenfull';
+
+MdEditor.config({
+ editorExtensions: {
+ screenfull: {
+ instance: screenfull
+ }
+ }
+});
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ return ;
+};
+```
+
+#### 📡 Intranet Link
+
+Get files from [unpkg.com](https://unpkg.com).
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor, config } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+MdEditor.config({
+ editorExtensions: {
+ screenfull: {
+ js: 'https://localhost:8090/screenfull@5.2.0/index.js'
+ }
+ }
+});
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ return ;
+};
+```
+
+### 📷 Upload Pictures
+
+By default, you can select multiple pictures. You can paste and upload screenshots and copy web page pictures.
+
+> Tips: When pasting pictures, if they are GIF graphs, it does not work! Please upload it by file system.
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+const onUploadImg = async (files, callback) => {
+ const res = await Promise.all(
+ files.map((file) => {
+ return new Promise((rev, rej) => {
+ const form = new FormData();
+ form.append('file', file);
+
+ axios
+ .post('/api/img/upload', form, {
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+ .then((res) => rev(res))
+ .catch((error) => rej(error));
+ });
+ })
+ );
+
+ callback(res.map((item) => item.data.url));
+};
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ return ;
+};
+```
+
+### 🏳️🌈 Extension Language
+
+```js
+import React, { useState } from 'react';
+import { MdEditor, config } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+MdEditor.config({
+ editorConfig: {
+ languageUserDefined: {
+ 'my-lang': {
+ toolbarTips: {
+ bold: 'bold',
+ underline: 'underline',
+ italic: 'italic',
+ strikeThrough: 'strikeThrough',
+ title: 'title',
+ sub: 'subscript',
+ sup: 'superscript',
+ quote: 'quote',
+ unorderedList: 'unordered list',
+ orderedList: 'ordered list',
+ task: 'task list',
+ codeRow: 'inline code',
+ code: 'block-level code',
+ link: 'link',
+ image: 'image',
+ table: 'table',
+ mermaid: 'mermaid',
+ katex: 'formula',
+ revoke: 'revoke',
+ next: 'undo revoke',
+ save: 'save',
+ prettier: 'prettier',
+ pageFullscreen: 'fullscreen in page',
+ fullscreen: 'fullscreen',
+ preview: 'preview',
+ htmlPreview: 'html preview',
+ catalog: 'catalog',
+ github: 'source code'
+ },
+ titleItem: {
+ h1: 'Lv1 Heading',
+ h2: 'Lv2 Heading',
+ h3: 'Lv3 Heading',
+ h4: 'Lv4 Heading',
+ h5: 'Lv5 Heading',
+ h6: 'Lv6 Heading'
+ },
+ imgTitleItem: {
+ link: 'Add Img Link',
+ upload: 'Upload Img',
+ clip2upload: 'Clip Upload'
+ },
+ linkModalTips: {
+ linkTitle: 'Add Link',
+ imageTitle: 'Add Image',
+ descLabel: 'Desc:',
+ descLabelPlaceHolder: 'Enter a description...',
+ urlLabel: 'Link:',
+ urlLabelPlaceHolder: 'Enter a link...',
+ buttonOK: 'OK'
+ },
+ clipModalTips: {
+ title: 'Crop Image',
+ buttonUpload: 'Upload'
+ },
+ copyCode: {
+ text: 'Copy',
+ successTips: 'Copied!',
+ failTips: 'Copy failed!'
+ },
+ mermaid: {
+ flow: 'flow',
+ sequence: 'sequence',
+ gantt: 'gantt',
+ class: 'class',
+ state: 'state',
+ pie: 'pie',
+ relationship: 'relationship',
+ journey: 'journey'
+ },
+ katex: {
+ inline: 'inline',
+ block: 'block'
+ },
+ footer: {
+ markdownTotal: 'Word Count',
+ scrollAuto: 'Scroll Auto'
+ }
+ }
+ }
+ }
+});
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [language] = useState('my-lang');
+
+ return ;
+};
+```
+
+You can install the existing language also: [md-editor-extension](https://github.com/imzbf/md-editor-extension). Refer to extension library for the usage and the way to contribute~
+
+### 📄 Get Catalogue
+
+- Get
+
+ ```jsx
+ import React, { useState } from 'react';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [catalogList, setList] = useState([]);
+
+ return ;
+ };
+ ```
+
+- Display
+
+ Use `MdCatalog`
+
+ ```jsx
+ import React, { useState } from 'react';
+ import { MdPreview, MdCatalog } from 'md-editor-rt';
+ import 'md-editor-rt/lib/preview.css';
+
+ const editorId = 'my-editor';
+
+ export default () => {
+ const [state] = useState({
+ text: '# heading',
+ scrollElement: document.documentElement
+ });
+
+ return (
+ <>
+
+
+ >
+ );
+ };
+ ```
+
+### 🪚 Define Toolbar
+
+> after v1.2.0, You can sort the toolbar as you like, split tools by `'-'`, the left and right toolbars are divided by `'='`!
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [toolbars] = useState(['italic', 'underline', '-', 'bold', '=', 'github']);
+
+ return ;
+};
+```
+
+### 💪 Customize Toolbar
+
+There are examples of `mark` and `emoji`.
+
+To get complete code, refer to [docs](https://github.com/imzbf/md-editor-rt/blob/docs/src/pages/Preview/index.tsx).
+
+![mark and Emoji extension](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+
+> Get more emojis, go to [https://getemoji.com/](https://getemoji.com/).
+
+### 🧙♂️ Change Styles
+
+```less
+.css-vars(@isDark) {
+ --md-color: if(@isDark, #999, #222);
+ --md-hover-color: if(@isDark, #bbb, #000);
+ --md-bk-color: if(@isDark, #000, #fff);
+ --md-bk-color-outstand: if(@isDark, #111, #f6f6f6);
+ --md-bk-hover-color: if(@isDark, #1b1a1a, #f5f7fa);
+ --md-border-color: if(@isDark, #2d2d2d, #e6e6e6);
+ --md-border-hover-color: if(@isDark, #636262, #b9b9b9);
+ --md-border-active-color: if(@isDark, #777, #999);
+ --md-modal-mask: #00000073;
+ --md-scrollbar-bg-color: if(@isDark, #0f0f0f, #e2e2e2);
+ --md-scrollbar-thumb-color: if(@isDark, #2d2d2d, #0000004d);
+ --md-scrollbar-thumb-hover-color: if(@isDark, #3a3a3a, #00000059);
+ --md-scrollbar-thumb-active-color: if(@isDark, #3a3a3a, #00000061);
+}
+
+.md-editor {
+ .css-vars(false);
+}
+
+.md-editor-dark {
+ .css-vars(true);
+}
+```
+
+Change background color in dark mode:
+
+```css
+.md-editor-dark {
+ --md-bk-color: #333 !important;
+}
+```
+
+### 🙍🏻♂️ Import All Library
+
+```jsx
+import { MdEditor, config } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+import screenfull from 'screenfull';
+
+import katex from 'katex';
+import 'katex/dist/katex.min.css';
+
+import Cropper from 'cropperjs';
+import 'cropperjs/dist/cropper.css';
+
+import mermaid from 'mermaid';
+
+import highlight from 'highlight.js';
+import 'highlight.js/styles/atom-one-dark.css';
+
+// <3.0
+import prettier from 'prettier';
+import parserMarkdown from 'prettier/parser-markdown';
+// >=3.0
+import * as prettier from 'prettier';
+import parserMarkdown from 'prettier/plugins/markdown';
+
+// https://at.alicdn.com/t/c/font_2605852_u82y61ve02.js
+import './assets/iconfont.js';
+
+config({
+ editorExtensions: {
+ prettier: {
+ prettierInstance: prettier,
+ parserMarkdownInstance: parserMarkdown
+ },
+ highlight: {
+ instance: highlight
+ },
+ screenfull: {
+ instance: screenfull
+ },
+ katex: {
+ instance: katex
+ },
+ cropper: {
+ instance: Cropper
+ },
+ mermaid: {
+ instance: mermaid
+ }
+ }
+});
+
+export default () => {
+ return ;
+};
+```
+
+> Tips: While import highlight styles by yourself, editor will not be able to change code styles.
+
+## 🔒 XSS
+
+after`1.3.0`, please use `sanitize` to sanitize `html`. eg: `sanitize-html`
+
+```shell
+yarn add sanitize-html
+```
+
+```jsx
+import React from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+import sanitizeHtml from 'sanitize-html';
+
+export default () => {
+ return sanitizeHtml(html)} />;
+};
+```
+
+## 🧻 Edit This Page
+
+[demo-en-US](https://github.com/imzbf/md-editor-rt/blob/dev-docs/public/demo-en-US.md)
diff --git a/docs/demo-zh-CN.md b/docs/demo-zh-CN.md
new file mode 100644
index 00000000..219cfc45
--- /dev/null
+++ b/docs/demo-zh-CN.md
@@ -0,0 +1,763 @@
+## 😁 基本使用示例
+
+目前一直在迭代开发,所以尽量安装最新版本。发布日志请前往:[releases](https://github.com/imzbf/md-editor-rt/releases)
+
+### 🤓 CDN 链接
+
+通过直接链接生产版本来使用,下面是一个小例子:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 🤖 NPM 安装
+
+```shell [install:yarn]
+yarn add md-editor-rt
+```
+
+```shell [install:npm]
+npm install md-editor-rt
+```
+
+#### 🤓 基本使用
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ return ;
+};
+```
+
+#### 📖 仅预览
+
+```jsx
+import React, { useState } from 'react';
+import { MdPreview, MdCatalog } from 'md-editor-rt';
+import 'md-editor-rt/lib/preview.css';
+
+export default () => {
+ const [id] = useState('preview-only');
+ const [scrollElement] = useState(document.documentElement);
+ const [text] = useState('hello md-editor-rt!');
+
+ return (
+ <>
+
+
+ >
+ );
+};
+```
+
+## 🥂 扩展功能
+
+这里包含了一些编辑器`api`的使用示范
+
+### 🥶 自定义快捷键
+
+内置的快捷键配置的源码:[commands.ts](https://github.com/imzbf/md-editor-rt/blob/develop/packages/MdEditor/layouts/Content/codemirror/commands.ts),它们作为扩展项被添加到了`codemirror`。
+
+想要替换、删除快捷键的基本原理是找到对应的扩展,然后遍历这个快捷键配置的数组,找到并处理它。
+
+事实上,`config`中`codeMirrorExtensions`的第二入参`extensions`是一个数组,它的第一项就是快捷键扩展,第三入参就是默认的快捷键配置。
+
+#### 💅 修改快捷键
+
+将`Ctrl-b`修改为`Ctrl-m`
+
+```js
+import { config } from 'md-editor-rt';
+import { keymap } from '@codemirror/view';
+
+config({
+ // [keymap, minimalSetup, markdown, EditorView.lineWrapping, EditorView.updateListener, EditorView.domEventHandlers, oneDark??oneLight]
+ codeMirrorExtensions(theme, extensions, mdEditorCommands) {
+ const newExtensions = [...extensions];
+ // 1. 先把默认的快捷键扩展移除
+ newExtensions.shift();
+
+ // 2. 参考快捷键配置的源码,找到CtrlB的配置项在mdEditorCommands中的位置
+ const CtrlB = mdEditorCommands[0];
+
+ // 3. 配置codemirror快捷键的文档
+ // https://codemirror.net/docs/ref/#commands
+ const CtrlM = {
+ // 这里我们需要CtrlB默认触发执行的run方法,如果是新增快捷键等,就需要自行处理触发逻辑
+ ...CtrlB,
+ key: 'Ctrl-m',
+ mac: 'Cmd-m'
+ };
+
+ // 4. 把修改后的快捷键放到待构建扩展的数组中
+ const newMdEditorCommands = [
+ CtrlM,
+ ...mdEditorCommands.filter((i) => i.key !== 'Ctrl-b')
+ ];
+
+ newExtensions.push(keymap.of(newMdEditorCommands));
+
+ return newExtensions;
+ }
+});
+```
+
+#### ✂️ 删除快捷键
+
+禁用所有快捷键
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ // [keymap, minimalSetup, markdown, EditorView.lineWrapping, EditorView.updateListener, EditorView.domEventHandlers, oneDark??oneLight]
+ codeMirrorExtensions(theme, extensions) {
+ const newExtensions = [...extensions];
+ // 1. 把默认的快捷键扩展移除
+ newExtensions.shift();
+
+ // 2. 返回扩展列表即可
+ return newExtensions;
+ }
+});
+```
+
+#### 💉 新增快捷键
+
+如果涉及到向编辑框插入内容,这是需要借助组件实例上绑定的`insert`方法,参考[手动向文本框插入内容](/md-editor-rt/zh-CN/docs#%F0%9F%92%89%20insert)。
+
+如果不是在编辑器所在的组件中使用`config`,这是无法拿到编辑器组件实例,这时,你可能需要借助`event-bus`。
+
+示例实现`Ctrl+m`向编辑框插入标记模块(`==mark==`)
+
+`index.ts`
+
+```js
+import { config } from 'md-editor-rt';
+import { keymap, KeyBinding } from '@codemirror/view';
+// 假设你使用了EventBus
+import bus from '@/utils/event-bus';
+
+config({
+ // [keymap, minimalSetup, markdown, EditorView.lineWrapping, EditorView.updateListener, EditorView.domEventHandlers, oneDark??oneLight]
+ codeMirrorExtensions(theme, extensions, mdEditorCommands) {
+ const newExtensions = [...extensions];
+ // 1. 先把默认的快捷键扩展移除
+ newExtensions.shift();
+
+ // 2. 创建一个新的快捷键配置,参考https://codemirror.net/docs/ref/#commands
+ const CtrlM: KeyBinding = {
+ key: 'Ctrl-m',
+ mac: 'Cmd-m',
+ run: () => {
+ bus.emit('insertMarkBlock');
+ return true;
+ }
+ };
+
+ // 4. 把新的快捷键添加到数组中
+ const newMdEditorCommands = [...mdEditorCommands, CtrlM];
+
+ newExtensions.push(keymap.of(newMdEditorCommands));
+
+ return newExtensions;
+ }
+});
+```
+
+接下来在编辑器所在组件监听`insertMarkBlock`这个事件
+
+`App.tsx`
+
+```tsx
+import React, { useState, useRef, useEffect } from 'react';
+import { MdEditor, ExposeParam } from 'md-editor-rt';
+// 假设你使用了EventBus
+import bus from '@/utils/event-bus';
+
+import 'md-editor-rt/lib/style.css';
+
+const App = () => {
+ const [text] = useState('## md-editor-rt\n\n');
+ const mdEditorRef = useRef();
+
+ useEffect(() => {
+ bus.on('insertMarkBlock', () => {
+ mdEditorRef.current?.insert((selectedText) => {
+ return {
+ targetValue: `==${selectedText}==`,
+ select: true,
+ deviationStart: 2,
+ deviationEnd: -2
+ };
+ });
+ });
+ }, []);
+
+ return ;
+};
+```
+
+附:`EventBus`最简单实现
+
+```ts
+/* eslint-disable @typescript-eslint/ban-types */
+class EventBus {
+ private events: Map;
+
+ constructor() {
+ this.events = new Map();
+ }
+
+ on(eventName: string, fn: Function) {
+ if (!eventName) {
+ console.error('无效的事件名称');
+ return false;
+ }
+
+ if (!(fn instanceof Function)) {
+ console.error('无效的回调方法');
+ return false;
+ }
+
+ const fns = this.events.get(eventName) || [];
+ fns.push(fn);
+ this.events.set(eventName, fns);
+ }
+
+ emit(eventName: string, ...args: any[]) {
+ this.events.get(eventName)?.forEach((fn) => {
+ fn(args);
+ });
+ }
+}
+
+export default new EventBus();
+```
+
+### 🍦 主题切换
+
+主题分为了编辑器主题(`theme`,称为全局主题)、预览内容主题(`previewTheme`)和块级代码主题(`codeTheme`)。
+
+#### 🍧 编辑器主题
+
+支持默认和暗夜模式两种
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [theme] = useState('dark');
+ return ;
+};
+```
+
+#### 🍡 预览主题
+
+内置了`default`、`github`、`vuepress`、`mk-cute`、`smart-blue`、`cyanosis`6 种主题,在一些直接预览文档内容时使用。并且支持在线切换(修改`previewTheme`即可)和自行扩展。
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [previewTheme] = useState('github');
+ return ;
+};
+```
+
+- 自定义
+
+ 1. 先以`xxx-theme`为类名,定义你的主题`css`,xxx 是主题名称,具体的内容参考[markdown-theme](https://github.com/imzbf/markdown-theme)
+
+ _xxx.css_
+
+ ```css
+ .xxx-theme code {
+ color: red;
+ }
+ ```
+
+ 2. 全局引入
+
+ ```js
+ import 'xxx.css';
+ ```
+
+ 3. 设置`previewTheme`为 xxx
+
+ ```jsx
+
+ ```
+
+#### 🎄 代码主题
+
+内置了`atom`、`a11y`、`github`、`gradient`、`kimbie`、`paraiso`、`qtcreator`、`stackoverflow`代码主题,均来至[highlight.js](https://highlightjs.org/)
+
+- 使用
+
+ ```jsx
+ import React, { useState } from 'react';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [codeTheme] = useState('atom');
+ return ;
+ };
+ ```
+
+- 自定义
+
+ 1. 找到你喜欢的代码主题,最好支持暗夜模式
+
+ ```js
+ import { config } from 'md-editor-rt';
+
+ config({
+ editorExtensions: {
+ highlight: {
+ css: {
+ xxxxx: {
+ light: 'https://unpkg.com/highlight.js@11.2.0/styles/xxxxx-light.css',
+ dark: 'https://unpkg.com/highlight.js@11.2.0/styles/xxxxx-dark.css'
+ },
+ yyyyy: {
+ light: 'https://unpkg.com/highlight.js@11.2.0/styles/xxxxx-light.css',
+ dark: 'https://unpkg.com/highlight.js@11.2.0/styles/xxxxx-dark.css'
+ }
+ }
+ }
+ }
+ });
+ ```
+
+ 你可以通过将`css`的`key`设置为内置名称来覆盖内置的链接。
+
+ 2. 设置`codeTheme`
+
+ ```jsx
+
+ ```
+
+### 🛠 扩展库替换
+
+highlight、prettier、cropper、screenfull 均使用外链引入,在无外网的时候,部分可将项目中已安装的依赖传入,也可以使用下载好的引用。
+
+`screenfull` 的例子:
+
+#### ⚰️ 内置实例
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor, config } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+// 引用screenfull
+import screenfull from 'screenfull';
+
+config({
+ editorExtensions: {
+ screenfull: {
+ instance: screenfull
+ }
+ }
+});
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ return ;
+};
+```
+
+#### 📡 内网链接
+
+对应的 js 文件可以去[unpkg.com](https://unpkg.com),直接找到对应的文件下载即可。
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor, config } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+config({
+ editorExtensions: {
+ screenfull: {
+ js: 'https://localhost:8090/screenfull@5.2.0/index.js'
+ }
+ }
+});
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ return ;
+};
+```
+
+### 📷 图片上传
+
+默认可以选择多张图片,支持截图粘贴板上传图片,支持复制网页图片粘贴上传。
+
+> 注意:粘贴板上传时,如果是网页上的 gif 图,无法正确上传为 gif 格式!请保存本地后再手动上传。
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+const onUploadImg = async (files, callback) => {
+ const res = await Promise.all(
+ files.map((file) => {
+ return new Promise((rev, rej) => {
+ const form = new FormData();
+ form.append('file', file);
+
+ axios
+ .post('/api/img/upload', form, {
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+ .then((res) => rev(res))
+ .catch((error) => rej(error));
+ });
+ })
+ );
+
+ callback(res.map((item) => item.data.url));
+};
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ return ;
+};
+```
+
+### 🏳️🌈 语言扩展与替换
+
+```js
+import React, { useState } from 'react';
+import { MdEditor, config } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+config({
+ editorConfig: {
+ languageUserDefined: {
+ 'my-lang': {
+ toolbarTips: {
+ bold: '加粗',
+ underline: '下划线',
+ italic: '斜体',
+ strikeThrough: '删除线',
+ title: '标题',
+ sub: '下标',
+ sup: '上标',
+ quote: '引用',
+ unorderedList: '无序列表',
+ orderedList: '有序列表',
+ task: '任务列表',
+ codeRow: '行内代码',
+ code: '块级代码',
+ link: '链接',
+ image: '图片',
+ table: '表格',
+ mermaid: 'mermaid图',
+ katex: 'katex公式',
+ revoke: '后退',
+ next: '前进',
+ save: '保存',
+ prettier: '美化',
+ pageFullscreen: '浏览器全屏',
+ fullscreen: '屏幕全屏',
+ preview: '预览',
+ htmlPreview: 'html代码预览',
+ catalog: '目录',
+ github: '源码地址'
+ },
+ titleItem: {
+ h1: '一级标题',
+ h2: '二级标题',
+ h3: '三级标题',
+ h4: '四级标题',
+ h5: '五级标题',
+ h6: '六级标题'
+ },
+ imgTitleItem: {
+ link: '添加链接',
+ upload: '上传图片',
+ clip2upload: '裁剪上传'
+ },
+ linkModalTips: {
+ linkTitle: '添加链接',
+ imageTitle: '添加图片',
+ descLabel: '链接描述:',
+ descLabelPlaceHolder: '请输入描述...',
+ urlLabel: '链接地址:',
+ urlLabelPlaceHolder: '请输入链接...',
+ buttonOK: '确定'
+ },
+ clipModalTips: {
+ title: '裁剪图片上传',
+ buttonUpload: '上传'
+ },
+ copyCode: {
+ text: '复制代码',
+ successTips: '已复制!',
+ failTips: '复制失败!'
+ },
+ mermaid: {
+ flow: '流程图',
+ sequence: '时序图',
+ gantt: '甘特图',
+ class: '类图',
+ state: '状态图',
+ pie: '饼图',
+ relationship: '关系图',
+ journey: '旅程图'
+ },
+ katex: {
+ inline: '行内公式',
+ block: '块级公式'
+ },
+ footer: {
+ markdownTotal: '字数',
+ scrollAuto: '同步滚动'
+ }
+ }
+ }
+ }
+});
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [language] = useState('my-lang');
+
+ return ;
+};
+```
+
+你也可以使用现成的扩展语言:[md-editor-extension](https://github.com/imzbf/md-editor-extension)。使用及贡献方式见扩展库文档~
+
+### 📄 目录获取与展示
+
+- 获取
+
+ ```jsx
+ import React, { useState } from 'react';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [catalogList, setList] = useState([]);
+
+ return ;
+ };
+ ```
+
+- 展示
+
+ 使用内置`MdCatalog`组件
+
+ ```jsx
+ import React, { useState } from 'react';
+ import { MdPreview, MdCatalog } from 'md-editor-rt';
+ import 'md-editor-rt/lib/preview.css';
+
+ const editorId = 'my-editor';
+
+ export default () => {
+ const [state] = useState({
+ text: '# 标题',
+ scrollElement: document.documentElement
+ });
+
+ return (
+ <>
+
+
+ >
+ );
+ };
+ ```
+
+### 🪚 调整工具栏
+
+从`v1.2.0`开始,支持调整工具栏内容顺序和分割符了 🤔。
+
+```jsx
+import React, { useState } from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('hello md-editor-rt!');
+ const [toolbars] = useState(['italic', 'underline', '-', 'bold', '=', 'github']);
+
+ return ;
+};
+```
+
+### 💪 自定义工具栏
+
+这里包含了`mark`标记扩展普通工具栏和`emoji`扩展下拉工具栏的类型
+
+可运行源码参考本文档[docs](https://github.com/imzbf/md-editor-rt/blob/docs/src/pages/Preview/index.tsx)。
+
+![标记及Emoji预览](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+
+> 更多 emoji,[https://getemoji.com/](https://getemoji.com/)。
+
+### 🧙♂️ 调整编辑器样式
+
+2.x 使用 css 变量定义了大部分内容:
+
+```less
+.css-vars(@isDark) {
+ --md-color: if(@isDark, #999, #222);
+ --md-hover-color: if(@isDark, #bbb, #000);
+ --md-bk-color: if(@isDark, #000, #fff);
+ --md-bk-color-outstand: if(@isDark, #111, #f6f6f6);
+ --md-bk-hover-color: if(@isDark, #1b1a1a, #f5f7fa);
+ --md-border-color: if(@isDark, #2d2d2d, #e6e6e6);
+ --md-border-hover-color: if(@isDark, #636262, #b9b9b9);
+ --md-border-active-color: if(@isDark, #777, #999);
+ --md-modal-mask: #00000073;
+ --md-scrollbar-bg-color: if(@isDark, #0f0f0f, #e2e2e2);
+ --md-scrollbar-thumb-color: if(@isDark, #2d2d2d, #0000004d);
+ --md-scrollbar-thumb-hover-color: if(@isDark, #3a3a3a, #00000059);
+ --md-scrollbar-thumb-active-color: if(@isDark, #3a3a3a, #00000061);
+}
+
+.md-editor {
+ .css-vars(false);
+}
+
+.md-editor-dark {
+ .css-vars(true);
+}
+```
+
+只需要调整对应的 css 变量,比如调整暗夜模式下的背景:
+
+```css
+.md-editor-dark {
+ --md-bk-color: #333 !important;
+}
+```
+
+### 🙍🏻♂️ 自行引入扩展库
+
+这里给出一个完全不使用外部链接,全部自行引入的示例:
+
+```jsx
+import { MdEditor, config } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+import screenfull from 'screenfull';
+
+import katex from 'katex';
+import 'katex/dist/katex.min.css';
+
+import Cropper from 'cropperjs';
+import 'cropperjs/dist/cropper.css';
+
+import mermaid from 'mermaid';
+
+import highlight from 'highlight.js';
+import 'highlight.js/styles/atom-one-dark.css';
+
+// <3.0
+import prettier from 'prettier';
+import parserMarkdown from 'prettier/parser-markdown';
+// >=3.0
+import * as prettier from 'prettier';
+import parserMarkdown from 'prettier/plugins/markdown';
+
+// https://at.alicdn.com/t/c/font_2605852_u82y61ve02.js
+import './assets/iconfont.js';
+
+config({
+ editorExtensions: {
+ prettier: {
+ prettierInstance: prettier,
+ parserMarkdownInstance: parserMarkdown
+ },
+ highlight: {
+ instance: highlight
+ },
+ screenfull: {
+ instance: screenfull
+ },
+ katex: {
+ instance: katex
+ },
+ cropper: {
+ instance: Cropper
+ },
+ mermaid: {
+ instance: mermaid
+ }
+ }
+});
+
+export default () => {
+ return ;
+};
+```
+
+> 注意:highlight 的样式自行引入后,将不支持切换代码样式。
+
+## 🔒 xss 防范
+
+在`1.3.0`之后,通过`sanitize`事件,自行处理不安全的 html 内容。例如:使用`sanitize-html`处理
+
+```shell
+yarn add sanitize-html
+```
+
+```jsx
+import React from 'react';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+import sanitizeHtml from 'sanitize-html';
+
+export default () => {
+ return sanitizeHtml(html)} />;
+};
+```
+
+更详细的实现可以参考本文档的源码!
+
+## 🧻 编辑此页面
+
+[demo-zh-CN](https://github.com/imzbf/md-editor-rt/blob/dev-docs/public/demo-zh-CN.md)
diff --git a/docs/doc-en-US.md b/docs/doc-en-US.md
new file mode 100644
index 00000000..d4e52393
--- /dev/null
+++ b/docs/doc-en-US.md
@@ -0,0 +1,1648 @@
+> Use it online: [Go](https://codesandbox.io/s/elated-khorana-65jmr)
+
+## 🔖 MdPreview Props
+
+This is the props of `MdPreview`, which is also part of `MdEditor`:
+
+### 📃 modelValue
+
+- **type**: `string`
+- **default**: `''`
+
+ Markdown content.
+
+ ```jsx
+
+ ```
+
+---
+
+### 🛍 theme
+
+- **type**: `'light' | 'dark'`
+- **default**: `'light'`
+
+ Editor's theme.
+
+ ```jsx
+
+ ```
+
+---
+
+### 🎀 className
+
+- **type**: `string`
+- **default**: `''`
+
+ ...
+
+---
+
+### 🔤 language
+
+- **type**: `string`
+- **default**: `'zh-CN'`
+
+ Build-in language('zh-CN', 'en-US').
+
+ You can install the existing language also: [md-editor-extension](https://github.com/imzbf/md-editor-extension). Refer to extension library for the usage and the way to contribute~
+
+---
+
+### 🎲 editorId
+
+- **type**: `string`
+- **default**: `'md-editor-rt'`
+
+ Editor's id, also the html id, it is used when there are two or more editor and server render.
+
+---
+
+### 🔢 showCodeRowNumber
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Show row number for code block or not.
+
+---
+
+### 🔦 previewTheme
+
+- **type**: `'default' | 'github' | 'vuepress' | 'mk-cute' | 'smart-blue' | 'cyanosis'`
+- **default**: `'default'`
+
+ Preview themes.
+
+ Custom:
+
+ 1. Write css
+
+ ```css
+ .xxx-theme {
+ color: red;
+ }
+ ```
+
+ 2. Set `previewTheme`
+
+ ```jsx
+
+ ```
+
+ For more, refer to [markdown-theme](https://github.com/imzbf/markdown-theme).
+
+---
+
+### 🎅🏻 style
+
+- **type**: `CSSProperties`
+- **default**: `{}`
+
+ Editor inline style.
+
+---
+
+### ☝️ noMermaid
+
+- **type**: `boolean`
+- **default**: `false`
+
+ do not want to use `mermaid`, set it to `true`.
+
+ ```jsx
+
+ ```
+
+---
+
+### ❌ noKatex
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Do not want to use `katex`, set it to `true`.
+
+---
+
+### 🦉 codeTheme
+
+- **type**: `'atom'|'a11y'|'github'|'gradient'|'kimbie'|'paraiso'|'qtcreator'|'stackoverflow'`
+- **default**: `'atom'`
+
+ Highlight code css name. Get Them from `highlight.js`.
+
+ Custom:
+
+ 1. Config `editorExtensions`
+
+ ```js
+ import { config } from 'md-editor-rt';
+
+ config({
+ editorExtensions: {
+ highlight: {
+ css: {
+ atom: {
+ light:
+ 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-light.min.css',
+ dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-dark.min.css'
+ },
+ xxx: {
+ light:
+ 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-light.css',
+ dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-dark.css'
+ }
+ }
+ }
+ }
+ });
+ ```
+
+ 2. Set `codeTheme`
+
+ ```jsx
+
+ ```
+
+---
+
+### 🎱 mdHeadingId
+
+- **type**: `(text: string, level: number, index: number) => string`
+- **default**: `(text) => text`
+
+ Title `ID` generator.
+
+ ```jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const mdHeadingId = (_text, _level, index) => `heading-${index}`;
+
+ export default () => {
+ return ;
+ };
+ ```
+
+---
+
+### 🐣 sanitize
+
+- **type**: `(html: string) => string`
+- **default**: `(html) => html`
+
+ Sanitize the html, prevent XSS. When you can be sure that your content is OK, ignore this.
+
+ `sanitize-html` example:
+
+ ```jsx
+ import sanitizeHtml from 'sanitize-html';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const sanitize = (html) => sanitizeHtml(html);
+
+ export default () => {
+ return ;
+ };
+ ```
+
+---
+
+### 🤞🏼 noIconfont
+
+- **type**: `boolean`
+- **default**:`true`
+
+ Not append iconfont script, [download](https://at.alicdn.com/t/c/font_2605852_u82y61ve02.js) and import it by yourself.
+
+ ```jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ import '/assets/iconfont.js';
+
+ export default () => {
+ return ;
+ };
+ ```
+
+---
+
+### 💅 formatCopiedText
+
+- **type**: `(text: string) => string`
+- **default**: `(text) => text`
+
+ Format copied code
+
+ ```jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const formatCopiedText = (text: string) => {
+ return `${text} - from md-editor-rt`;
+ };
+
+ return ;
+ };
+ ```
+
+---
+
+### 🛁 codeStyleReverse
+
+- **type**: `boolean`
+- **default**: `true`
+
+ Code style will be reversed to dark while code block of the theme has a dark background.
+
+---
+
+### 🧼 codeStyleReverseList
+
+- **type**: `Array`
+- **default**: `['default', 'mk-cute']`
+
+ Themes to be reversed.
+
+---
+
+### 🕊 noHighlight
+
+- **type**: `boolean`
+- **default**: `false`
+
+ never highlight code
+
+---
+
+### 🕊 noImgZoomIn
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Enable the function of enlarging images.
+
+---
+
+## 🔩 MdEditor Props
+
+Except for the same as `MdPreview`:
+
+### 💻 pageFullscreen
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Screenfull in web page.
+
+---
+
+### 📱 preview
+
+- **type**: `boolean`
+- **default**: `true`
+
+ Preview content in editor.
+
+---
+
+### 📀 htmlPreview
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Preview html in editor. Set `preview` to `false` when `htmlPreview` is `true`.
+
+---
+
+### 🧱 toolbars
+
+- **type**: `Array`
+- **default**: `[all]`
+
+ Show contents of toolbar.
+
+ You can sort the toolbar as you like, split tools by `'-'`, the left and right toolbars are divided by `'='`!
+
+ _[all]_
+
+ ```js
+ [
+ 'bold',
+ 'underline',
+ 'italic',
+ '-',
+ 'strikeThrough',
+ 'sub',
+ 'sup',
+ 'quote',
+ 'unorderedList',
+ 'orderedList',
+ 'task',
+ '-',
+ 'codeRow',
+ 'code',
+ 'link',
+ 'image',
+ 'table',
+ 'mermaid',
+ 'katex',
+ '-',
+ 'revoke',
+ 'next',
+ 'save',
+ '=',
+ 'pageFullscreen',
+ 'fullscreen',
+ 'preview',
+ 'htmlPreview',
+ 'catalog',
+ 'github'
+ ];
+ ```
+
+---
+
+### 🧱 toolbarsExclude
+
+- **type**: `Array`
+- **default**: `[]`
+
+ Don't show some item of toolbars, all keys.
+
+---
+
+### 💪 defToolbars
+
+- **type**: `Array`
+- **default**: `[]`
+
+ Custom toolbar in `DropdownToolbar`, `NormalToolbar` or `ModalToolbar`. To display them, put index of `defToolbars` into `toolbars`(this is not standard).
+
+ ```jsx
+ import { MdEditor, NormalToolbar } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const handler = () => {
+ console.log('NormalToolbar clicked!');
+ };
+
+ export default () => {
+ return (
+
+
+
+ }
+ />
+ ]}
+ />
+ );
+ };
+ ```
+
+ ![NormalToolbar](https://imzbf.github.io/md-editor-rt/imgs/normal-toolbar.gif)
+
+ ![DropdownToolbar](https://imzbf.github.io/md-editor-rt/imgs/dropdown-toolbar.gif)
+
+ For more info, Get **Internal Components** heading. Get source code of **mark**, **emoji** and **modal preview** at [docs](https://github.com/imzbf/md-editor-rt/tree/docs/src/components) branch.
+
+---
+
+### 🪒 noPrettier
+
+- **type**: `boolean`
+- **default**: `true`
+
+ Use prettier to beautify content or not.
+
+---
+
+### 🤏 tabWidth
+
+- **type**: `number`
+- **default**: `2`
+
+ One tab eq some space.
+
+---
+
+### 📅 tableShape
+
+- **type**: `[number, number]`
+- **default**: `[6, 4]`
+
+ Preset the size of the table, [columns, rows].
+
+ ```jsx
+
+ ```
+
+ ![Preview](https://imzbf.github.io/md-editor-rt/imgs/20211216165424.png)
+
+---
+
+### 🪧 placeholder
+
+- **type**: `string`
+- **default**: `''`
+
+ em-\_-!
+
+---
+
+### 🦶 footers
+
+- **type**: `Array<'markdownTotal' \| '=' \| 'scrollSwitch' \| number>`
+- **default**: `['markdownTotal', '=', 'scrollSwitch']`
+
+ Show contents of footer, they are divided by `'='`. Set it to [] to hidden footer.
+
+---
+
+### 🦿 defFooters
+
+- **type**: `Array`
+- **default**: `[]`
+
+ Custom footer.
+
+ [Get](https://github.com/imzbf/md-editor-rt/blob/docs/src/pages/Preview/index.tsx) example code.
+
+---
+
+### ⛵️ scrollAuto
+
+- **type**: `boolean`
+- **default**: `true`
+
+ Scroll default setting.
+
+---
+
+### 🥹 noUploadImg
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Not show the entrance to upload pictures
+
+ ```jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ return ;
+ };
+ ```
+
+---
+
+### 🔬 autoFocus
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Same as `autofocus` in native textarea.
+
+---
+
+### 🔩 disabled
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Same as `disabled` in native textarea.
+
+---
+
+### 🔒 readOnly
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Same as `readonly` in native textarea.
+
+---
+
+### 📏 maxLength
+
+- **type**: `number`
+- **default**: ``
+
+ Same as `maxlength` in native textarea.
+
+---
+
+### 📥 autoDetectCode
+
+- **type**: `boolean`
+- **default**: `false`
+
+ Auto detect the type of pasted code, only support that copied from `vscode`.
+
+---
+
+### 📝 completions
+
+- **type**: `Array`
+- **default**: `[]`
+
+ Additional completion sources.
+
+ ```tsx
+ import { useMemo, useState } from 'react';
+ import { CompletionSource } from '@codemirror/autocomplete';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const [t, s] = useState('');
+
+ const completions = useMemo>(() => {
+ return [
+ (context) => {
+ const word = context.matchBefore(/@\w*/);
+
+ if (word === null || (word.from == word.to && context.explicit)) {
+ return null;
+ }
+
+ return {
+ from: word.from,
+ options: [
+ {
+ label: '@imzbf',
+ type: 'text'
+ }
+ ]
+ };
+ }
+ ];
+ }, []);
+
+ return ;
+ };
+ ```
+
+---
+
+### 📥 showToolbarName
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ Show toolbar name or not
+
+![](https://imzbf.github.io/md-editor-rt/imgs/showToolbarName.jpg)
+
+---
+
+## 🧵 MdPreview Events
+
+### 🚁 onHtmlChanged
+
+- **type**: `(h: string) => void`
+
+ Compile markdown successful event, you can use it to get the html code.
+
+---
+
+### 🗒 onGetCatalog
+
+- **type**: `(list: HeadList[]) => void`
+
+ Get catalogue of article.
+
+---
+
+## 🪢 MdEditor Events
+
+Except for the same as `MdPreview`:
+
+### 📞 onChange
+
+- **type**: `(v: string) => void`
+
+ Content changed event(bind to `oninput` of `textarea`).
+
+---
+
+### 💾 onSave
+
+- **type**: `(v: string, h: Promise) => void`
+
+ Saving content event, `ctrl+s` and clicking button will trigger it.
+
+ ```jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ return (
+ {
+ console.log(v);
+
+ h.then((html) => {
+ console.log(html);
+ });
+ }}
+ />
+ );
+ };
+ ```
+
+---
+
+### 📸 onUploadImg
+
+- **type**: `(files: Array, callback: (urls: Array) => void) => void`
+
+ Uploading picture event, when picture is uploading the modal will not close, please provide right urls to the callback function.
+
+```jsx
+import axios from 'axios';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+const onUploadImg = async (files, callback) => {
+ const res = await Promise.all(
+ files.map((file) => {
+ return new Promise((rev, rej) => {
+ const form = new FormData();
+ form.append('file', file);
+
+ axios
+ .post('/api/img/upload', form, {
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+ .then((res) => rev(res))
+ .catch((error) => rej(error));
+ });
+ })
+ );
+
+ callback(res.map((item) => item.data.url));
+};
+
+export default () => {
+ return ;
+};
+```
+
+---
+
+### 💀 onError
+
+- **type**: `(err: { name: 'Cropper' \| 'fullscreen' \| 'prettier' \| 'overlength'; message: string }) => void`
+
+ Run-Time error event, only be called when `Cropper`, `fullscreen`, `prettier` is not loaded. And content exceeds the length limit error.
+
+ ```jsx
+ const onError = (err) => {
+ alert(err.message);
+ };
+
+ export default () => ;
+ ```
+
+---
+
+### 🐾 onBlur
+
+- **type**: `(event: FocusEvent) => void`
+
+ Textarea has lost focus.
+
+ ```jsx
+ const onBlur = (err) => {
+ console.log('onBlur', e);
+ };
+
+ export default () => ;
+ ```
+
+---
+
+### 🔖 onFocus
+
+- **type**: `(event: FocusEvent) => void`
+
+ Textarea has received focus.
+
+---
+
+### 🔖 onInput
+
+- **type**: `(event: Event) => void`
+
+ Element gets input.
+
+---
+
+## 🤱🏼 Expose
+
+After 2.5.0, Editor exposes several methods on the instance, used to get or change the internal status of the editor.
+
+```jsx
+import React, { useState, useEffect, useRef } from 'react';
+import { MdEditor, ExposeParam } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('#Hello Editor');
+
+ const editorRef = useRef();
+
+ useEffect(() => {
+ editorRef.current?.on('catalog', console.log);
+ }, []);
+
+ return ;
+};
+```
+
+### 👂🏼 on
+
+Get the internal state of the editor, including pageFullscreen, fullscreen, preview, htmlPreview, catalog, etc.
+
+- pageFullscreen
+
+ ```js
+ editorRef.current?.on('pageFullscreen', (status) => console.log(status));
+ ```
+
+- fullscreen
+ ```js
+ editorRef.current?.on('fullscreen', (status) => console.log(status));
+ ```
+- preview
+ ```js
+ editorRef.current?.on('preview', (status) => console.log(status));
+ ```
+- htmlPreview
+ ```js
+ editorRef.current?.on('htmlPreview', (status) => console.log(status));
+ ```
+- catalog
+ ```js
+ editorRef.current?.on('catalog', (status) => console.log(status));
+ ```
+
+---
+
+### 💻 togglePageFullscreen
+
+Toggle status of fullscreen within the page.
+
+```js
+editorRef.current?.togglePageFullscreen(true);
+```
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 🖥 toggleFullscreen
+
+Toggle status of fullscreen widthin browser.
+
+```js
+editorRef.current?.toggleFullscreen(true);
+```
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 📖 togglePreview
+
+Toggle status of preview.
+
+```js
+editorRef.current?.togglePreview(true);
+```
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 📼 toggleHtmlPreview
+
+Toggle status of htmlPreview.
+
+```js
+editorRef.current?.toggleHtmlPreview(true);
+```
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 🧬 toggleCatalog
+
+Toggle status of catalog.
+
+```js
+editorRef.current?.toggleCatalog(true);
+```
+
+> Switched to the opposite status, without input parameter.
+
+---
+
+### 💾 triggerSave
+
+```js
+editorRef.current?.triggerSave();
+```
+
+---
+
+### 💉 insert
+
+Manually insert content into textarea.
+
+```js
+/**
+ * @params selectedText
+ */
+editorRef.current?.insert((selectedText) => {
+ /**
+ * @return targetValue Content to be inserted
+ * @return select Automatically select content
+ * @return deviationStart Start position of the selected content
+ * @return deviationEnd End position of the selected content
+ */
+ return {
+ targetValue: `${selectedText}`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+});
+```
+
+---
+
+### 🎯 focus
+
+Focus on the textarea.
+
+```ts
+import type { FocusOption } from 'md-editor-rt';
+
+const option: FocusOption | undefined = 'start';
+
+// Cursor position when focusing on textarea, default: position when it last lost focus
+editorRef.current?.focus(option);
+```
+
+```ts
+type FocusOption =
+ | 'start'
+ | 'end'
+ | {
+ // Start position, default cursor position
+ rangeAnchor?: number;
+ // End position, default cursor position
+ rangeHead?: number;
+ // Cursor position
+ cursorPos: number;
+ };
+```
+
+---
+
+## 💴 Config Editor
+
+Use `config(option: ConfigOption)` to reconfigure `markdown-it` and so on.
+
+### 🦪 codeMirrorExtensions
+
+Customize new extensions based on theme and default extensions f codeMirror.
+
+Example: Editor does not render the line number of textarea by default, this extension needs to be manually added
+
+```js
+import { config } from 'md-editor-rt';
+import { lineNumbers } from '@codemirror/view';
+
+config({
+ codeMirrorExtensions(_theme, extensions) {
+ return [...extensions, lineNumbers()];
+ }
+});
+```
+
+---
+
+### 🍤 markdownItConfig
+
+Customize extensions, attributes of `markdown-it`, etc.
+
+Example: Use `markdown-it-anchor` to render a hyperlink symbol to the right of the title
+
+```js
+import { config } from 'md-editor-rt';
+import ancher from 'markdown-it-anchor';
+
+config({
+ markdownItConfig(mdit) {
+ mdit.use(ancher, {
+ permalink: true
+ });
+ }
+});
+```
+
+---
+
+### 🍤 markdownItPlugins
+
+Select and add built-in plugins to `markdown-it`.
+
+Example: Modify the class name of the image.
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ markdownItPlugins(plugins) {
+ return plugins.map((p) => {
+ if (p.type === 'image') {
+ return {
+ ...p,
+ options: {
+ ...p.options,
+ classes: 'my-class'
+ }
+ };
+ }
+
+ return p;
+ });
+ }
+});
+```
+
+---
+
+### 🍙 editorConfig
+
+Add more languages, reset `mermaid` template or delay rendering time
+
+#### 🍚 languageUserDefined
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ languageUserDefined: {
+ 'en-US': {
+ toolbarTips: {
+ bold: 'bold',
+ underline: 'underline',
+ italic: 'italic',
+ strikeThrough: 'strikeThrough',
+ title: 'title',
+ sub: 'subscript',
+ sup: 'superscript',
+ quote: 'quote',
+ unorderedList: 'unordered list',
+ orderedList: 'ordered list',
+ codeRow: 'inline code',
+ code: 'block-level code',
+ link: 'link',
+ image: 'image',
+ table: 'table',
+ mermaid: 'mermaid',
+ katex: 'formula',
+ revoke: 'revoke',
+ next: 'undo revoke',
+ save: 'save',
+ prettier: 'prettier',
+ pageFullscreen: 'fullscreen in page',
+ fullscreen: 'fullscreen',
+ preview: 'preview',
+ htmlPreview: 'html preview',
+ catalog: 'catalog',
+ github: 'source code'
+ },
+ titleItem: {
+ h1: 'Lv1 Heading',
+ h2: 'Lv2 Heading',
+ h3: 'Lv3 Heading',
+ h4: 'Lv4 Heading',
+ h5: 'Lv5 Heading',
+ h6: 'Lv6 Heading'
+ },
+ imgTitleItem: {
+ link: 'Add Img Link',
+ upload: 'Upload Img',
+ clip2upload: 'Clip Upload'
+ },
+ linkModalTips: {
+ linkTitle: 'Add Link',
+ imageTitle: 'Add Image',
+ descLabel: 'Desc:',
+ descLabelPlaceHolder: 'Enter a description...',
+ urlLabel: 'Link:',
+ urlLabelPlaceHolder: 'Enter a link...',
+ buttonOK: 'OK'
+ },
+ clipModalTips: {
+ title: 'Crop Image',
+ buttonUpload: 'Upload'
+ },
+ copyCode: {
+ text: 'Copy',
+ successTips: 'Copied!',
+ failTips: 'Copy failed!'
+ },
+ mermaid: {
+ flow: 'flow',
+ sequence: 'sequence',
+ gantt: 'gantt',
+ class: 'class',
+ state: 'state',
+ pie: 'pie',
+ relationship: 'relationship',
+ journey: 'journey'
+ },
+ katex: {
+ inline: 'inline',
+ block: 'block'
+ },
+ footer: {
+ markdownTotal: 'Word Count',
+ scrollAuto: 'Scroll Auto'
+ }
+ }
+ }
+ }
+});
+```
+
+#### 🍘 mermaidTemplate
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // mermaid template
+ mermaidTemplate: {
+ flow: `flow tempalte`,
+ sequence: `sequence template`,
+ gantt: `gantt template`,
+ class: `class template`,
+ state: `state template`,
+ pie: `pie template`,
+ relationship: `relationship template`,
+ journey: `journey template`
+ }
+ }
+});
+```
+
+#### 🍥 renderDelay
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // delay rendering time(ms)
+ renderDelay: 0
+ }
+});
+```
+
+---
+
+### 🥠 editorExtensions
+
+Config some dependency libraries, like highlight..
+
+```typescript
+import { config } from 'md-editor-rt';
+
+config({
+ editorExtensions: { iconfont: 'https://xxx.cc' }
+});
+```
+
+
+ [EditorExtensions]
+
+```ts
+export interface EditorExtensions {
+ highlight?: {
+ instance?: any;
+ js?: string;
+ css?: {
+ [key: string]: {
+ light: string;
+ dark: string;
+ };
+ };
+ };
+ prettier?: {
+ // >= 2.2.0
+ prettierInstance?: any;
+ parserMarkdownInstance?: any;
+
+ standaloneJs?: string;
+ parserMarkdownJs?: string;
+ };
+ cropper?: {
+ instance?: any;
+ js?: string;
+ css?: string;
+ };
+ iconfont?: string;
+ screenfull?: {
+ instance?: any;
+ js?: string;
+ };
+ mermaid?: {
+ instance?: any;
+ js?: string;
+ };
+ katex?: {
+ instance?: any;
+ js?: string;
+ css?: string;
+ };
+}
+```
+
+
+
+---
+
+## 🪡 Shortcut Keys
+
+!!! warning Pay attention
+
+Shortcut keys are only available when the textarea has received focus!
+
+!!!
+
+| key | function | description |
+| --- | --- | --- |
+| TAB | insert space | Insert space, the length eq `tabWidth`, default: 2, support multiline |
+| SHIFT + TAB | delete space, setting is the same as Tab | |
+| CTRL + C | copy | When selected, copy the selected content. When not selected, copy the content of the current line |
+| CTRL + X | shear | When selected, cut the selected content. When not selected, cut the current line |
+| CTRL + D | delete | When selected, delete the selected content. When not selected, delete the current line |
+| CTRL + S | save | Trigger `onSave` event |
+| CTRL + B | bold text | `**bold**` |
+| CTRL + U | underline | `underline ` |
+| CTRL + I | italic | `*italic*` |
+| CTRL + 1-6 | h1-h6 | `# title` |
+| CTRL + ↑ | superscript | `superscript ` |
+| CTRL + ↓ | subscript | `subscript ` |
+| CTRL + O | ordered list | `1. ordered list` |
+| CTRL + L | link | `[link](https://github.com/imzbf/md-editor-rt)` |
+| CTRL + Z | withdraw | Withdraw history in editor, not the function of system |
+| CTRL + SHIFT + S | line-through | `~line-through~` |
+| CTRL + SHIFT + U | unordered list | `- unordered list` |
+| CTRL + SHIFT + C | code block | |
+| CTRL + SHIFT + I | picture | `![picture](https://imzbf.cc)` |
+| CTRL + SHIFT + Z | forward | Forward history in editor, not the function of system |
+| CTRL + SHIFT + F | Beautify | |
+| CTRL + ALT + C | code row | |
+| CTRL + SHIFT + ALT + T | table | `\|table\|` |
+
+## 🪤 Internal components
+
+On-demand import, eg: `import { DropdownToolbar } from 'md-editor-rt'`.
+
+After `v4.3.0`, `insert` will be automatically injected into the component by the editor.
+
+### 🐣 NormalToolbar
+
+- **props**
+
+ - `title`: `string`, not necessary, title of toolbar.
+ - `trigger`: `ReactNode`, necessary, it is usually an icon, which is displayed on the toolbar.
+
+- **events**
+
+ - `onClick`: `(e: MouseEvent) => void`, necessary.
+
+usage:
+
+```jsx
+import { useState } from 'react';
+import { MdEditor, NormalToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * `insert` will be automatically injected into the component by the editor
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ return (
+
+
+
+ }
+ onClick={() => {
+ insert((selectedText) => {
+ /**
+ * @return targetValue Content to be inserted
+ * @return select Automatically select content
+ * @return deviationStart Start position of the selected content
+ * @return deviationEnd End position of the selected content
+ */
+ return {
+ targetValue: `==${selectedText}==`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ key="mark-toolbar"
+ />
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+```
+
+[MarkExtension Source Code](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/MarkExtension/index.tsx)
+
+---
+
+### 🐼 DropdownToolbar
+
+- **props**
+
+ - `title`: `string`, not necessary, title of toolbar.
+ - `visible`: `boolean`, necessary.
+ - `trigger`: `ReactNode`, necessary, it is usually an icon, which is displayed on the toolbar.
+ - `overlay`: `ReactNode`, necessary, content of dropdown box.
+
+- **events**
+
+ - `onChange`: `(visible: boolean) => void`, necessary.
+
+usage:
+
+```jsx
+import { useState } from 'react';
+import { MdEditor, DropdownToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * `insert` will be automatically injected into the component by the editor
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ const [visible, setVisible] = useState(false);
+
+ return (
+
+ {
+ insert((selectedText) => {
+ /**
+ * @return targetValue Content to be inserted
+ * @return select Automatically select content
+ * @return deviationStart Start position of the selected content
+ * @return deviationEnd End position of the selected content
+ */
+ return {
+ targetValue: `==${selectedText}==`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ >
+ option 1
+
+ option 2
+
+ }
+ trigger={
+
+
+
+ }
+ key="emoji-toolbar"
+ />
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+```
+
+[EmojiExtension Source Code](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/EmojiExtension/index.tsx)
+
+---
+
+### 🦉 ModalToolbar
+
+- **props**
+
+ - `title`: `string`, not necessary, title of toolbar.
+ - `modalTitle`: `ReactNode`, not necessary, title of the Modal.
+ - `visible`: `boolean`, necessary, visibility of Modal.
+ - `width`: `string`, not necessary, width of Modal, default `auto`.
+ - `height`: `string`, same as `width`.
+ - `showAdjust`: `boolean`, not necessary, visibility of fullscreen button.
+ - `isFullscreen`: `boolean`, necessary when `showAdjust = true`, status of fullscreen.
+ - `trigger`: `ReactNode`, necessary, it is usually an icon, which is displayed on the toolbar.
+ - `children`: `ReactNode`, necessary, content of Modal.
+
+- **events**
+
+ - `onClick`: `() => void`, necessary.
+ - `onClose`: `() => void`, necessary, close event.
+ - `onAdjust`: `(val: boolean) => void`, fullscreen button click event.
+
+```jsx
+import { useState } from 'react';
+import { MdEditor, ModalToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * `insert` will be automatically injected into the component by the editor
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ const [visible, setVisible] = useState(false);
+ const [isFullscreen, setIsFullscreen] = useState(false);
+
+ return (
+ {
+ setVisible(true);
+ }}
+ onClose={() => {
+ setVisible(false);
+ }}
+ onAdjust={() => {
+ setIsFullscreen((i) => !i);
+ }}
+ trigger={
+
+
+
+ }
+ >
+
+ {
+ insert((selectedText) => {
+ /**
+ * @return targetValue Content to be inserted
+ * @return select Automatically select content
+ * @return deviationStart Start position of the selected content
+ * @return deviationEnd End position of the selected content
+ */
+ return {
+ targetValue: `==${selectedText}==`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ >
+ click me
+
+
+
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+```
+
+[ReadExtension Source Code](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/ReadExtension/index.tsx)
+
+---
+
+### 🐻 MdCatalog
+
+- **props**
+
+ - `editorId`: `string`, necessary, editor's `editorId`, used to register listening events.
+ - `className`: `string`, not necessary.
+ - `mdHeadingId`: `mdHeadingId`, not necessary, same as editor.
+ - `scrollElement`: `string | HTMLElement`, not necessary, it is an element selector when its type is string. When using `MdPreview`, it is usually set to `document.documentElement`.
+ - `theme`: 'light' | 'dark', not necessary, provide it when you want to change theme online, it is the same as Editor `theme`.
+ - `offsetTop`: `number`, not necessary, highlight current item of catalogs when title is `offsetTop` pixels from the top, default 20.
+ - `scrollElementOffsetTop`: `number`, not necessary, offsetTop of the scroll container,default 0.
+
+- **events**
+
+ - `onClick`: `(e: MouseEvent, t: TocItem) => void`, not necessary.
+
+usage:
+
+```jsx
+import { MdPreview, MdCatalog } from 'md-editor-rt';
+import 'md-editor-rt/lib/preview.css';
+
+const editorId = 'my-editor';
+
+export default () => {
+ const [state] = useState({
+ text: '# heading',
+ scrollElement: document.documentElement
+ });
+
+ return (
+ <>
+ {/* Ensure that the editorId is the same */}
+
+
+ >
+ );
+};
+```
+
+---
+
+### 🛸 MdModal
+
+It is usually used in conjunction with `DropdownToolbar`.
+
+- **props**
+
+ - `title`: `ReactNode`, not necessary, title of Modal.
+ - `visible`: `boolean`, necessary, visibility of Modal.
+ - `width`: `string`, not necessary, width of Modal, default `auto`.
+ - `height`: `string`, same as `width`.
+ - `showAdjust`: `boolean`, not necessary, visibility of fullscreen button.
+ - `isFullscreen`: `boolean`, necessary when `showAdjust = true`, status of fullscreen.
+ - `children`: `ReactNode`, necessary, content of Modal.
+ - `className`: `string`, not necessary.
+ - `style`: `CSSProperties`, not necessary.
+
+- **events**
+
+ - `onClose`: `() => void`, necessary, close event.
+ - `onAdjust`: `(val: boolean) => void`, fullscreen button click event.
+
+```jsx
+import { useState } from 'react';
+import { MdEditor, DropdownToolbar, MdModal } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+/**
+ * `insert` will be automatically injected into the component by the editor
+ */
+const MyToolbar = () => {
+ const [visible, setVisible] = useState(false);
+ const [mVisible, setMvisible] = useState(false);
+
+ return (
+
+ {
+ setMvisible(true);
+ }}
+ >
+ option 1
+
+ option 2
+
+ }
+ trigger={
+
+
+
+ }
+ key="modal-toolbar"
+ >
+ {
+ setMvisible(false);
+ }}
+ >
+ Content, Content
+
+
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+```
+
+---
+
+## ✍️ Edit This Page
+
+[doc-en-US](https://github.com/imzbf/md-editor-rt/blob/dev-docs/public/doc-en-US.md)
+
+```
+
+```
diff --git a/docs/doc-zh-CN.md b/docs/doc-zh-CN.md
new file mode 100644
index 00000000..745d845c
--- /dev/null
+++ b/docs/doc-zh-CN.md
@@ -0,0 +1,1688 @@
+> 在线尝试示例:[传送门](https://codesandbox.io/s/elated-khorana-65jmr)。
+
+## 🔖 MdPreview Props
+
+这是预览组件`MdPreview`的`Props`,它们同样也是`MdEditor`的:
+
+### 📃 modelValue
+
+- **类型**:`string`
+- **默认值**:`''`
+
+ 编辑的内容。
+
+ ```jsx
+
+ ```
+
+---
+
+### 🛍 theme
+
+- **类型**:`'light' | 'dark'`
+- **默认值**:`'light'`
+
+ 编辑器主题。
+
+ ```jsx
+
+ ```
+
+---
+
+### 🎀 className
+
+- **类型**:`string`
+- **默认值**:`''`
+
+ ...
+
+---
+
+### 🔤 language
+
+- **类型**:`string`
+- **默认值**:`'zh-CN'`
+
+ 内置中英文(`'zh-CN'`, `'en-US'`),可自行扩展其他语言,同时可覆盖内置的中英文。
+
+ 你也可以使用现成的扩展语言:[md-editor-extension](https://github.com/imzbf/md-editor-extension)。使用及贡献方式见扩展库文档~
+
+---
+
+### 🎲 editorId
+
+- **类型**:`string`
+- **默认值**:`'md-editor-rt'`
+
+ 编辑器唯一标识,非必须项,服务端渲染时,防止产生服务端与客户端渲染内容不一致错误提示,以及单页面多编辑器时做区别。
+
+---
+
+### 🔢 showCodeRowNumber
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 代码块是否显示行号。
+
+---
+
+### 🔦 previewTheme
+
+- **类型**:`'default' | 'github' | 'vuepress' | 'mk-cute' | 'smart-blue' | 'cyanosis'`
+- **默认值**:`'default'`
+
+ 预览内容主题,支持自定义。
+
+ 主题自定义方式:
+
+ 1. 编辑 css
+
+ ```css
+ .xxx-theme {
+ color: red;
+ }
+ ```
+
+ 2. 设置`previewTheme`
+
+ ```jsx
+
+ ```
+
+ 参考[markdown-theme](https://github.com/imzbf/markdown-theme)项目。
+
+---
+
+### 🎅🏻 style
+
+- **类型**:`CSSProperties`
+- **默认值**:`{}`
+
+ 编辑器内联样式。
+
+---
+
+### ☝️ noMermaid
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 如果你不希望使用图表展示内容,可以设置关闭。
+
+```jsx
+
+```
+
+---
+
+### ❌ noKatex
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 如果你不希望使用数学公式展示内容,可以设置关闭。
+
+```jsx
+
+```
+
+---
+
+### 🦉 codeTheme
+
+- **类型**:`'atom'|'a11y'|'github'|'gradient'|'kimbie'|'paraiso'|'qtcreator'|'stackoverflow'`
+- **默认值**:`'atom'`
+
+ 代码块高亮样式名称。
+
+ 你可以添加自己的样式,把该属性设置为你想要的即可,方式如下:
+
+ 1. 配置样式链接
+
+ ```js
+ import { config } from 'md-editor-rt';
+
+ config({
+ editorExtensions: {
+ highlight: {
+ css: {
+ atom: {
+ light:
+ 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-light.min.css',
+ dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/atom-one-dark.min.css'
+ },
+ xxx: {
+ light:
+ 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-light.css',
+ dark: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/xxx-dark.css'
+ }
+ }
+ }
+ }
+ });
+ ```
+
+ 2. 设置`codeTheme`
+
+ ```jsx
+
+ ```
+
+---
+
+### 🎱 mdHeadingId
+
+- **类型**:`(text: string, level: number, index: number) => string`
+- **默认值**:`(text) => text`
+
+ 构造标题`ID`的生成方式。
+
+ ```jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const mdHeadingId = (_text, _level, index) => `heading-${index}`;
+
+ export default () => {
+ return ;
+ };
+ ```
+
+---
+
+### 🐣 sanitize
+
+- **类型**:`(html: string) => string`
+- **默认值**:`(html) => html`
+
+ 在每次生成 html 后,通过该方法移除危险内容,比如 xss 相关,当你很确定你的内容不会出现类似情况时,不必设置它。
+
+ 使用`sanitize-html`演示
+
+ ```jsx
+ import sanitizeHtml from 'sanitize-html';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const sanitize = (html) => sanitizeHtml(html);
+
+ export default () => {
+ return ;
+ };
+ ```
+
+ > 为什么不内置到编辑器:由于类似编辑器大多属于自行处理文本,自身即可确认内容是否安全,并不需要该功能。
+
+---
+
+### 🤞🏼 noIconfont
+
+- **类型**:`boolean`
+- **默认值**:`true`
+
+ 不插入 iconfont 链接,你可以[下载](https://at.alicdn.com/t/c/font_2605852_u82y61ve02.js)到本地自行引入。
+
+ ```jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ import '/assets/iconfont.js';
+
+ export default () => {
+ return ;
+ };
+ ```
+
+---
+
+### 💅 formatCopiedText
+
+- **类型**:`(text: string) => string`
+- **默认值**:`(text) => text`
+
+ 格式化复制代码
+
+ ```jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const formatCopiedText = (text: string) => {
+ return `${text} - from md-editor-rt`;
+ };
+
+ export default () => {
+ return ;
+ };
+ ```
+
+---
+
+### 🛁 codeStyleReverse
+
+- **类型**:`boolean`
+- **默认值**:`true`
+
+ 某些预览主题的代码模块背景是暗色系,将这个属性设置为 true,会自动在该主题下的 light 模式下使用暗色系的代码风格。
+
+---
+
+### 🧼 codeStyleReverseList
+
+- **类型**:`Array`
+- **默认值**:`['default', 'mk-cute']`
+
+ 需要自动调整的预览主题,已默认包含 default、mk-cute。
+
+---
+
+### 🕊 noHighlight
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 不高亮代码,也不会加载相应的扩展库
+
+---
+
+### 🕊 noImgZoomIn
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 是否关闭编辑器默认的放大功能(`^4.4.0`)
+
+---
+
+## 🔩 MdEditor Props
+
+除去和`MdPreivew`相同的以外:
+
+### 💻 pageFullscreen
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 页面内全屏。
+
+---
+
+### 📱 preview
+
+- **类型**:`boolean`
+- **默认值**:`true`
+
+ 是否显示预览。
+
+---
+
+### 📀 htmlPreview
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 是否显示 html 预览。当设置为`true`时,需要将`preview`设置为`false`
+
+ ```jsx
+
+ ```
+
+---
+
+### 🧱 toolbars
+
+- **类型**:`Array`
+- **默认值**:`[all]`
+
+ 选择性展示工具栏,可选内容见下方。
+
+ 你可以随意排序工具栏,通过`'-'`分割两个工具,通过`'='`实现左右放置!
+
+ _[all]_
+
+ ```js
+ [
+ 'bold',
+ 'underline',
+ 'italic',
+ '-',
+ 'strikeThrough',
+ 'sub',
+ 'sup',
+ 'quote',
+ 'unorderedList',
+ 'orderedList',
+ 'task',
+ '-',
+ 'codeRow',
+ 'code',
+ 'link',
+ 'image',
+ 'table',
+ 'mermaid',
+ 'katex',
+ '-',
+ 'revoke',
+ 'next',
+ 'save',
+ '=',
+ 'pageFullscreen',
+ 'fullscreen',
+ 'preview',
+ 'htmlPreview',
+ 'catalog',
+ 'github'
+ ];
+
+ // 对应功能名称
+ [
+ '加粗',
+ '下划线',
+ '斜体',
+ '删除线',
+ '下标',
+ '上标',
+ '引用',
+ '无序列表',
+ '有序列表',
+ '任务',
+ '行内代码',
+ '块级代码',
+ '链接',
+ '图片',
+ '表格',
+ '图表',
+ '公式',
+ '后退一步',
+ '前进一步',
+ '保存',
+ '页面内全屏',
+ '屏幕全屏',
+ '内容预览',
+ 'html代码预览',
+ '目录',
+ '源码地址'
+ ];
+ ```
+
+---
+
+### 🧱 toolbarsExclude
+
+- **类型**:`Array`
+- **默认值**:`[]`
+
+ 选择性不展示工具栏,内容同上。
+
+---
+
+### 💪 defToolbars
+
+- **类型**:`Array`
+- **默认值**:`[]`
+
+ 自定义工具栏插槽,通过使用内置的`NormalToolbar`普通点击触发事件组件,`DropdownToolbar`下拉点击触发事件组件,和`ModalToolbar`弹窗组件进行扩展。将`defToolbars`插槽中的组件下标穿插在`toolbars`实现展示(这并不规范)
+
+ ```jsx
+ import { MdEditor, NormalToolbar } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ const handler = () => {
+ console.log('NormalToolbar clicked!');
+ };
+
+ export default () => {
+ return (
+
+
+
+ }
+ />
+ ]}
+ />
+ );
+ };
+ ```
+
+ ![普通扩展工具栏](https://imzbf.github.io/md-editor-rt/imgs/normal-toolbar.gif)
+
+ ![下拉扩展工具栏](https://imzbf.github.io/md-editor-rt/imgs/dropdown-toolbar.gif)
+
+ 扩展组件属性参考**内置组件**,使用示例参见[文档分支](https://github.com/imzbf/md-editor-rt/tree/docs/src/components),提供**标记**、**表情**和**弹窗预览**扩展组件。
+
+---
+
+### 🪒 noPrettier
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 是否启用 prettier 优化 md 内容。
+
+---
+
+### 🤏 tabWidth
+
+- **类型**:`number`
+- **默认值**:`2`
+
+ 编辑器一个 TAB 键等于空格数。
+
+---
+
+### 📅 tableShape
+
+- **类型**:`[number, number]`
+- **默认值**:`[6, 4]`
+
+ 标题栏添加表格时,预设待选表格大小,第一个代表最大列数,第二个代表最大行数。
+
+```jsx
+
+```
+
+![表格预设大小预览](https://imzbf.github.io/md-editor-rt/imgs/20211216165424.png)
+
+---
+
+### 🪧 placeholder
+
+- **类型**:`string`
+- **默认值**:`''`
+
+ 啊这-\_-!
+
+---
+
+### 🦶 footers
+
+- **类型**:`Array<'markdownTotal' | '=' | 'scrollSwitch' | number>`
+- **默认值**:`['markdownTotal', '=', 'scrollSwitch']`
+
+ 页脚显示内容,`'='`左右分割,设置为`[]`不显示页脚。
+
+---
+
+### 🦿 defFooters
+
+- **类型**:`Array`
+- **默认值**:`[]`
+
+ 自定义扩展页脚。
+
+ 示例代码见[文档页源码](https://github.com/imzbf/md-editor-rt/blob/docs/src/pages/Preview/index.tsx)。
+
+---
+
+### ⛵️ scrollAuto
+
+- **类型**:`boolean`
+- **默认值**:`true`
+
+ 默认左右同步滚动状态。
+
+---
+
+### 🥹 noUploadImg
+
+- **type**: `boolean`
+- **default**: `false`
+
+ 工具栏不显示上传图片入口。
+
+ ```jsx
+
+ ```
+
+---
+
+### 🔬 autoFocus
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 原生属性,文本区域自动获得焦点。
+
+---
+
+### 🔩 disabled
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 原生属性,禁用文本区域。
+
+---
+
+### 🔒 readOnly
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 原生属性,文本区域为只读。
+
+---
+
+### 📏 maxLength
+
+- **类型**:`number`
+- **默认值**:``
+
+ 原生属性,文本区域允许的最大字符数。
+
+---
+
+### 📥 autoDetectCode
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 是否启用自动识别粘贴代码类别,目前仅支持从`vscode`复制的内容。
+
+---
+
+### 📝 completions
+
+- **类型**:`Array`
+- **默认值**:`[]`
+
+ 添加额外的输入自动完成来源。
+
+ ```tsx
+ import { useMemo, useState } from 'react';
+ import { CompletionSource } from '@codemirror/autocomplete';
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ const [t, s] = useState('');
+
+ const completions = useMemo>(() => {
+ return [
+ (context) => {
+ const word = context.matchBefore(/@\w*/);
+
+ if (word === null || (word.from == word.to && context.explicit)) {
+ return null;
+ }
+
+ return {
+ from: word.from,
+ options: [
+ {
+ label: '@imzbf',
+ type: 'text'
+ }
+ ]
+ };
+ }
+ ];
+ }, []);
+
+ return ;
+ };
+ ```
+
+---
+
+### 📥 showToolbarName
+
+- **类型**:`boolean`
+- **默认值**:`false`
+
+ 是否在工具栏下面显示对应的文字名称
+
+![](https://imzbf.github.io/md-editor-rt/imgs/showToolbarName.jpg)
+
+---
+
+## 🧵 MdPreview 绑定事件
+
+### 🚁 onHtmlChanged
+
+- **类型**:`(h: string) => void`
+
+ html 变化回调事件,用于获取预览 html 代码。
+
+---
+
+### 🗒 onGetCatalog
+
+- **类型**:`(list: HeadList[]) => void`
+
+ 动态获取`markdown`目录。
+
+---
+
+## 🪢 MdEditor 绑定事件
+
+除去和`MdPreivew`相同的以外:
+
+### 📞 onChange
+
+- **类型**:`(v: string) => void`
+
+ 内容变化事件(当前与`textare`的`oninput`事件绑定,每输入一个单字即会触发)。
+
+---
+
+### 💾 onSave
+
+- **类型**:`(v: string, h: Promise) => void`
+
+ 保存事件,快捷键与保存按钮均会触发。
+
+ ```jsx
+ import { MdEditor } from 'md-editor-rt';
+ import 'md-editor-rt/lib/style.css';
+
+ export default () => {
+ return (
+ {
+ console.log(v);
+
+ h.then((html) => {
+ console.log(html);
+ });
+ }}
+ />
+ );
+ };
+ ```
+
+---
+
+### 📸 onUploadImg
+
+- **类型**:`(files: Array, callback: (urls: Array) => void) => void`
+
+ 上传图片事件,弹窗会等待上传结果,务必将上传后的 urls 作为 callback 入参回传。
+
+```jsx
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+import axios from 'axios';
+
+const onUploadImg = async (files, callback) => {
+ const res = await Promise.all(
+ files.map((file) => {
+ return new Promise((rev, rej) => {
+ const form = new FormData();
+ form.append('file', file);
+
+ axios
+ .post('/api/img/upload', form, {
+ headers: {
+ 'Content-Type': 'multipart/form-data'
+ }
+ })
+ .then((res) => rev(res))
+ .catch((error) => rej(error));
+ });
+ })
+ );
+
+ callback(res.map((item) => item.data.url));
+};
+
+export default () => {
+ return ;
+};
+```
+
+---
+
+### 💀 onError
+
+- **类型**:`(err: { name: 'Cropper' \| 'fullscreen' \| 'prettier' \| 'overlength'; message: string }) => void`
+
+ 捕获执行错误事件,目前支持`Cropper`、`fullscreen`、`prettier`实例未加载完成操作,以及输入内容超出限制长度的错误。
+
+ ```jsx
+ const onError = (err) => {
+ alert(err.message);
+ };
+
+ export default () => ;
+ ```
+
+---
+
+### 🐾 onBlur
+
+- **类型**:`(event: FocusEvent) => void`
+
+ 输入框失去焦点时触发事件。
+
+ ```jsx
+ const onBlur = (err) => {
+ console.log('onBlur', e);
+ };
+
+ export default () => ;
+ ```
+
+---
+
+### 🔖 onFocus
+
+- **类型**:`(event: FocusEvent) => void`
+
+ 输入框获得焦点时触发事件。
+
+---
+
+### 🔖 onInput
+
+- **类型**:`(event: Event) => void`
+
+ 输入框键入内容事件。
+
+---
+
+## 🤱🏼 实例暴露
+
+2.5.0 版本之后,编辑器暴露了若干方法在组件实例上,用来快捷监听编辑器内部状态或对调整内部状态。
+
+```jsx
+import React, { useState, useEffect, useRef } from 'react';
+import { MdEditor, ExposeParam } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default () => {
+ const [text, setText] = useState('#Hello Editor');
+
+ const editorRef = useRef();
+
+ useEffect(() => {
+ editorRef.current?.on('catalog', console.log);
+ }, []);
+
+ return ;
+};
+```
+
+### 👂🏼 on
+
+监听编辑器内部状态,包括:屏幕全屏、浏览器全屏、预览文本、预览 html、目录等。
+
+- pageFullscreen
+
+ ```js
+ editorRef.value?.on('pageFullscreen', (status) => console.log(status));
+ ```
+
+- fullscreen
+ ```js
+ editorRef.value?.on('fullscreen', (status) => console.log(status));
+ ```
+- preview
+ ```js
+ editorRef.value?.on('preview', (status) => console.log(status));
+ ```
+- htmlPreview
+ ```js
+ editorRef.value?.on('htmlPreview', (status) => console.log(status));
+ ```
+- catalog
+ ```js
+ editorRef.value?.on('catalog', (status) => console.log(status));
+ ```
+
+---
+
+### 💻 togglePageFullscreen
+
+切换页面内全屏。
+
+```js
+editorRef.value?.togglePageFullscreen(true);
+```
+
+> 不设置入参切换为相反状态
+
+---
+
+### 🖥 toggleFullscreen
+
+切换屏幕全屏。
+
+```js
+editorRef.value?.toggleFullscreen(true);
+```
+
+> 不设置入参切换为相反状态
+
+---
+
+### 📖 togglePreview
+
+切换是否显示预览。
+
+```js
+editorRef.value?.togglePreview(true);
+```
+
+> 不设置入参切换为相反状态
+
+---
+
+### 📼 toggleHtmlPreview
+
+切换是否显示 html 预览。
+
+```js
+editorRef.value?.toggleHtmlPreview(true);
+```
+
+> 不设置入参切换为相反状态
+
+---
+
+### 🧬 toggleCatalog
+
+切换是否显示目录。
+
+```js
+editorRef.value?.toggleCatalog(true);
+```
+
+> 不设置入参切换为相反状态
+
+---
+
+### 💾 triggerSave
+
+触发保存。
+
+```js
+editorRef.value?.triggerSave();
+```
+
+---
+
+### 💉 insert
+
+手动向文本框插入内容。
+
+```js
+/**
+ * @params selectedText 选中的内容
+ */
+editorRef.value?.insert((selectedText) => {
+ /**
+ * @return targetValue 待插入内容
+ * @return select 插入后是否自动选中内容
+ * @return deviationStart 插入后选中内容鼠标开始位置
+ * @return deviationEnd 插入后选中内容鼠标结束位置
+ */
+ return {
+ targetValue: `${selectedText}`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+});
+```
+
+---
+
+### 🎯 focus
+
+手动聚焦输入框。
+
+```ts
+import type { FocusOption } from 'md-editor-rt';
+
+const option: FocusOption | undefined = 'start';
+
+// 聚焦时光标的位置,不提供默认上次失焦时的位置
+editorRef.current?.focus(option);
+```
+
+```ts
+type FocusOption =
+ | 'start'
+ | 'end'
+ | {
+ // 选中的开始位置,默认光标位置
+ rangeAnchor?: number;
+ // 选中的结束位置,默认光标位置
+ rangeHead?: number;
+ // 光标的位置
+ cursorPos: number;
+ };
+```
+
+---
+
+## 💴 配置编辑器
+
+使用`config(option: ConfigOption)`方法,可以对构建实例进行定制。
+
+### 🦪 codeMirrorExtensions
+
+根据主题和内部默认的 codeMirror 扩展自定义新的扩展。
+
+使用示例:编辑器默认不显示输入框的行号,需要手动添加扩展
+
+```js
+import { config } from 'md-editor-rt';
+import { lineNumbers } from '@codemirror/view';
+
+config({
+ codeMirrorExtensions(_theme, extensions) {
+ return [...extensions, lineNumbers()];
+ }
+});
+```
+
+---
+
+### 🍤 markdownItConfig
+
+自定义 markdown-it 核心库扩展、属性等。
+
+使用示例:配置使用`markdown-it-anchor`并在标题右侧显示一个超链接符号
+
+```js
+import { config } from 'md-editor-rt';
+import ancher from 'markdown-it-anchor';
+
+config({
+ markdownItConfig(mdit) {
+ mdit.use(ancher, {
+ permalink: true
+ });
+ }
+});
+```
+
+---
+
+### 🍤 markdownItPlugins
+
+挑选、新增 markdown-it 核心库已预设的扩展。
+
+使用示例:修改图片的类名
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ markdownItPlugins(plugins) {
+ return plugins.map((p) => {
+ if (p.type === 'image') {
+ return {
+ ...p,
+ options: {
+ ...p.options,
+ classes: 'my-class'
+ }
+ };
+ }
+
+ return p;
+ });
+ }
+});
+```
+
+---
+
+### 🍙 editorConfig
+
+编辑器常规配置,语言、`mermaid`默认模板、渲染延迟:
+
+#### 🍚 languageUserDefined
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // 语言
+ languageUserDefined: {
+ 'my-lang': {
+ toolbarTips: {
+ bold: '加粗',
+ underline: '下划线',
+ italic: '斜体',
+ strikeThrough: '删除线',
+ title: '标题',
+ sub: '下标',
+ sup: '上标',
+ quote: '引用',
+ unorderedList: '无序列表',
+ orderedList: '有序列表',
+ codeRow: '行内代码',
+ code: '块级代码',
+ link: '链接',
+ image: '图片',
+ table: '表格',
+ mermaid: 'mermaid图',
+ katex: '公式',
+ revoke: '后退',
+ next: '前进',
+ save: '保存',
+ prettier: '美化',
+ pageFullscreen: '浏览器全屏',
+ fullscreen: '屏幕全屏',
+ preview: '预览',
+ htmlPreview: 'html代码预览',
+ catalog: '目录',
+ github: '源码地址'
+ },
+ titleItem: {
+ h1: '一级标题',
+ h2: '二级标题',
+ h3: '三级标题',
+ h4: '四级标题',
+ h5: '五级标题',
+ h6: '六级标题'
+ },
+ imgTitleItem: {
+ link: '添加链接',
+ upload: '上传图片',
+ clip2upload: '裁剪上传'
+ },
+ linkModalTips: {
+ linkTitle: '添加链接',
+ imageTitle: '添加图片',
+ descLabel: '链接描述:',
+ descLabelPlaceHolder: '请输入描述...',
+ urlLabel: '链接地址:',
+ urlLabelPlaceHolder: '请输入链接...',
+ buttonOK: '确定'
+ },
+ clipModalTips: {
+ title: '裁剪图片上传',
+ buttonUpload: '上传'
+ },
+ copyCode: {
+ text: '复制代码',
+ successTips: '已复制!',
+ failTips: '复制失败!'
+ },
+ mermaid: {
+ flow: '流程图',
+ sequence: '时序图',
+ gantt: '甘特图',
+ class: '类图',
+ state: '状态图',
+ pie: '饼图',
+ relationship: '关系图',
+ journey: '旅程图'
+ },
+ katex: {
+ inline: '行内公式',
+ block: '块级公式'
+ },
+ footer: {
+ markdownTotal: '字数',
+ scrollAuto: '同步滚动'
+ }
+ }
+ }
+ }
+});
+```
+
+#### 🍘 mermaidTemplate
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // mermaid模板
+ mermaidTemplate: {
+ // 流程图
+ flow: `flow tempalte`,
+ // 时序图
+ sequence: `sequence template`,
+ // 甘特图
+ gantt: `gantt template`,
+ // 类图
+ class: `class template`,
+ // 状态图
+ state: `state template`,
+ // 饼图
+ pie: `pie template`,
+ // 关系图
+ relationship: `relationship template`,
+ // 旅程图
+ journey: `journey template`
+ }
+ }
+});
+```
+
+#### 🍥 renderDelay
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ editorConfig: {
+ // 输入渲染延迟(ms)
+ renderDelay: 0
+ }
+});
+```
+
+---
+
+### 🥠 editorExtensions
+
+类型如下,用于配置编辑器内部的扩展
+
+```js
+import { config } from 'md-editor-rt';
+
+config({
+ editorExtensions: { iconfont: 'https://xxx.cc' }
+});
+```
+
+
+ [EditorExtensions]
+
+```ts
+export interface EditorExtensions {
+ highlight?: {
+ instance?: any;
+ js?: string;
+ css?: {
+ [key: string]: {
+ light: string;
+ dark: string;
+ };
+ };
+ };
+ prettier?: {
+ // >= 2.2.0
+ prettierInstance?: any;
+ parserMarkdownInstance?: any;
+
+ standaloneJs?: string;
+ parserMarkdownJs?: string;
+ };
+ cropper?: {
+ instance?: any;
+ js?: string;
+ css?: string;
+ };
+ iconfont?: string;
+ screenfull?: {
+ instance?: any;
+ js?: string;
+ };
+ mermaid?: {
+ instance?: any;
+ js?: string;
+ };
+ katex?: {
+ instance?: any;
+ js?: string;
+ css?: string;
+ };
+}
+```
+
+
+
+---
+
+## 🪡 快捷键
+
+主要以`CTRL`搭配对应功能英文单词首字母,冲突项添加`SHIFT`,再冲突替换为`ALT`。
+
+!!! warning 注意事项
+
+快捷键仅在输入框获取到焦点时可用!
+
+!!!
+
+| 键位 | 功能 | 说明 |
+| --- | --- | --- |
+| TAB | 空格 | 通过`tabWidth`属性预设 TAB 键位新增空格长度,默认 2,支持多行 |
+| SHIFT + TAB | 取消空格 | 同上,一次取消两个空格,支持多行 |
+| CTRL + C | 复制 | 选中时复制选中内容,未选中时复制当前行内容 |
+| CTRL + X | 剪切 | 选中时剪切选中内容,未选中时剪切当前行 |
+| CTRL + D | 删除 | 选中时删除选中内容,未选中时删除当前行 |
+| CTRL + S | 保存 | 触发编辑器的`onSave`回调 |
+| CTRL + B | 加粗 | `**加粗**` |
+| CTRL + U | 下划线 | `下划线 ` |
+| CTRL + I | 斜体 | `*斜体*` |
+| CTRL + 1-6 | 1-6 级标题 | `# 标题` |
+| CTRL + ↑ | 上角标 | `上角标 ` |
+| CTRL + ↓ | 下角标 | `下角标 ` |
+| CTRL + O | 有序列表 | `1. 有序列表` |
+| CTRL + L | 链接 | `[链接](https://imzbf.cc)` |
+| CTRL + Z | 撤回 | 触发编辑器内内容撤回,与系统无关 |
+| CTRL + SHIFT + S | 删除线 | `~删除线~` |
+| CTRL + SHIFT + U | 无序列表 | `- 无序列表` |
+| CTRL + SHIFT + C | 块级代码 | 多行代码块 |
+| CTRL + SHIFT + I | 图片链接 | `![图片](https://imzbf.cc)` |
+| CTRL + SHIFT + Z | 前进一步 | 触发编辑器内内容前进,与系统无关 |
+| CTRL + SHIFT + F | 美化内容 | |
+| CTRL + ALT + C | 行内代码 | 行内代码块 |
+| CTRL + SHIFT + ALT + T | 表格 | `\|表格\|` |
+
+## 🪤 内置组件
+
+按需引用编辑器的扩展组件,例如:`import { DropdownToolbar } from 'md-editor-rt'`。
+
+在`v4.3.0`以后, `insert`方法会由编辑器自动向组件的组件注入。
+
+### 🐣 NormalToolbar
+
+- **props**
+
+ - `title`: `string`,非必须,作为工具栏上的 hover 提示。
+ - `trigger`: `ReactNode`,必须,通常是个图标,用来展示在工具栏上。
+
+- **events**
+
+ - `onClick`: `(e: MouseEvent) => void`,必须,点击事件。
+
+```jsx
+import { useState } from 'react';
+import { MdEditor, NormalToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * `insert`方法会由编辑器自动向组件的组件注入。
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ return (
+
+
+
+ }
+ onClick={() => {
+ insert((selectedText) => {
+ /**
+ * @return targetValue 待插入内容
+ * @return select 插入后是否自动选中内容
+ * @return deviationStart 插入后选中内容鼠标开始位置
+ * @return deviationEnd 插入后选中内容鼠标结束位置
+ */
+ return {
+ targetValue: `==${selectedText}==`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ key="mark-toolbar"
+ />
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+```
+
+[标记组件的源码](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/MarkExtension/index.tsx)
+
+---
+
+### 🐼 DropdownToolbar
+
+- **props**
+
+ - `title`: `string`,非必须,作为工具栏上的 hover 提示。
+ - `visible`: `boolean`,必须,下拉状态。
+ - `trigger`: `ReactNode`,必须,通常是个图标,用来展示在工具栏上。
+ - `overlay`: `ReactNode`,必须,下拉框中的内容。
+
+- **events**
+
+ - `onChange`: `(visible: boolean) => void`,必须,状态变化事件。
+
+```jsx
+import { useState } from 'react';
+import { MdEditor, DropdownToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * `insert`方法会由编辑器自动向组件的组件注入。
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ const [visible, setVisible] = useState(false);
+
+ return (
+
+ {
+ insert((selectedText) => {
+ /**
+ * @return targetValue 待插入内容
+ * @return select 插入后是否自动选中内容
+ * @return deviationStart 插入后选中内容鼠标开始位置
+ * @return deviationEnd 插入后选中内容鼠标结束位置
+ */
+ return {
+ targetValue: `==${selectedText}==`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ >
+ option 1
+
+ option 2
+
+ }
+ trigger={
+
+
+
+ }
+ key="emoji-toolbar"
+ />
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+```
+
+[Emoji 组件的源码](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/EmojiExtension/index.tsx)
+
+---
+
+### 🦉 ModalToolbar
+
+- **props**
+
+ - `title`: `string`,非必须,作为工具栏上的 hover 提示。
+ - `modalTitle`: `ReactNode`,非必须,弹窗的标题。
+ - `visible`: `boolean`,必须,弹窗显示状态。
+ - `width`: `string`,非必须,弹窗宽度,默认`auto`。
+ - `height`:`string`,同`width`。
+ - `showAdjust`: `boolean`,非必须,是否显示弹窗全屏按钮。
+ - `isFullscreen`: `boolean`,显示全屏按钮时必须,弹窗全屏状态。
+ - `trigger`: `ReactNode`,必须,通常是个图标,用来展示在工具栏上。
+ - `children`: `ReactNode`,必须,弹窗中的内容。
+
+- **events**
+
+ - `onClick`: `() => void`,必须,工具栏点击事件。
+ - `onClose`:`() => void`,必须,弹窗点击关闭事件。
+ - `onAdjust`:`(val: boolean) => void`,弹窗全屏按钮点击事件。
+
+```jsx
+import { useState } from 'react';
+import { MdEditor, ModalToolbar, InsertContentGenerator } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+interface MyToolbarProps {
+ insert?: (generator: InsertContentGenerator) => void;
+}
+
+/**
+ * `insert`方法会由编辑器自动向组件的组件注入。
+ */
+const MyToolbar = ({ insert = () => {} }: MyToolbarProps) => {
+ const [visible, setVisible] = useState(false);
+ const [isFullscreen, setIsFullscreen] = useState(false);
+
+ return (
+ {
+ setVisible(true);
+ }}
+ onClose={() => {
+ setVisible(false);
+ }}
+ onAdjust={() => {
+ setIsFullscreen((i) => !i);
+ }}
+ trigger={
+
+
+
+ }
+ >
+
+ {
+ insert((selectedText) => {
+ /**
+ * @return targetValue 待插入内容
+ * @return select 插入后是否自动选中内容
+ * @return deviationStart 插入后选中内容鼠标开始位置
+ * @return deviationEnd 插入后选中内容鼠标结束位置
+ */
+ return {
+ targetValue: `==${selectedText}==`,
+ select: true,
+ deviationStart: 0,
+ deviationEnd: 0
+ };
+ });
+ }}
+ >
+ click me
+
+
+
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+```
+
+[阅读组件的源码](https://github.com/imzbf/md-editor-rt/blob/docs/src/components/ReadExtension/index.tsx)
+
+---
+
+### 🐻 MdCatalog
+
+- **props**
+
+ - `editorId`: `string`,必须,对应编辑器的`editorId`,在内部注册目录变化监听事件。
+ - `className`: `string`,非必须,目录组件最外层类名。
+ - `mdHeadingId`: `mdHeadingId`,非必须,特殊化编辑器标题的算法,与编辑器相同。
+ - `scrollElement`: `string | HTMLElement`,非必须,为字符时应是一个元素选择器。仅预览模式中,整页滚动时,设置为`document.documentElement`。
+ - `theme`: `'light' | 'dark'`,非必须,当需要切换主题时提供,同编辑器的`theme`。
+ - `offsetTop`: `number`,非必须,标题距离顶部该像素时高亮当前目录项,默认 20 像素。
+ - `scrollElementOffsetTop`: `number`,非必须,滚动区域的固定顶部高度,默认 0。
+
+- **events**
+
+ - `onClick`: `(e: MouseEvent, t: TocItem) => void`,非必须,导航点击事件。
+
+> `scrollElement`说明:仅预览下,该元素必须已定位的并且支持滚动。
+
+```jsx
+import { MdPreview, MdCatalog } from 'md-editor-rt';
+import 'md-editor-rt/lib/preview.css';
+
+const editorId = 'my-editor';
+
+export default () => {
+ const [state] = useState({
+ text: '# 标题',
+ scrollElement: document.documentElement
+ });
+
+ return (
+ <>
+ {/* 保证editorId是相同的 */}
+
+
+ >
+ );
+};
+```
+
+---
+
+### 🛸 MdModal
+
+编辑器内部的弹窗组件,它通常配合下拉工具栏组件使用。
+
+- **props**
+
+ - `title`: `ReactNode`,非必须,弹窗标题栏。
+ - `visible`: `boolean`,必须,弹窗显示状态。
+ - `width`: `string`,非必须,弹窗宽度,默认`auto`。
+ - `height`: `string`,同`width`。
+ - `showAdjust`: `boolean`,非必须,是否显示弹窗全屏按钮。
+ - `isFullscreen`: `boolean`,显示全屏按钮时必须,弹窗全屏状态。
+ - `children`: `ReactNode`,非必须,弹窗显示的内容。
+ - `className`: `string`,非必须,类名。
+ - `style`: `CSSProperties`,非必须,样式。
+
+- **events**
+
+ - `onClose`: `() => void`,必须,弹窗点击关闭事件。
+ - `onAdjust`: `(val: boolean) => void`,弹窗全屏按钮点击事件。
+
+```jsx
+import { useState } from 'react';
+import { MdEditor, DropdownToolbar, MdModal } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+/**
+ * `insert`方法会由编辑器自动向组件的组件注入。
+ */
+const MyToolbar = () => {
+ const [visible, setVisible] = useState(false);
+ const [mVisible, setMvisible] = useState(false);
+
+ return (
+
+ {
+ setMvisible(true);
+ }}
+ >
+ option 1
+
+ option 2
+
+ }
+ trigger={
+
+
+
+ }
+ key="emoji-toolbar"
+ >
+ {
+ setMvisible(false);
+ }}
+ >
+ Content, Content
+
+
+ );
+};
+
+export default () => {
+ const [value, setValue] = useState('');
+
+ return (
+ ]}
+ onChange={setValue}
+ />
+ );
+};
+```
+
+---
+
+## ✍️ 编辑此页面
+
+[doc-zh-CN](https://github.com/imzbf/md-editor-rt/blob/dev-docs/public/doc-zh-CN.md)
diff --git a/docs/grammar-en-US.md b/docs/grammar-en-US.md
new file mode 100644
index 00000000..6beafa86
--- /dev/null
+++ b/docs/grammar-en-US.md
@@ -0,0 +1,294 @@
+## 🐶 Heading
+
+```markdown
+## Heading
+```
+
+---
+
+## 🐱 Bold
+
+**I have a dream that one day this nation will rise up.**
+
+```markdown
+**I have a dream that one day this nation will rise up.**
+```
+
+---
+
+## 🐭 Italic
+
+_It is a dream deeply rooted in the American dream._
+
+```markdown
+_It is a dream deeply rooted in the American dream._
+```
+
+---
+
+## 🐹 Strikethrough
+
+~~It is a dream deeply rooted in the American dream.~~
+
+```markdown
+~~It is a dream deeply rooted in the American dream.~~
+```
+
+---
+
+## 🐻 Link
+
+[md-editor-rt](https://imzbf.github.io/md-editor-rt/)
+
+```markdown
+[md-editor-rt](https://imzbf.github.io/md-editor-rt/)
+```
+
+---
+
+## 🐼 Picture
+
+![Description](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+
+```markdown
+![Description](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+```
+
+---
+
+## 🙉 Underline
+
+So even though we face the difficulties of today and tomorrow, I still have a dream.
+
+```markdown
+So even though we face the difficulties of today and tomorrow, I still have a dream.
+```
+
+---
+
+## 🙊 Superscript
+
+I have a dream that one day this nation will rise up.[1]
+
+```markdown
+I have a dream that one day this nation will rise up.[1]
+```
+
+---
+
+## 🐒 Subscript
+
+I have a dream that one day this nation will rise up.[2]
+
+```markdown
+I have a dream that one day this nation will rise up.[2]
+```
+
+---
+
+## 🐰 Inline Code
+
+`md-editor-rt`
+
+```markdown
+`md-editor-rt`
+```
+
+---
+
+## 🦊 Block Code
+
+````markdown
+```js
+import MdEditor from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+```
+````
+
+### 🗄 Combination
+
+```shell [id:yarn]
+yarn add md-editor-rt
+```
+
+```shell [id:npm]
+npm install md-editor-rt
+```
+
+```shell [id:pnpm]
+pnpm install md-editor-rt
+```
+
+````markdown
+```shell [id:yarn]
+yarn add md-editor-rt
+```
+
+```shell [id:npm]
+npm install md-editor-rt
+```
+
+```shell [id:pnpm]
+pnpm install md-editor-rt
+```
+````
+
+---
+
+## 🐻❄️ Quote
+
+> Quote: I Have a Dream
+
+```markdown
+> Quote: I Have a Dream
+```
+
+---
+
+## 🐨 Ordered List
+
+1. So even though we face the difficulties of today and tomorrow, I still have a dream.
+2. It is a dream deeply rooted in the American dream.
+3. I have a dream that one day this nation will rise up.
+
+```markdown
+1. So even though we face the difficulties of today and tomorrow, I still have a dream.
+2. It is a dream deeply rooted in the American dream.
+3. I have a dream that one day this nation will rise up.
+```
+
+---
+
+## 🐯 Unordered List
+
+- So even though we face the difficulties of today and tomorrow, I still have a dream.
+- It is a dream deeply rooted in the American dream.
+- I have a dream that one day this nation will rise up.
+
+```markdown
+- So even though we face the difficulties of today and tomorrow, I still have a dream.
+- It is a dream deeply rooted in the American dream.
+- I have a dream that one day this nation will rise up.
+```
+
+---
+
+## 🦁 Task List
+
+- [ ] Friday
+- [ ] Saturday
+- [x] Sunday
+
+```markdown
+- [ ] Friday
+- [ ] Saturday
+- [x] Sunday
+```
+
+---
+
+## 🐮 Table
+
+| nickname | from |
+| -------- | ---------------- |
+| zhijian | ChongQing, China |
+
+```markdown
+| nickname | from |
+| -------- | ---------------- |
+| zhijian | ChongQing, China |
+```
+
+---
+
+## 🐷 Mathematical Formula
+
+Two modes.
+
+### 🐽 Inline
+
+$x+y^{2x}$
+
+```markdown
+$x+y^{2x}$
+```
+
+---
+
+### 🐸 Block
+
+$$\sqrt[3]{x}$$
+
+```markdown
+$$
+\sqrt[3]{x}
+$$
+
+or
+
+$$\sqrt[3]{x}$$
+```
+
+For more usage: [https://katex.org/docs/supported.html](https://katex.org/docs/supported.html)
+
+---
+
+## 🐵 Diagram
+
+```mermaid
+---
+title: Example Git diagram
+---
+gitGraph
+ commit
+ commit
+ branch develop
+ checkout develop
+ commit
+ commit
+ checkout main
+ merge develop
+ commit
+ commit
+```
+
+````markdown
+```mermaid
+---
+title: Example Git diagram
+---
+gitGraph
+ commit
+ commit
+ branch develop
+ checkout develop
+ commit
+ commit
+ checkout main
+ merge develop
+ commit
+ commit
+```
+````
+
+For more usage: [https://mermaid.js.org/syntax/flowchart.html](https://mermaid.js.org/syntax/flowchart.html)
+
+---
+
+## 🙈 Alert
+
+!!! note Supported Types
+
+note、abstract、info、tip、success、question、warning、failure、danger、bug、example、quote、hint、caution、error、attention
+
+!!!
+
+```markdown
+!!! note Supported Types
+
+note、abstract、info、tip、success、question、warning
+
+failure、danger、bug、example、quote、hint、caution、error、attention
+
+!!!
+```
diff --git a/docs/grammar-zh-CN.md b/docs/grammar-zh-CN.md
new file mode 100644
index 00000000..e57a6a9b
--- /dev/null
+++ b/docs/grammar-zh-CN.md
@@ -0,0 +1,292 @@
+## 🐶 标题
+
+```markdown
+## 标题
+```
+
+---
+
+## 🐱 加粗
+
+**I have a dream that one day this nation will rise up.**
+
+```markdown
+**I have a dream that one day this nation will rise up.**
+```
+
+---
+
+## 🐭 斜体
+
+_It is a dream deeply rooted in the American dream._
+
+```markdown
+_It is a dream deeply rooted in the American dream._
+```
+
+---
+
+## 🐹 删除线
+
+~~It is a dream deeply rooted in the American dream.~~
+
+```markdown
+~~It is a dream deeply rooted in the American dream.~~
+```
+
+---
+
+## 🐻 超链接
+
+[md-editor-rt](https://imzbf.github.io/md-editor-rt/)
+
+```markdown
+[md-editor-rt](https://imzbf.github.io/md-editor-rt/)
+```
+
+---
+
+## 🐼 图片
+
+![描述文字](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+
+```markdown
+![描述文字](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+```
+
+---
+
+## 🙉 下划线
+
+So even though we face the difficulties of today and tomorrow, I still have a dream.
+
+```markdown
+So even though we face the difficulties of today and tomorrow, I still have a dream.
+```
+
+---
+
+## 🙊 上标
+
+I have a dream that one day this nation will rise up.[1]
+
+```markdown
+I have a dream that one day this nation will rise up.[1]
+```
+
+---
+
+## 🐒 下标
+
+I have a dream that one day this nation will rise up.[2]
+
+```markdown
+I have a dream that one day this nation will rise up.[2]
+```
+
+---
+
+## 🐰 行内代码
+
+`md-editor-rt`
+
+```markdown
+`md-editor-rt`
+```
+
+---
+
+## 🦊 块级代码
+
+````markdown
+```js
+import MdEditor from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+```
+````
+
+### 🗄 代码组合
+
+```shell [id:yarn]
+yarn add md-editor-rt
+```
+
+```shell [id:npm]
+npm install md-editor-rt
+```
+
+```shell [id:pnpm]
+pnpm install md-editor-rt
+```
+
+````markdown
+```shell [id:yarn]
+yarn add md-editor-rt
+```
+
+```shell [id:npm]
+npm install md-editor-rt
+```
+
+```shell [id:pnpm]
+pnpm install md-editor-rt
+```
+````
+
+---
+
+## 🐻❄️ 引用
+
+> 引用:《I Have a Dream》
+
+```markdown
+> 引用:《I Have a Dream》
+```
+
+---
+
+## 🐨 有序列表
+
+1. So even though we face the difficulties of today and tomorrow, I still have a dream.
+2. It is a dream deeply rooted in the American dream.
+3. I have a dream that one day this nation will rise up.
+
+```markdown
+1. So even though we face the difficulties of today and tomorrow, I still have a dream.
+2. It is a dream deeply rooted in the American dream.
+3. I have a dream that one day this nation will rise up.
+```
+
+---
+
+## 🐯 无序列表
+
+- So even though we face the difficulties of today and tomorrow, I still have a dream.
+- It is a dream deeply rooted in the American dream.
+- I have a dream that one day this nation will rise up.
+
+```markdown
+- So even though we face the difficulties of today and tomorrow, I still have a dream.
+- It is a dream deeply rooted in the American dream.
+- I have a dream that one day this nation will rise up.
+```
+
+---
+
+## 🦁 任务列表
+
+- [ ] 周五
+- [ ] 周六
+- [x] 周天
+
+```markdown
+- [ ] 周五
+- [ ] 周六
+- [x] 周天
+```
+
+---
+
+## 🐮 表格
+
+| 昵称 | 来自 |
+| ---- | --------- |
+| 之间 | 中国-重庆 |
+
+```markdown
+| 昵称 | 来自 |
+| ---- | --------- |
+| 之间 | 中国-重庆 |
+```
+
+---
+
+## 🐷 数学公式
+
+有两种模式
+
+### 🐽 行内
+
+$x+y^{2x}$
+
+```markdown
+$x+y^{2x}$
+```
+
+### 🐸 块级
+
+$$\sqrt[3]{x}$$
+
+```markdown
+$$
+\sqrt[3]{x}
+$$
+
+或者
+
+$$\sqrt[3]{x}$$
+```
+
+更多公式示例参考:[https://katex.org/docs/supported.html](https://katex.org/docs/supported.html)
+
+---
+
+## 🐵 图表
+
+```mermaid
+---
+title: Example Git diagram
+---
+gitGraph
+ commit
+ commit
+ branch develop
+ checkout develop
+ commit
+ commit
+ checkout main
+ merge develop
+ commit
+ commit
+```
+
+````markdown
+```mermaid
+---
+title: Example Git diagram
+---
+gitGraph
+ commit
+ commit
+ branch develop
+ checkout develop
+ commit
+ commit
+ checkout main
+ merge develop
+ commit
+ commit
+```
+````
+
+更多图形示例参考:[https://mermaid.js.org/syntax/flowchart.html](https://mermaid.js.org/syntax/flowchart.html)
+
+---
+
+## 🙈 提示
+
+!!! note 支持的类型
+
+note、abstract、info、tip、success、question、warning、failure、danger、bug、example、quote、hint、caution、error、attention
+
+!!!
+
+```markdown
+!!! note 支持的类型
+
+note、abstract、info、tip、success、question、warning
+
+failure、danger、bug、example、quote、hint、caution、error、attention
+
+!!!
+```
diff --git a/docs/imgs/20211216165424.png b/docs/imgs/20211216165424.png
new file mode 100644
index 00000000..b3e62abf
Binary files /dev/null and b/docs/imgs/20211216165424.png differ
diff --git a/docs/imgs/dropdown-toolbar.gif b/docs/imgs/dropdown-toolbar.gif
new file mode 100644
index 00000000..64c9b3fb
Binary files /dev/null and b/docs/imgs/dropdown-toolbar.gif differ
diff --git a/docs/imgs/mark_emoji.gif b/docs/imgs/mark_emoji.gif
new file mode 100644
index 00000000..4cd7af63
Binary files /dev/null and b/docs/imgs/mark_emoji.gif differ
diff --git a/docs/imgs/normal-toolbar.gif b/docs/imgs/normal-toolbar.gif
new file mode 100644
index 00000000..6668906a
Binary files /dev/null and b/docs/imgs/normal-toolbar.gif differ
diff --git a/docs/imgs/preview-dark.png b/docs/imgs/preview-dark.png
new file mode 100644
index 00000000..c80a4efa
Binary files /dev/null and b/docs/imgs/preview-dark.png differ
diff --git a/docs/imgs/preview-light.png b/docs/imgs/preview-light.png
new file mode 100644
index 00000000..187ea114
Binary files /dev/null and b/docs/imgs/preview-light.png differ
diff --git a/docs/imgs/preview-previewOnly.png b/docs/imgs/preview-previewOnly.png
new file mode 100644
index 00000000..e850e16d
Binary files /dev/null and b/docs/imgs/preview-previewOnly.png differ
diff --git a/docs/imgs/showToolbarName.jpg b/docs/imgs/showToolbarName.jpg
new file mode 100644
index 00000000..5d96d783
Binary files /dev/null and b/docs/imgs/showToolbarName.jpg differ
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 00000000..407a6a15
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+ MdEditorRT Documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/preview-en-US.md b/docs/preview-en-US.md
new file mode 100644
index 00000000..ba364f5a
--- /dev/null
+++ b/docs/preview-en-US.md
@@ -0,0 +1,72 @@
+## 😲 md-editor-rt
+
+Markdown Editor for React, developed in jsx and typescript, support different themes、beautify content by prettier.
+
+### 🤖 Base
+
+**bold**, underline , _italic_, ~~line-through~~, superscript26 ,subscript[1] ,`inline code`,[link](https://imzbf.cc)
+
+> quote: I Have a Dream
+
+1. So even though we face the difficulties of today and tomorrow, I still have a dream.
+2. It is a dream deeply rooted in the American dream.
+3. I have a dream that one day this nation will rise up.
+
+- [ ] Friday
+- [ ] Saturday
+- [x] Sunday
+
+![Picture](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+
+## 🤗 Demo
+
+```js
+import { defineComponent, ref } from 'vue';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default defineComponent({
+ name: 'MdEditor',
+ setup() {
+ const text = ref('');
+ return () => (
+ (text.value = v)} />
+ );
+ }
+});
+```
+
+## 🖨 Text
+
+The Old Man and the Sea served to reinvigorate Hemingway's literary reputation and prompted a reexamination of his entire body of work.
+
+## 📈 Table
+
+| nickname | from |
+| -------- | ---------------- |
+| zhijian | ChongQing, China |
+
+## 📏 Formula
+
+Inline: $x+y^{2x}$
+
+$$
+\sqrt[3]{x}
+$$
+
+## 🧬 Diagram
+
+```mermaid
+flowchart TD
+ Start --> Stop
+```
+
+## 🪄 Alert
+
+!!! note Supported Types
+
+note、abstract、info、tip、success、question、warning、failure、danger、bug、example、quote、hint、caution、error、attention
+
+!!!
+
+## ☘️ em...
diff --git a/docs/preview-zh-CN.md b/docs/preview-zh-CN.md
new file mode 100644
index 00000000..85cb638f
--- /dev/null
+++ b/docs/preview-zh-CN.md
@@ -0,0 +1,72 @@
+## 😲 md-editor-rt
+
+Markdown 编辑器,React 版本,使用 jsx 和 typescript 语法开发,支持切换主题、prettier 美化文本等。
+
+### 🤖 基本演示
+
+**加粗**,下划线 ,_斜体_,~~删除线~~,上标26 ,下标[1] ,`inline code`,[超链接](https://imzbf.cc)
+
+> 引用:《I Have a Dream》
+
+1. So even though we face the difficulties of today and tomorrow, I still have a dream.
+2. It is a dream deeply rooted in the American dream.
+3. I have a dream that one day this nation will rise up.
+
+- [ ] 周五
+- [ ] 周六
+- [x] 周天
+
+![图片](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif)
+
+## 🤗 代码演示
+
+```js
+import { defineComponent, ref } from 'vue';
+import { MdEditor } from 'md-editor-rt';
+import 'md-editor-rt/lib/style.css';
+
+export default defineComponent({
+ name: 'MdEditor',
+ setup() {
+ const text = ref('');
+ return () => (
+ (text.value = v)} />
+ );
+ }
+});
+```
+
+## 🖨 文本演示
+
+依照普朗克长度这项单位,目前可观测的宇宙的直径估计值(直径约 930 亿光年,即 8.8 × 1026 米)即为 5.4 × 1061 倍普朗克长度。而可观测宇宙体积则为 8.4 × 10184 立方普朗克长度(普朗克体积)。
+
+## 📈 表格演示
+
+| 昵称 | 来自 |
+| ---- | --------- |
+| 之间 | 中国-重庆 |
+
+## 📏 公式
+
+行内:$x+y^{2x}$
+
+$$
+\sqrt[3]{x}
+$$
+
+## 🧬 图表
+
+```mermaid
+flowchart TD
+ Start --> Stop
+```
+
+## 🪄 提示
+
+!!! note 支持的类型
+
+note、abstract、info、tip、success、question、warning、failure、danger、bug、example、quote、hint、caution、error、attention
+
+!!!
+
+## ☘️ 占个坑@!