Permission is hereby granted, free of charge, to any person obtaining a copy
371 | of this software and associated documentation files (the "Software"), to deal
372 | in the Software without restriction, including without limitation the rights
373 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
374 | copies of the Software, and to permit persons to whom the Software is
375 | furnished to do so, subject to the following conditions:
376 |
The above copyright notice and this permission notice shall be included in
377 | all copies or substantial portions of the Software.
378 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
379 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
380 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
381 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
382 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
383 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
384 | THE SOFTWARE.
385 |
386 |
387 |
388 |
389 |
390 |
On This Page
391 |
392 |
393 |
394 |
395 |
396 |
397 |
412 |
413 |
414 |
415 |
--------------------------------------------------------------------------------
/docs/dist/normal.css:
--------------------------------------------------------------------------------
1 | @import"https://fonts.googleapis.com/css2?family=Source+Serif+4:ital@0;1&family=Cousine:wght@400;700&family=Nunito+Sans:opsz,wght@6..12,500;6..12,700&display=swap";.font-sample-sans{font-family:var(--sans-font)}.font-sample-serif{font-family:var(--serif-font)}.font-sample-mono{font-family:var(--mono-font)}.color-samples{display:flex;height:4rem;line-height:4rem;text-align:center;font-family:var(--sans-font)}.color-samples div{flex-grow:2}.color-samples .prim{color:var(--col-sec);background-color:var(--col-prim)}.color-samples .prim-light{color:var(--col-sec-light);background-color:var(--col-prim-light)}.color-samples .prim-dark{color:var(--col-sec-dark);background-color:var(--col-prim-dark)}.color-samples .sec{color:var(--col-prim);background-color:var(--col-sec)}.color-samples .sec-light{color:var(--col-prim-light);background-color:var(--col-sec-light)}.color-samples .sec-dark{color:var(--col-prim-dark);background-color:var(--col-sec-dark)}[data-theme=ice-age]{--col-sec: hsl(222, 40%, 90%);--col-sec-dark: hsl(222, 40%, 99%);--col-sec-light: hsl(222, 40%, 81%);--col-prim: hsl(223, 15%, 37%);--col-prim-dark: hsl(223, 15%, 46%);--col-prim-light: hsl(223, 15%, 28%);--cnt-link-color: lightsteelblue;--cnt-link-visited-color: steelblue}[data-theme=ultra-violet]{--col-prim: hsl(185, 13%, 81%);--col-prim-light: hsl(185, 13%, 90%);--col-prim-dark: hsl(185, 13%, 72%);--col-sec: hsl(269, 35%, 38%);--col-sec-light: hsl(269, 35%, 47%);--col-sec-dark: hsl(269, 35%, 29%)}[data-theme=chocolate]{--col-prim: hsl(29, 69%, 92%);--col-prim-light: hsl(29, 69%, 100%);--col-prim-dark: hsl(29, 69%, 83%);--col-sec: hsl(5, 21%, 42%);--col-sec-light: hsl(5, 21%, 51%);--col-sec-dark: hsl(5, 21%, 33%)}[data-theme=red-alert]{--col-prim: hsl(9, 54%, 97%);--col-prim-light: hsl(9, 54%, 100%);--col-prim-dark: hsl(9, 54%, 88%);--col-sec: hsl(353, 100%, 30%);--col-sec-light: hsl(353, 100%, 39%);--col-sec-dark: hsl(353, 100%, 21%)}[data-theme=blueberry]{--col-prim: hsl(40, 42%, 82%);--col-prim-light: hsl(40, 42%, 91%);--col-prim-dark: hsl(40, 42%, 73%);--col-sec: hsl(248, 19%, 24%);--col-sec-light: hsl(248, 19%, 33%);--col-sec-dark: hsl(248, 19%, 15%)}[data-theme=book-cover]{--col-sec: hsl(33, 87%, 63%);--col-sec-dark: hsl(33, 87%, 72%);--col-sec-light: hsl(33, 87%, 54%);--col-prim: hsl(213, 20%, 11%);--col-prim-dark: hsl(213, 20%, 20%);--col-prim-light: hsl(213, 20%, 2%);--toc-link-color: lightgray;--cnt-color: lightgray;--cnt-link-color: lightsteelblue;--cnt-link-visited-color: steelblue}[data-theme=vintage]{--col-prim: hsl(345, 6%, 14%);--col-prim-light: hsl(345, 6%, 5%);--col-prim-dark: hsl(345, 6%, 23%);--col-sec: hsl(25, 36%, 79%);--col-sec-light: hsl(25, 36%, 70%);--col-sec-dark: hsl(25, 36%, 88%);--cnt-header-color: lightblue;--cnt-link-color: lightsteelblue;--cnt-link-visited-color: steelblue}[data-theme=greyhound]{--col-prim: hsl(0, 0%, 92%);--col-prim-light: hsl(0, 0%, 100%);--col-prim-dark: hsl(0, 0%, 83%);--col-sec: hsl(222, 29%, 27%);--col-sec-light: hsl(222, 29%, 36%);--col-sec-dark: hsl(222, 29%, 18%)}[data-theme=mustard]{--col-sec: hsl(42, 73%, 57%);--col-sec-dark: hsl(42, 73%, 66%);--col-sec-light: hsl(42, 73%, 48%);--col-prim: hsl(352, 53%, 19%);--col-prim-dark: hsl(352, 53%, 28%);--col-prim-light: hsl(352, 53%, 10%);--cnt-link-color: lightsteelblue;--cnt-link-visited-color: steelblue}[data-theme=peachy]{--col-prim: hsl(19, 79%, 65%);--col-prim-light: hsl(19, 79%, 74%);--col-prim-dark: hsl(19, 79%, 56%);--col-sec: hsl(233, 56%, 18%);--col-sec-light: hsl(233, 56%, 27%);--col-sec-dark: hsl(233, 56%, 9%)}[data-theme=brownie]{--col-prim: hsl(33, 51%, 71%);--col-prim-light: hsl(33, 51%, 80%);--col-prim-dark: hsl(33, 51%, 62%);--col-sec: hsl(11, 66%, 35%);--col-sec-light: hsl(11, 66%, 44%);--col-sec-dark: hsl(11, 66%, 26%)}[data-theme=camouflage]{--col-prim: hsl(77, 11%, 87%);--col-prim-light: hsl(77, 11%, 96%);--col-prim-dark: hsl(77, 11%, 78%);--col-sec: hsl(154, 7%, 19%);--col-sec-light: hsl(154, 7%, 28%);--col-sec-dark: hsl(154, 7%, 10%)}body{--sans-font: "Nunito Sans";--serif-font: "Source Serif 4";--mono-font: "Cousine";--col-prim: hsl(29, 69%, 92%);--col-prim-light: hsl(29, 69%, 100%);--col-prim-dark: hsl(29, 69%, 83%);--col-sec: hsl(5, 21%, 42%);--col-sec-light: hsl(5, 21%, 51%);--col-sec-dark: hsl(5, 21%, 33%);--col-prim-text: var(--col-sec);--col-prim-text-light: var(--col-sec-light);--col-prim-text-dark: var(--col-sec-dark);--col-sec-text: var(--col-prim);--col-sec-text-light: var(--col-prim-dark);--col-sec-text-dark: var(--col-prim-light);--nav-text-transform: capitalize;--nav-horz-padding: .5rem;--nav-vert-padding: .5rem;--nav-font-size: 1.2rem;--nav-transition: .3s;--nav-button-justify: flex-start;--nav-button-spacing: .5rem;--nav-border-radius: 4px;--nav-bg-color: var(--col-sec-light);--nav-border-color: var(--col-sec);--nav-text-color: var(--col-prim);--nav-title-color: var(--col-prim-light);--nav-text-hover: var(--col-prim-light);--nav-icon-color: var(--col-prim-dark);--nav-text-height: calc(1.3 * var(--nav-font-size));--nav-height: calc(var(--nav-text-height) + (var(--nav-vert-padding) * 2));--hamburger-height: var(--nav-text-height);--toc-transition: .3s;--scrollbar-width: 4px;--scrollbar-color: var(--col-prim);--scrollbar-hover: var(--col-prim-dark);--toc-header-font-size: 1rem;--toc-font-size: .9rem;--toc-border-width: 2px;--toc-sideicon-radius: @nav-button-radius;--toc-bg-color: var(--col-prim);--toc-text-color: var(--col-sec);--toc-link-color: var(--toc-text-color);--toc-ruler-color: var(--col-prim-dark);--toc-hover-color: var(--col-sec-light);--toc-hover-bg: var(--col-prim-light);--toc-scrollbar-color: var(--col-prim-dark);--toc-scrollbar-hover: var(--col-sec-light);--pm-transition: .3s;--pm-header-font-size: 1rem;--pm-font-size: .9rem;--pm-bg-color: var(--cnt-bg-color);--pm-text-color: var(--col-sec);--pm-ruler-color: var(--col-prim-dark);--pm-hover-color: var(--col-sec-dark);--cnt-font: var(--serif-font);--cnt-header-font: var(--sans-font);--cnt-font-size: 1.1rem;--cnt-mono-font-size: .9rem;--cnt-width: 80ch;--cnt-margin: 1rem;--cnt-color: var(--col-sec-dark);--cnt-header-color: var(--col-sec);--cnt-bg-color: var(--col-prim-light);--cnt-pre-color: var(--col-prim);--cnt-border-color: var(--col-prim);--cnt-dark-border: var(--col-prim-dark);--cnt-link-color: blue;--cnt-link-visited-color: darkblue;--cnt-link-hover-color: dodgerblue;--cnt-link-active-color: orange;--ftr-color: var(--col-prim);--ftr-dark-color: var(--col-prim-dark);--ftr-bg-color: var(--col-sec);--ftr-font-family: var(--sans-font);--ftr-font-size: 1rem;--ftr-padding: 1rem;--ftr-border-color: var(--col-sec-light);--ftr-text-hover: var(--col-prim-light);--tooltip-color: var(--col-sec-text);--tooltip-bg-color: var(--col-sec);--tooltip-border-color: var(--col-sec-light);--lnd-background: var(--col-prim);--lnd-background-attachment: fixed;--lnd-background-repeat: no-repeat;--lnd-title-color: var(--col-prim-text);--lnd-title-font-size: 12vw;--lnd-title-font-weight: bold;--lnd-info-background-color: @color-white;--lnd-info-text-color: @color-text}.narrow-scrollbars::-webkit-scrollbar{background:transparent}.narrow-scrollbars::-webkit-scrollbar:horizontal{height:var(--scrollbar-width)}.narrow-scrollbars::-webkit-scrollbar:vertical{width:var(--scrollbar-width)}.narrow-scrollbars::-webkit-scrollbar-thumb{border-radius:calc(var(--scrollbar-width) / 2)}.narrow-scrollbars::-webkit-scrollbar-thumb:hover{background-color:var(--scrollbar-hover)!important}.narrow-scrollbars:hover::-webkit-scrollbar-thumb{background-color:var(--scrollbar-color)}pre.syntaxhighlight{--code-tab-size: 4;color:var(--code-text-color);background:var(--code-background-color);-moz-tab-size:var(--code-tab-size);-o-tab-size:var(--code-tab-size);tab-size:var(--code-tab-size);-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden}pre.syntaxhighlight .tooltip-inner{max-width:1000px}pre.syntaxhighlight .punctuation{color:var(--punctuation-color)}pre.syntaxhighlight .keyword,pre.syntaxhighlight .attribute,pre.syntaxhighlight .attr{color:var(--keyword-color);font-weight:var(--keyword-font-weight, normal)}pre.syntaxhighlight .comment{color:var(--comment-color)}pre.syntaxhighlight .member,pre.syntaxhighlight .selector-class{color:var(--member-color)}pre.syntaxhighlight .string{color:var(--string-color);background:var(--string-background-color, var(--code-background-color))}pre.syntaxhighlight .number,pre.syntaxhighlight .literal{color:var(--number-color)}pre.syntaxhighlight .typename,pre.syntaxhighlight .variable{color:var(--typename-color);font-weight:var(--typename-font-weight, normal)}pre.syntaxhighlight a,pre.syntaxhighlight a:visited{color:inherit}pre.syntaxhighlight a:hover span{color:var(--link-hover-color);text-decoration:underline}pre.syntaxhighlight a:active span{color:var(--link-active-color);text-decoration:underline}[data-syntax-highlight=monokai]{--code-text-color: #f8f8f2;--code-background-color: #272822;--link-hover-color: blue;--link-active-color: blueviolet;--punctuation-color: #d0d0c8;--keyword-color: #66d9ef;--comment-color: slategray;--member-color: #a6e22e;--string-color: #f92672;--number-color: #ae81ff;--typename-color: #e6db74}[data-syntax-highlight=coding-horror]{--code-text-color: #000000;--code-background-color: #F8F8F8;--link-hover-color: blue;--link-active-color: blueviolet;--punctuation-color:#000000;--keyword-color: #000080;--keyword-font-weight: bold;--comment-color: #008000;--member-color: slategray;--string-color: #000000;--string-background-color: #ffffe6;--number-color: #800000;--typename-color: #a65300}[data-syntax-highlight=solarized-light]{--code-text-color: #657b83;--code-background-color: #fdf6e3;--link-hover-color: blue;--link-active-color: blueviolet;--punctuation-color:#719a07;--keyword-color: #859900;--comment-color: #93a1a1;--member-color: #cb4b16;--string-color: #2aa198;--number-color: #2aa14e;--typename-color: #b58900;--typename-font-weight: bold}[data-syntax-highlight=son-of-obsidian]{--code-text-color: #f1f2f2;--code-background-color: #22282a;--link-hover-color: deepskyblue;--link-active-color: blueviolet;--punctuation-color: #e8e2b7;--keyword-color: #93c763;--comment-color: #66747b;--member-color: #a082bd;--string-color: #ec7600;--number-color: #ffcd22;--typename-color: #678cb1}@layer components,site,content;@layer site{body{margin:0}.layout{--toc-width: 20%;--pm-width: 20%;display:flex;flex-direction:row;justify-content:space-between;margin-top:calc(var(--nav-height));background-color:var(--cnt-bg-color)}.layout>div{flex-grow:0;flex-shrink:0}.sidepane{--scrollbar-color: transparent;position:sticky;top:0;height:100dvh;height:100vh;overflow-x:hidden;overflow-y:auto;transition:width var(--toc-transition)}.sidepane{--scrollbar-color: var(--toc-scrollbar-color);--scrollbar-hover: var(--toc-scrollbar-hover)}.sidepane:first-of-type{background-color:var(--toc-bg-color);border:solid var(--toc-border-width) var(--toc-ruler-color);width:var(--toc-width)}.sidepane:last-of-type{width:var(--pm-width)}.toc-button{display:none;height:100%;justify-content:center;align-items:center;cursor:pointer}.toc-button svg{stroke:var(--col-sec-light)}.layout.toc-open .toc-button{display:none}.layout.toc-open .tocmenu{display:block}@media only screen and (max-width: 1300px){.layout{--toc-width: min(24px, 5%) ;--pm-width: 25%}.tocmenu{display:none}.toc-button{display:flex}.layout.toc-open{--toc-width: min(75%, 35ch) ;--pm-width: 0px}}@media only screen and (max-width: 1100px){.layout{--pm-width: 0px}}@media only screen and (max-width: 850px){.layout{--cnt-width: 85%}}.contentarea{width:var(--cnt-width);margin:var(--cnt-margin);scroll-behavior:smooth}}@layer components{#navbar{--title-font-size: var(--nav-font-size);font-family:var(--sans-font);position:fixed;top:0;left:0;width:100%;display:flex;align-items:flex-start;z-index:101;transition:top var(--nav-transition),height var(--nav-transition)}#navbar,.navitem>.navmenu{background-color:var(--nav-bg-color);color:var(--nav-icon-color);border:solid 1px var(--nav-border-color);border-radius:var(--nav-border-radius)}.navmenu{display:flex;flex-grow:100;align-items:stretch}.navitem{position:relative;cursor:pointer;display:flex;align-items:center}.navitem>.navmenu{display:none;position:absolute;overflow:auto;flex-direction:column;flex-wrap:wrap;min-width:max-content;max-height:50vh;align-items:stretch;top:100%;left:0;z-index:102}.navitem:hover>.navmenu{display:flex}.navitem.active>a{color:var(--nav-text-hover)}.navitem.active:after{content:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='icon icon-tabler icon-tabler-check' viewBox='0 0 24 24' stroke-width='1.5' stroke='lime' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke='none' d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M5 12l5 5l10 -10' /%3E%3C/svg%3E");width:2ch;height:2ch;padding-right:1ch}.navitem a{text-wrap:nowrap;flex-grow:1;display:flex;align-items:center;text-decoration:none;user-select:none;color:var(--nav-text-color);font-size:calc(var(--nav-font-size) - 3px);text-transform:var(--nav-text-transform);padding:var(--nav-vert-padding) var(--nav-horz-padding)}#navbar>.navmenu>.navitem>a{margin-right:var(--nav-button-spacing)}.navitem a:hover{text-shadow:0 0 1px var(--nav-text-hover)}.navitem a svg,.navitem a img{height:var(--title-font-size);stroke:var(--nav-icon-color)}.navitem a span{margin-left:4px}.navitem a.title{color:var(--nav-title-color);font-size:var(--title-font-size)}.navitem a.title svg,.navitem a.title img{height:var(--nav-text-height)}#navbar .hamburger{display:none;margin:var(--nav-vert-padding) var(--nav-horz-padding)}@media only screen and (max-width: 800px){#navbar:not(.expanded)>.navmenu>.navitem:not(:first-child){display:none}#navbar .hamburger{display:block}.navitem>.navmenu{left:4ch}#navbar.expanded>.navmenu a{display:flex;font-size:var(--title-font-size)}#navbar.expanded>.navmenu{flex-direction:column;align-items:stretch;padding-bottom:var(--nav-vert-padding)}}}@layer components{.hamburger{--hamburger-size: calc((var(--hamburger-height) / 6) + 1px);--hamburger-offs: calc(var(--hamburger-size) * 1.4);--hamburger-width: calc(var(--hamburger-height) + 6px);display:block;cursor:pointer}.bar1,.bar2,.bar3{width:var(--hamburger-width);height:var(--hamburger-size);background-color:currentColor;border-radius:2px;transition:transform var(--nav-transition)}.bar2{margin:var(--hamburger-size) 0}.hamburger.open .bar1{transform:rotate(-45deg) translate(calc(0px - var(--hamburger-offs)),var(--hamburger-offs))}.hamburger.open .bar2{opacity:0}.hamburger.open .bar3{transform:rotate(45deg) translate(calc(0px - var(--hamburger-offs)),calc(0px - var(--hamburger-offs)))}}@layer components{#tooltip{--font: var(--sans-font);--arrow-size: 4px;--arrow-border-size: calc(var(--arrow-size) + 1px);position:absolute;padding:4px;z-index:9999;font-family:var(--font);font-size:14px;background-color:var(--tooltip-bg-color);border-radius:4px;color:var(--tooltip-color);border:1px solid var(--tooltip-border-color);opacity:0%;transform:translateY(-110%);transition:opacity .5s}#tooltip:after,#tooltip:before{top:100%;left:min(1em,50%);border:solid transparent;content:"";height:0;width:0;position:absolute;pointer-events:none}#tooltip:after{border-top-color:var(--tooltip-bg-color);border-width:var(--arrow-size);margin-left:calc(0 - var(--arrow-size))}#tooltip:before{border-top-color:var(--tooltip-border-color);border-width:var(--arrow-border-size);margin-left:calc(0 - var(--arrow-border-size))}}@layer components{.tocmenu{--highlight-bar-width: 3px;--highlight-margin: 10px;--padding-vert: calc(var(--toc-font-size) * .2);margin:1rem;color:var(--toc-text-color);font-family:var(--sans-font);font-size:var(--toc-font-size)}.tocmenu h3{font-size:var(--toc-header-font-size);font-weight:700;margin-block:.5rem;padding-inline:0;--divider-color: var(--toc-ruler-color);border-bottom:solid calc(var(--toc-font-size) / 8) var(--toc-ruler-color)}.tocmenu ul{list-style:none;overflow:hidden;margin-block:0;padding-inline:0;transition:max-height var(--toc-transition)}.tocmenu ul ul{margin-left:var(--toc-font-size)}.tocmenu a{text-decoration:none;color:var(--toc-link-color);display:grid;grid-template-columns:3ch auto;align-items:baseline;padding:var(--padding-vert) 0 var(--padding-vert) var(--highlight-margin)}.tocmenu a.highlight{border-left:var(--highlight-bar-width) solid var(--toc-ruler-color);padding-left:calc(var(--highlight-margin) - var(--highlight-bar-width));font-weight:700}.tocmenu a:hover{background:linear-gradient(to right,var(--toc-hover-bg),transparent)}.accordion{display:flex;justify-content:space-between;border-top:2px solid var(--toc-ruler-color);cursor:pointer;padding:var(--padding-vert) 0;margin-top:var(--padding-vert);margin-left:var(--highlight-margin);width:100%;font-weight:700;font-size:var(--toc-header-font-size)}.accordion>svg{width:var(--toc-font-size);stroke:var(--toc-ruler-color);margin:0 var(--highlight-margin) 0 5px;transition:transform var(--toc-transition)}.accordion.collapsed>svg{transform:rotate(180deg)}.accordion:hover{border-top-color:var(--toc-hover-color)}.accordion:hover>svg{stroke:var(--toc-hover-color)}}@layer content{.contentarea{--radius: 4px;font-family:var(--cnt-font);font-size:var(--cnt-font-size);color:var(--cnt-color);line-height:1.6em}.contentarea a{color:var(--cnt-link-color);text-decoration:none}.contentarea a:visited{color:var(--cnt-link-visited-color)}.contentarea a:hover{color:var(--cnt-link-hover-color)}.contentarea a:active{color:var(--cnt-link-active-color)}.contentarea a:focus{outline:thin dotted}.contentarea a:hover,.contentarea a:active{outline:0}.contentarea p{margin:1rem 0;margin-block-start:.5rem;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.contentarea p code,.contentarea ul code,.contentarea ol code{color:var(--cnt-header-color);background-color:var(--cnt-border-color);padding:3px 4px;border-radius:var(--radius)}.contentarea img{max-width:100%;float:right;margin:0 0 1rem 1rem}.contentarea h1,.contentarea h2,.contentarea h3,.contentarea h4,.contentarea h5,.contentarea h6{font-family:var(--cnt-header-font);font-weight:400;color:var(--cnt-header-color);line-height:1em;margin-block:0;padding-inline:0;clear:both}.contentarea h1{margin:1rem 0 2rem;font-size:2rem;font-weight:700;border-bottom:.1em var(--cnt-border-color) solid}.contentarea h2{font-size:1.6rem}.contentarea h3{font-size:1.4rem}.contentarea h2,.contentarea h3{margin:2.5rem 0 0;border-bottom:.1em var(--cnt-border-color) solid}.contentarea blockquote{font-style:italic;font-size:1rem;margin:1rem;text-align:justify;padding:1rem 2rem;box-shadow:4px 4px 0 var(--cnt-dark-border);background-color:var(--col-prim);max-width:90%}.contentarea blockquote:before{display:block;padding-left:10px;content:"\201c";font-size:3rem;position:relative;left:-2.5rem;top:.5rem;height:0}.contentarea hr{display:block;height:2px;border:0;border-top:1px solid #aaa;border-bottom:1px solid #eee;margin:1em 0;padding:0}.contentarea code,.contentarea pre{font-family:var(--mono-font);font-size:var(--cnt-mono-font-size);line-height:1.5em;tab-size:4;hyphens:none}.contentarea pre:not(.syntaxhighlight){background-color:var(--cnt-pre-color)}.contentarea pre{padding:1em;border-radius:var(--radius);overflow-x:auto;overflow-y:hidden;clear:both}.contentarea pre.console{background-color:#000;color:#d3d3d3}.contentarea pre.console:before{content:"> ";color:#a9a9a9}.contentarea b,.contentarea strong{font-weight:700}.contentarea ins{background:#ff9;color:#000;text-decoration:none}.contentarea mark{background:#ff0;color:#000;font-style:italic;font-weight:700}.contentarea sub,.contentarea sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}.contentarea sup{top:-.5em}.contentarea sub{bottom:-.25em}.contentarea ul,.contentarea ol{margin:1em 0;padding:0 0 0 2em}.contentarea p+ul,.contentarea p+ol{margin-top:-.5em}.contentarea li{padding-left:.5em}.contentarea dd{margin:0 0 0 2em}.contentarea table{border-collapse:collapse;border:1px solid var(--col-prim-dark);border-radius:.5em;margin-inline:auto;overflow:hidden;color:var(--col-prim-text);padding:1em}.contentarea tbody tr:nth-child(odd){background-color:var(--col-prim-dark)}.contentarea tbody tr:nth-child(2n){background-color:var(--col-prim)}.contentarea th,.contentarea td{padding:.5em 1em}.contentarea thead{background-color:var(--col-sec-light);color:var(--col-sec-text-light);text-align:left;font-family:var(--sans-font)}.contentarea td{vertical-align:top}.contentarea svg{display:block;margin-left:auto;margin-right:auto}.contentarea summary{font-family:var(--cnt-header-font);font-weight:400;color:#888;cursor:pointer}.contentarea summary:focus{outline:none}.contentarea summary:hover{color:var(--cnt-color)}.contentarea details{padding:0 8px;border:#AAA dashed 1px;border-radius:var(--radius);max-height:2em;overflow:auto;transition:max-height 2s}.contentarea details[open]{max-height:95vh}.contentarea .alert{font-family:var(--sans-font);font-weight:600;display:flex;align-items:center;border-radius:var(--radius);padding:1em;background-color:var(--bgColor, #f8d7da);color:var(--textColor, #721c24)}.contentarea .alert:before{content:var(--icon);font-size:24px;margin-right:.5em}.contentarea .alert.error{--bgColor: #f8d7da;--textColor: #721c24;--icon: "\26d4"}.contentarea .alert.warning{--bgColor: #fff3cd;--textColor: #856404;--icon: "\26a0\fe0f"}.contentarea .alert.info{--bgColor: #d1ecf1;--textColor: #0c5460;--icon: "\2139\fe0f"}.contentarea .alert.success{--bgColor: #d4edda;--textColor: #155724;--icon: "\2705"}@media only screen and (max-width: 850px){.contentarea img{float:none;display:block;max-width:90%;margin:1rem auto}}}@layer components{.pagemenu{margin:1rem;color:var(--pm-text-color);font-family:var(--sans-font);font-size:var(--pm-font-size)}.pagemenu h3{font-size:var(--pm-header-font-size);border-bottom:solid calc(var(--pm-font-size) / 8) var(--pm-ruler-color);margin-block:.5rem;padding-inline:0}.pagemenu ul{list-style-type:none;overflow:hidden;margin-block:0;padding-inline:0}.pagemenu ul ul{margin-left:var(--pm-font-size)}.pagemenu li{margin:calc(var(--pm-font-size) * .4) 0}.pagemenu a{font-family:var(--serif-font);display:inline-block;text-decoration:none;color:var(--pm-text-color);width:90%;padding-left:10px}.pagemenu a.highlight{border-left:solid 3px var(--pm-ruler-color);padding-left:7px;font-weight:700}.pagemenu a:active{color:var(--pm-hover-color)}.pagemenu a:hover{text-decoration:underline}}@layer components{.footer{box-sizing:border-box;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;width:100%;color:var(--ftr-color);background-color:var(--ftr-bg-color);font-family:var(--sans-font);font-size:var(--ftr-font-size);padding:var(--ftr-padding)}.footer-button{color:var(--ftr-color);text-decoration:none;padding:calc(var(--ftr-padding) / 2);border:solid 2px var(--ftr-border-color);border-radius:4px;margin:2px}.footer-button.disabled{color:var(--ftr-border-color);cursor:not-allowed}.footer p{margin:0;padding:0}.footer-button p:first-of-type{color:var(--ftr-dark-color);font-weight:400;font-size:calc(var(--ftr-font-size) - 2px)}.footer-text{margin:var(--ftr-padding);text-align:center;color:var(--ftr-dark-color)}.footer-text a{color:var(--ftr-color);text-decoration:none}.footer-text p:last-of-type{font-size:calc(var(--ftr-font-size) - 2px)}.footer a:hover{text-shadow:0 0 1px var(--ftr-text-hover)}@media only screen and (max-width: 850px){.footer{justify-content:space-around}.footer-text{order:1}}}
2 |
--------------------------------------------------------------------------------
/src/actions.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * # Converting Keybindings to Actions
3 | *
4 | * This module defines the schema of the configuration file using TypeScript
5 | * interfaces. We parse the configuration JSON to TypeScript objects which
6 | * directly define all the valid keyboard sequences and the commands that these
7 | * will invoke.
8 | */
9 | //#region -c action.ts imports
10 | import * as vscode from 'vscode'
11 | //#endregion
12 | /**
13 | * ## Action Definitions
14 | *
15 | * The keybinding configuration consist of _actions_ that can take three forms:
16 | * an action can be a command (defined later), a keymap, or a number that refers
17 | * to a keymap defined earlier.
18 | */
19 | export type Action = Command | Keymap | number
20 | /**
21 | * Commands can be invoked in four ways: by specifying just command a name
22 | * (string), or using a conditional command, a command with parameters, or a
23 | * sequence (array) of commands. The definition is recursive, meaning that a
24 | * sequence can contain all four types of commands.
25 | */
26 | export type Command = string | Conditional | Parameterized | Command[]
27 | /**
28 | * A conditional command consist of condition (a JavaScript expression) and set
29 | * of branches to take depending on the result of the condition. Each branch can
30 | * be any type of command defined above.
31 | */
32 | export interface Conditional {
33 | condition: string
34 | [branch: string]: Command
35 | }
36 | /**
37 | * A command that takes arguments can be specified using the `Parameterized`
38 | * interface. Arguments can be given either as an object or a string, which
39 | * is assumed to contain a valid JS expression. Additionally, you can specify
40 | * that the command is run multiple times by setting the `repeat` property. The
41 | * property must be either a number, or a JS expression that evaluates to a
42 | * number. If it evaluates to some other type, the expression is used as a
43 | * condition that is evaluated after the command is run. If the expression
44 | * returns a truthy value, the command is repeated.
45 | */
46 | export interface Parameterized {
47 | command: string
48 | args?: {} | string
49 | repeat?: number | string
50 | }
51 | /**
52 | * A keymap is a dictionary of keys (characters) to actions. Keys are either
53 | * single characters or character ranges, denoted by sequences of `,`
54 | * and `-`. Values of the dictionary can be also nested keymaps.
55 | * This is how you can define commands that require multiple keypresses.
56 | *
57 | * 
58 | * When the value of a key is number, it refers to another keymap whose `id`
59 | * equals the number. The number can also point to the same keymap where it
60 | * resides. With this mechanism, you can define _recursive_ keymaps that can
61 | * take (theoretically) infinitely long key sequences. The picture on the right
62 | * illustrates this.
63 | *
64 | * The `help` field contains help text that is shown in the status bar when the
65 | * keymap is active.
66 | */
67 | export interface Keymap {
68 | id: number
69 | help: string
70 | [key: string]: Action
71 | }
72 | /**
73 | * ## Cursor Shapes
74 | *
75 | * You can use various cursor shapes in different modes. The list of available
76 | * shapes is defined below.
77 | */
78 | type Cursor =
79 | | "block"
80 | | "block-outline"
81 | | "line"
82 | | "line-thin"
83 | | "underline"
84 | | "underline-thin"
85 | | undefined
86 | /**
87 | * ## Configuration State
88 | *
89 | * The variables below contain the current cursor configuration.
90 | */
91 | let insertCursorStyle: vscode.TextEditorCursorStyle
92 | let normalCursorStyle: vscode.TextEditorCursorStyle
93 | let searchCursorStyle: vscode.TextEditorCursorStyle
94 | let selectCursorStyle: vscode.TextEditorCursorStyle
95 | let insertStatusText: string
96 | let normalStatusText: string
97 | let searchStatusText: string
98 | let selectStatusText: string
99 | let insertStatusColor: string | undefined
100 | let normalStatusColor: string | undefined
101 | let searchStatusColor: string | undefined
102 | let selectStatusColor: string | undefined
103 | /**
104 | * Another thing you can set in config, is whether ModalEdit starts in normal
105 | * mode.
106 | */
107 | let startInNormalMode: boolean
108 | /**
109 | * The root of the action configuration is keymap. This defines what key
110 | * sequences will be run when keys are pressed in normal mode.
111 | */
112 | let baseKeymap: Keymap
113 | let selectKeymap: Keymap
114 | /**
115 | * The current active keymap is stored here. The active keymap changes when the
116 | * user invokes a multi-key action sequence.
117 | */
118 | let currentKeymap: Keymap | null = null
119 | /**
120 | * The last command run is also stored. This is needed to run commands which
121 | * capture the keyboard.
122 | */
123 | let lastCommand: string
124 | /**
125 | * The key sequence that user has pressed is stored for error reporting
126 | * purposes and to make it available to command arguments. Since commands
127 | * can invoke other commands through `typeNormalKeys` command, we need to
128 | * maintain the key sequences in a stack. Both current key sequence and the
129 | * stack is initialized to empty array.
130 | */
131 | let keySequence: string[] = []
132 | let keySeqStack: string[][] = []
133 | /**
134 | * We need a dictionary that returns a keymap for given id.
135 | */
136 | let keymapsById: { [id: number]: Keymap }
137 | /**
138 | * ## Configuration Accessors
139 | *
140 | * The following functions return the current configuration settings.
141 | */
142 | export function getInsertStyles():
143 | [vscode.TextEditorCursorStyle, string, string | undefined] {
144 | return [ insertCursorStyle, insertStatusText, insertStatusColor ]
145 | }
146 |
147 | export function getNormalStyles():
148 | [vscode.TextEditorCursorStyle, string, string | undefined ] {
149 | return [ normalCursorStyle, normalStatusText, normalStatusColor ]
150 | }
151 |
152 | export function getSearchStyles():
153 | [vscode.TextEditorCursorStyle, string, string | undefined] {
154 | return [ searchCursorStyle, searchStatusText, searchStatusColor ]
155 | }
156 |
157 | export function getSelectStyles():
158 | [vscode.TextEditorCursorStyle, string, string | undefined] {
159 | return [ selectCursorStyle, selectStatusText, selectStatusColor ]
160 | }
161 |
162 | export function getStartInNormalMode(): boolean {
163 | return startInNormalMode
164 | }
165 | /**
166 | * You can also set the last command from outside the module.
167 | */
168 | export function setLastCommand(command: string) {
169 | lastCommand = command
170 | }
171 | /**
172 | * ## Logging
173 | *
174 | * To enable logging and error reporting ModalEdit creates an output channel
175 | * that is visible in the output pane. The channel is created in the extension
176 | * activation hook, but it is passed to this module using the `setOutputChannel`
177 | * function.
178 | */
179 | let outputChannel: vscode.OutputChannel
180 |
181 | export function setOutputChannel(channel: vscode.OutputChannel) {
182 | outputChannel = channel
183 | }
184 | /**
185 | * Once the channel is set, we can output messages to it using the `log`
186 | * function.
187 | */
188 | export function log(message: string) {
189 | outputChannel.appendLine(message)
190 | }
191 | /**
192 | * ## Updating Configuration from settings.json
193 | *
194 | * Whenever you save the user-level `settings.json` or the one located in the
195 | * `.vsode` directory VS Code calls this function that updates the current
196 | * configuration.
197 | */
198 | export function updateFromConfig(): void {
199 | const config = vscode.workspace.getConfiguration("modaledit")
200 | UpdateKeybindings(config)
201 | insertCursorStyle = toVSCursorStyle(
202 | config.get("insertCursorStyle", "line"))
203 | normalCursorStyle = toVSCursorStyle(
204 | config.get("normalCursorStyle", "block"))
205 | searchCursorStyle = toVSCursorStyle(
206 | config.get("searchCursorStyle", "underline"))
207 | selectCursorStyle = toVSCursorStyle(
208 | config.get("selectCursorStyle", "line-thin"))
209 | insertStatusText = config.get("insertStatusText", "-- $(edit) INSERT --")
210 | normalStatusText = config.get("normalStatusText", "-- $(move) NORMAL --")
211 | searchStatusText = config.get("searchStatusText", "$(search) SEARCH")
212 | selectStatusText = config.get("selectStatusText", "-- $(paintcan) VISUAL --")
213 | insertStatusColor = config.get("insertStatusColor") || undefined
214 | normalStatusColor = config.get("normalStatusColor") || undefined
215 | searchStatusColor = config.get("searchStatusColor") || undefined
216 | selectStatusColor = config.get("selectStatusColor") || undefined
217 | startInNormalMode = config.get("startInNormalMode", true)
218 | }
219 | /**
220 | * The following function updates base keymap and select-mode keymap.
221 | */
222 | function UpdateKeybindings(config: vscode.WorkspaceConfiguration) {
223 | log("Validating keybindings in 'settings.json'...")
224 | keymapsById = {}
225 | errors = 0
226 | let sel = config.get