diff --git a/404.html b/404.html new file mode 100644 index 000000000..3a1ef021a --- /dev/null +++ b/404.html @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + 404 Page not found | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + +
+ +
+
+
+

Page not found :(

+

The page you are looking for doesn't exist or has been moved.

+

Try using the search, or go home.

+
+
+ + + diff --git a/CNAME b/CNAME new file mode 100644 index 000000000..d55d57f1f --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +builddocs.nosqlbench.io diff --git a/Discord-Logo-Color.png b/Discord-Logo-Color.png new file mode 100644 index 000000000..e2964bb6b Binary files /dev/null and b/Discord-Logo-Color.png differ diff --git a/Discord-Logo-Wordmark-Color.png b/Discord-Logo-Wordmark-Color.png new file mode 100644 index 000000000..aa1b5e2e0 Binary files /dev/null and b/Discord-Logo-Wordmark-Color.png differ diff --git a/GitHub-Mark-120px-plus.png b/GitHub-Mark-120px-plus.png new file mode 100644 index 000000000..ea6ff545a Binary files /dev/null and b/GitHub-Mark-120px-plus.png differ diff --git a/GitHub-Mark-32px.png b/GitHub-Mark-32px.png new file mode 100644 index 000000000..8b25551a9 Binary files /dev/null and b/GitHub-Mark-32px.png differ diff --git a/GitHub-Mark-64px.png b/GitHub-Mark-64px.png new file mode 100644 index 000000000..182a1a3f7 Binary files /dev/null and b/GitHub-Mark-64px.png differ diff --git a/GitHub-Mark-Light-120px-plus.png b/GitHub-Mark-Light-120px-plus.png new file mode 100644 index 000000000..192846a12 Binary files /dev/null and b/GitHub-Mark-Light-120px-plus.png differ diff --git a/GitHub-Mark-Light-32px.png b/GitHub-Mark-Light-32px.png new file mode 100644 index 000000000..628da97c7 Binary files /dev/null and b/GitHub-Mark-Light-32px.png differ diff --git a/GitHub-Mark-Light-64px.png b/GitHub-Mark-Light-64px.png new file mode 100644 index 000000000..73db1f61f Binary files /dev/null and b/GitHub-Mark-Light-64px.png differ diff --git a/abridge-blue-dark.css b/abridge-blue-dark.css new file mode 100644 index 000000000..90c9b871b --- /dev/null +++ b/abridge-blue-dark.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}.z-code{color:#bfbab0;background-color:#191919}.z-comment,.z-punctuation.z-definition.z-comment{color:#87929f;font-style:italic}.z-variable{color:#bfbab0}.z-string,.z-constant.z-other.z-symbol{color:#c2d94c}.z-constant.z-numeric{color:#f29718}.z-string.z-regexp,.z-constant.z-character.z-escape{color:#95e6cb}.z-constant.z-language{color:#f29718}.z-constant.z-character,.z-constant.z-other{color:#f29718}.z-variable.z-member{color:#fe7d83}.z-keyword,.z-keyword.z-operator.z-word{color:#0bf}.z-keyword.z-operator{color:#f29668}.z-punctuation.z-separator,.z-punctuation.z-terminator{color:#bfbab0}.z-punctuation.z-section{color:#bfbab0}.z-punctuation.z-accessor{color:#f29668}.z-punctuation.z-definition.z-annotation{color:#bfbab0}.z-variable.z-other.z-dollar.z-only.z-js,.z-variable.z-other.z-object.z-dollar.z-only.z-js,.z-variable.z-type.z-dollar.z-only.z-js,.z-support.z-class.z-dollar.z-only.z-js{color:#e6b673}.z-storage{color:#0bf}.z-storage.z-type{color:#0bf}.z-entity.z-name.z-function{color:#ffb454}.z-entity.z-name,.z-entity.z-name.z-tag,.z-entity.z-name.z-label{color:#59c2ff}.z-entity.z-other.z-inherited-class{color:#59c2ff;text-decoration:underline}.z-variable.z-parameter{color:#f29718}.z-variable.z-language{color:#39bae6;font-style:italic}.z-entity.z-name.z-tag,.z-meta.z-tag.z-sgml{color:#39bae6}.z-punctuation.z-definition.z-tag.z-end,.z-punctuation.z-definition.z-tag.z-begin,.z-punctuation.z-definition.z-tag{color:#39bae6}.z-entity.z-other.z-attribute-name{color:#ffb454}.z-variable.z-function,.z-variable.z-annotation{color:#ffb454}.z-support.z-function,.z-support.z-macro{color:#fe7d83}.z-support.z-constant{color:#f29668;font-style:italic}.z-support.z-type,.z-support.z-class{color:#39bae6;font-style:italic}.z-invalid{color:#ff7c6d}.z-invalid.z-deprecated{color:#fff;background-color:#0bf}.z-meta.z-diff,.z-meta.z-diff.z-header{color:#c594c5}.z-source.z-ruby .z-variable.z-other.z-readwrite{color:#ffb454}.z-source.z-css .z-entity.z-name.z-tag,.z-source.z-sass .z-entity.z-name.z-tag,.z-source.z-scss .z-entity.z-name.z-tag,.z-source.z-less .z-entity.z-name.z-tag,.z-source.z-stylus .z-entity.z-name.z-tag{color:#59c2ff}.z-source.z-css .z-support.z-type,.z-source.z-sass .z-support.z-type,.z-source.z-scss .z-support.z-type,.z-source.z-less .z-support.z-type,.z-source.z-stylus .z-support.z-type{color:#798491}.z-support.z-type.z-property-name{color:#39bae6}.z-constant.z-numeric.z-line-number.z-find-in-files{color:#798491}.z-constant.z-numeric.z-line-number.z-match{color:#0bf}.z-entity.z-name.z-filename.z-find-in-files{color:#c2d94c}.z-message.z-error{color:#ff7c6d}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-markup.z-heading{color:#0bf;font-weight:bold}.z-string.z-other.z-link,.z-markup.z-underline.z-link{color:#95e6cb;text-decoration:underline;font-style:italic}.z-punctuation.z-definition.z-image{color:#ffb454}.z-markup.z-italic{color:#fe7d83;font-style:italic}.z-markup.z-bold{color:#fe7d83;font-weight:bold}.z-markup.z-italic .z-markup.z-bold,.z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}.z-markup.z-raw{background-color:#bfbab0}.z-markup.z-raw.z-inline{background-color:#bfbab0}.z-meta.z-separator{color:#798491;background-color:#bfbab0;font-weight:bold}.z-markup.z-quote{color:#f29718;font-style:italic}.z-markup.z-list.z-numbered.z-bullet,.z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#95e6cb}.z-markup.z-inserted{color:#c2d94c}.z-markup.z-changed{color:#39bae6}.z-markup.z-deleted{color:#fe7d83}.z-markup.z-strike{color:#e6b673}.z-markup.z-table{color:#39bae6;background-color:#bfbab0}.z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#f29668}.z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#798491}.z-markup.z-raw.z-block.z-fenced.z-markdown{color:#bfbab0;background-color:#bfbab0}.z-punctuation.z-definition.z-fenced.z-markdown,.z-variable.z-language.z-fenced.z-markdown{color:#798491;background-color:#bfbab0}.z-variable.z-language.z-fenced.z-markdown{color:#798491}.z-markup.z-inserted.z-git_gutter{color:#c2d94c}.z-markup.z-changed.z-git_gutter{color:#39bae6}.z-markup.z-deleted.z-git_gutter{color:#ff7c6d}.z-markup.z-ignored.z-git_gutter{color:#20272c}.z-markup.z-untracked.z-git_gutter{color:#20272c}.z-gutter_color{color:#fff}.z-acejump.z-label.z-blue{color:#fff;background-color:#39bae6}.z-acejump.z-label.z-green{color:#fff;background-color:#c2d94c}.z-acejump.z-label.z-orange{color:#fff;background-color:#0bf}.z-acejump.z-label.z-purple{color:#fff;background-color:#fe7d83}.z-sublimelinter.z-mark.z-warning{color:#39bae6}.z-sublimelinter.z-gutter-mark{color:#fff}.z-sublimelinter.z-mark.z-error{color:#ff7c6d}:root{--f1: #ccc;--f2: #ddd;--c1: #111;--c2: #222;--c3: #333;--c4: #888;--a1: #09f;--a2: #0bf;--a3: #0af;--cg: #593;--cr: #e33} \ No newline at end of file diff --git a/abridge-blue-light.css b/abridge-blue-light.css new file mode 100644 index 000000000..98afa8590 --- /dev/null +++ b/abridge-blue-light.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}.z-code{color:#50565a;background-color:#fafafa}.z-comment,.z-punctuation.z-definition.z-comment{color:#676c72;font-style:italic}.z-variable{color:#50565a}.z-string,.z-constant.z-other.z-symbol{color:#497700}.z-constant.z-numeric{color:#b04e00}.z-string.z-regexp,.z-constant.z-character.z-escape{color:#007b59}.z-constant.z-language{color:#b04e00}.z-constant.z-character,.z-constant.z-other{color:#b04e00}.z-variable.z-member{color:#c33947}.z-keyword,.z-keyword.z-operator.z-word{color:#0062e8}.z-keyword.z-operator{color:#a4552c}.z-punctuation.z-separator,.z-punctuation.z-terminator{color:#50565a}.z-punctuation.z-section{color:#50565a}.z-punctuation.z-accessor{color:#a4552c}.z-punctuation.z-definition.z-annotation{color:#50565a}.z-variable.z-other.z-dollar.z-only.z-js,.z-variable.z-other.z-object.z-dollar.z-only.z-js,.z-variable.z-type.z-dollar.z-only.z-js,.z-support.z-class.z-dollar.z-only.z-js{color:#8b6426}.z-storage{color:#0062e8}.z-storage.z-type{color:#0062e8}.z-entity.z-name.z-function{color:#a45600}.z-entity.z-name,.z-entity.z-name.z-tag,.z-entity.z-name.z-label{color:#0070b3}.z-entity.z-other.z-inherited-class{color:#0070b3;text-decoration:underline}.z-variable.z-parameter{color:#b04e00}.z-variable.z-language{color:#007492;font-style:italic}.z-entity.z-name.z-tag,.z-meta.z-tag.z-sgml{color:#007492}.z-punctuation.z-definition.z-tag.z-end,.z-punctuation.z-definition.z-tag.z-begin,.z-punctuation.z-definition.z-tag{color:#007492}.z-entity.z-other.z-attribute-name{color:#a45600}.z-variable.z-function,.z-variable.z-annotation{color:#a45600}.z-support.z-function,.z-support.z-macro{color:#b94046}.z-support.z-constant{color:#a4552c;font-style:italic}.z-support.z-type,.z-support.z-class{color:#007492;font-style:italic}.z-invalid{color:#da0001}.z-invalid.z-deprecated{color:#fff;background-color:#0062e8}.z-source.z-ruby .z-variable.z-other.z-readwrite{color:#a45600}.z-source.z-css .z-entity.z-name.z-tag,.z-source.z-sass .z-entity.z-name.z-tag,.z-source.z-scss .z-entity.z-name.z-tag,.z-source.z-less .z-entity.z-name.z-tag,.z-source.z-stylus .z-entity.z-name.z-tag{color:#0070b3}.z-source.z-css .z-support.z-type,.z-source.z-sass .z-support.z-type,.z-source.z-scss .z-support.z-type,.z-source.z-less .z-support.z-type,.z-source.z-stylus .z-support.z-type{color:#676c72}.z-support.z-type.z-property-name{color:#007492}.z-constant.z-numeric.z-line-number.z-find-in-files{color:#676c72}.z-constant.z-numeric.z-line-number.z-match{color:#0062e8}.z-entity.z-name.z-filename.z-find-in-files{color:#497700}.z-message.z-error{color:#da0001}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-markup.z-heading{color:#0062e8;font-weight:bold}.z-string.z-other.z-link,.z-markup.z-underline.z-link{color:#007b59;text-decoration:underline;font-style:italic}.z-punctuation.z-definition.z-image{color:#a45600}.z-markup.z-italic{color:#b94046;font-style:italic}.z-markup.z-bold{color:#b94046;font-weight:bold}.z-markup.z-italic .z-markup.z-bold,.z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}.z-markup.z-raw{background-color:#50565a}.z-markup.z-raw.z-inline{background-color:#50565a}.z-meta.z-separator{color:#676c72;background-color:#50565a;font-weight:bold}.z-markup.z-quote{color:#b04e00;font-style:italic}.z-markup.z-list.z-numbered.z-bullet,.z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#007b59}.z-markup.z-inserted{color:#497700}.z-markup.z-changed{color:#007492}.z-markup.z-deleted{color:#b94046}.z-markup.z-strike{color:#8b6426}.z-markup.z-table{color:#007492;background-color:#50565a}.z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#a4552c}.z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#676c72}.z-markup.z-raw.z-block.z-fenced.z-markdown{color:#50565a;background-color:#50565a}.z-punctuation.z-definition.z-fenced.z-markdown,.z-variable.z-language.z-fenced.z-markdown{color:#676c72;background-color:#50565a}.z-variable.z-language.z-fenced.z-markdown{color:#676c72}.z-markup.z-inserted.z-git_gutter{color:#497700}.z-markup.z-changed.z-git_gutter{color:#007492}.z-markup.z-deleted.z-git_gutter{color:#da0001}.z-markup.z-ignored.z-git_gutter{color:#696b6c}.z-markup.z-untracked.z-git_gutter{color:#696b6c}.z-gutter_color{color:#fff}.z-acejump.z-label.z-blue{color:#fff;background-color:#007492}.z-acejump.z-label.z-green{color:#fff;background-color:#497700}.z-acejump.z-label.z-orange{color:#fff;background-color:#0062e8}.z-acejump.z-label.z-purple{color:#fff;background-color:#b94046}.z-sublimelinter.z-mark.z-warning{color:#007492}.z-sublimelinter.z-gutter-mark{color:#fff}.z-sublimelinter.z-mark.z-error{color:#da0001}:root{--f1: #444;--f2: #333;--c1: #fff;--c2: #eee;--c3: #ddd;--c4: #677;--a1: #06e;--a2: #09f;--a3: #07f;--cg: #373;--cr: #d33} \ No newline at end of file diff --git a/abridge-blue-switcher.css b/abridge-blue-switcher.css new file mode 100644 index 000000000..2c7a8a0fe --- /dev/null +++ b/abridge-blue-switcher.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}:root:not(.light) .z-code{color:#bfbab0;background-color:#191919}:root:not(.light) .z-comment,:root:not(.light) .z-punctuation.z-definition.z-comment{color:#87929f;font-style:italic}:root:not(.light) .z-variable{color:#bfbab0}:root:not(.light) .z-string,:root:not(.light) .z-constant.z-other.z-symbol{color:#c2d94c}:root:not(.light) .z-constant.z-numeric{color:#f29718}:root:not(.light) .z-string.z-regexp,:root:not(.light) .z-constant.z-character.z-escape{color:#95e6cb}:root:not(.light) .z-constant.z-language{color:#f29718}:root:not(.light) .z-constant.z-character,:root:not(.light) .z-constant.z-other{color:#f29718}:root:not(.light) .z-variable.z-member{color:#fe7d83}:root:not(.light) .z-keyword,:root:not(.light) .z-keyword.z-operator.z-word{color:#0bf}:root:not(.light) .z-keyword.z-operator{color:#f29668}:root:not(.light) .z-punctuation.z-separator,:root:not(.light) .z-punctuation.z-terminator{color:#bfbab0}:root:not(.light) .z-punctuation.z-section{color:#bfbab0}:root:not(.light) .z-punctuation.z-accessor{color:#f29668}:root:not(.light) .z-punctuation.z-definition.z-annotation{color:#bfbab0}:root:not(.light) .z-variable.z-other.z-dollar.z-only.z-js,:root:not(.light) .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root:not(.light) .z-variable.z-type.z-dollar.z-only.z-js,:root:not(.light) .z-support.z-class.z-dollar.z-only.z-js{color:#e6b673}:root:not(.light) .z-storage{color:#0bf}:root:not(.light) .z-storage.z-type{color:#0bf}:root:not(.light) .z-entity.z-name.z-function{color:#ffb454}:root:not(.light) .z-entity.z-name,:root:not(.light) .z-entity.z-name.z-tag,:root:not(.light) .z-entity.z-name.z-label{color:#59c2ff}:root:not(.light) .z-entity.z-other.z-inherited-class{color:#59c2ff;text-decoration:underline}:root:not(.light) .z-variable.z-parameter{color:#f29718}:root:not(.light) .z-variable.z-language{color:#39bae6;font-style:italic}:root:not(.light) .z-entity.z-name.z-tag,:root:not(.light) .z-meta.z-tag.z-sgml{color:#39bae6}:root:not(.light) .z-punctuation.z-definition.z-tag.z-end,:root:not(.light) .z-punctuation.z-definition.z-tag.z-begin,:root:not(.light) .z-punctuation.z-definition.z-tag{color:#39bae6}:root:not(.light) .z-entity.z-other.z-attribute-name{color:#ffb454}:root:not(.light) .z-variable.z-function,:root:not(.light) .z-variable.z-annotation{color:#ffb454}:root:not(.light) .z-support.z-function,:root:not(.light) .z-support.z-macro{color:#fe7d83}:root:not(.light) .z-support.z-constant{color:#f29668;font-style:italic}:root:not(.light) .z-support.z-type,:root:not(.light) .z-support.z-class{color:#39bae6;font-style:italic}:root:not(.light) .z-invalid{color:#ff7c6d}:root:not(.light) .z-invalid.z-deprecated{color:#fff;background-color:#0bf}:root:not(.light) .z-meta.z-diff,:root:not(.light) .z-meta.z-diff.z-header{color:#c594c5}:root:not(.light) .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#ffb454}:root:not(.light) .z-source.z-css .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-sass .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-scss .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-less .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-stylus .z-entity.z-name.z-tag{color:#59c2ff}:root:not(.light) .z-source.z-css .z-support.z-type,:root:not(.light) .z-source.z-sass .z-support.z-type,:root:not(.light) .z-source.z-scss .z-support.z-type,:root:not(.light) .z-source.z-less .z-support.z-type,:root:not(.light) .z-source.z-stylus .z-support.z-type{color:#798491}:root:not(.light) .z-support.z-type.z-property-name{color:#39bae6}:root:not(.light) .z-constant.z-numeric.z-line-number.z-find-in-files{color:#798491}:root:not(.light) .z-constant.z-numeric.z-line-number.z-match{color:#0bf}:root:not(.light) .z-entity.z-name.z-filename.z-find-in-files{color:#c2d94c}:root:not(.light) .z-message.z-error{color:#ff7c6d}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-markup.z-heading{color:#0bf;font-weight:bold}:root:not(.light) .z-string.z-other.z-link,:root:not(.light) .z-markup.z-underline.z-link{color:#95e6cb;text-decoration:underline;font-style:italic}:root:not(.light) .z-punctuation.z-definition.z-image{color:#ffb454}:root:not(.light) .z-markup.z-italic{color:#fe7d83;font-style:italic}:root:not(.light) .z-markup.z-bold{color:#fe7d83;font-weight:bold}:root:not(.light) .z-markup.z-italic .z-markup.z-bold,:root:not(.light) .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root:not(.light) .z-markup.z-raw{background-color:#bfbab0}:root:not(.light) .z-markup.z-raw.z-inline{background-color:#bfbab0}:root:not(.light) .z-meta.z-separator{color:#798491;background-color:#bfbab0;font-weight:bold}:root:not(.light) .z-markup.z-quote{color:#f29718;font-style:italic}:root:not(.light) .z-markup.z-list.z-numbered.z-bullet,:root:not(.light) .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#95e6cb}:root:not(.light) .z-markup.z-inserted{color:#c2d94c}:root:not(.light) .z-markup.z-changed{color:#39bae6}:root:not(.light) .z-markup.z-deleted{color:#fe7d83}:root:not(.light) .z-markup.z-strike{color:#e6b673}:root:not(.light) .z-markup.z-table{color:#39bae6;background-color:#bfbab0}:root:not(.light) .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#f29668}:root:not(.light) .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#798491}:root:not(.light) .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#bfbab0;background-color:#bfbab0}:root:not(.light) .z-punctuation.z-definition.z-fenced.z-markdown,:root:not(.light) .z-variable.z-language.z-fenced.z-markdown{color:#798491;background-color:#bfbab0}:root:not(.light) .z-variable.z-language.z-fenced.z-markdown{color:#798491}:root:not(.light) .z-markup.z-inserted.z-git_gutter{color:#c2d94c}:root:not(.light) .z-markup.z-changed.z-git_gutter{color:#39bae6}:root:not(.light) .z-markup.z-deleted.z-git_gutter{color:#ff7c6d}:root:not(.light) .z-markup.z-ignored.z-git_gutter{color:#20272c}:root:not(.light) .z-markup.z-untracked.z-git_gutter{color:#20272c}:root:not(.light) .z-gutter_color{color:#fff}:root:not(.light) .z-acejump.z-label.z-blue{color:#fff;background-color:#39bae6}:root:not(.light) .z-acejump.z-label.z-green{color:#fff;background-color:#c2d94c}:root:not(.light) .z-acejump.z-label.z-orange{color:#fff;background-color:#0bf}:root:not(.light) .z-acejump.z-label.z-purple{color:#fff;background-color:#fe7d83}:root:not(.light) .z-sublimelinter.z-mark.z-warning{color:#39bae6}:root:not(.light) .z-sublimelinter.z-gutter-mark{color:#fff}:root:not(.light) .z-sublimelinter.z-mark.z-error{color:#ff7c6d}:root.light .z-code{color:#50565a;background-color:#fafafa}:root.light .z-comment,:root.light .z-punctuation.z-definition.z-comment{color:#676c72;font-style:italic}:root.light .z-variable{color:#50565a}:root.light .z-string,:root.light .z-constant.z-other.z-symbol{color:#497700}:root.light .z-constant.z-numeric{color:#b04e00}:root.light .z-string.z-regexp,:root.light .z-constant.z-character.z-escape{color:#007b59}:root.light .z-constant.z-language{color:#b04e00}:root.light .z-constant.z-character,:root.light .z-constant.z-other{color:#b04e00}:root.light .z-variable.z-member{color:#c33947}:root.light .z-keyword,:root.light .z-keyword.z-operator.z-word{color:#0062e8}:root.light .z-keyword.z-operator{color:#a4552c}:root.light .z-punctuation.z-separator,:root.light .z-punctuation.z-terminator{color:#50565a}:root.light .z-punctuation.z-section{color:#50565a}:root.light .z-punctuation.z-accessor{color:#a4552c}:root.light .z-punctuation.z-definition.z-annotation{color:#50565a}:root.light .z-variable.z-other.z-dollar.z-only.z-js,:root.light .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root.light .z-variable.z-type.z-dollar.z-only.z-js,:root.light .z-support.z-class.z-dollar.z-only.z-js{color:#8b6426}:root.light .z-storage{color:#0062e8}:root.light .z-storage.z-type{color:#0062e8}:root.light .z-entity.z-name.z-function{color:#a45600}:root.light .z-entity.z-name,:root.light .z-entity.z-name.z-tag,:root.light .z-entity.z-name.z-label{color:#0070b3}:root.light .z-entity.z-other.z-inherited-class{color:#0070b3;text-decoration:underline}:root.light .z-variable.z-parameter{color:#b04e00}:root.light .z-variable.z-language{color:#007492;font-style:italic}:root.light .z-entity.z-name.z-tag,:root.light .z-meta.z-tag.z-sgml{color:#007492}:root.light .z-punctuation.z-definition.z-tag.z-end,:root.light .z-punctuation.z-definition.z-tag.z-begin,:root.light .z-punctuation.z-definition.z-tag{color:#007492}:root.light .z-entity.z-other.z-attribute-name{color:#a45600}:root.light .z-variable.z-function,:root.light .z-variable.z-annotation{color:#a45600}:root.light .z-support.z-function,:root.light .z-support.z-macro{color:#b94046}:root.light .z-support.z-constant{color:#a4552c;font-style:italic}:root.light .z-support.z-type,:root.light .z-support.z-class{color:#007492;font-style:italic}:root.light .z-invalid{color:#da0001}:root.light .z-invalid.z-deprecated{color:#fff;background-color:#0062e8}:root.light .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#a45600}:root.light .z-source.z-css .z-entity.z-name.z-tag,:root.light .z-source.z-sass .z-entity.z-name.z-tag,:root.light .z-source.z-scss .z-entity.z-name.z-tag,:root.light .z-source.z-less .z-entity.z-name.z-tag,:root.light .z-source.z-stylus .z-entity.z-name.z-tag{color:#0070b3}:root.light .z-source.z-css .z-support.z-type,:root.light .z-source.z-sass .z-support.z-type,:root.light .z-source.z-scss .z-support.z-type,:root.light .z-source.z-less .z-support.z-type,:root.light .z-source.z-stylus .z-support.z-type{color:#676c72}:root.light .z-support.z-type.z-property-name{color:#007492}:root.light .z-constant.z-numeric.z-line-number.z-find-in-files{color:#676c72}:root.light .z-constant.z-numeric.z-line-number.z-match{color:#0062e8}:root.light .z-entity.z-name.z-filename.z-find-in-files{color:#497700}:root.light .z-message.z-error{color:#da0001}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-markup.z-heading{color:#0062e8;font-weight:bold}:root.light .z-string.z-other.z-link,:root.light .z-markup.z-underline.z-link{color:#007b59;text-decoration:underline;font-style:italic}:root.light .z-punctuation.z-definition.z-image{color:#a45600}:root.light .z-markup.z-italic{color:#b94046;font-style:italic}:root.light .z-markup.z-bold{color:#b94046;font-weight:bold}:root.light .z-markup.z-italic .z-markup.z-bold,:root.light .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root.light .z-markup.z-raw{background-color:#50565a}:root.light .z-markup.z-raw.z-inline{background-color:#50565a}:root.light .z-meta.z-separator{color:#676c72;background-color:#50565a;font-weight:bold}:root.light .z-markup.z-quote{color:#b04e00;font-style:italic}:root.light .z-markup.z-list.z-numbered.z-bullet,:root.light .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#007b59}:root.light .z-markup.z-inserted{color:#497700}:root.light .z-markup.z-changed{color:#007492}:root.light .z-markup.z-deleted{color:#b94046}:root.light .z-markup.z-strike{color:#8b6426}:root.light .z-markup.z-table{color:#007492;background-color:#50565a}:root.light .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#a4552c}:root.light .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#676c72}:root.light .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#50565a;background-color:#50565a}:root.light .z-punctuation.z-definition.z-fenced.z-markdown,:root.light .z-variable.z-language.z-fenced.z-markdown{color:#676c72;background-color:#50565a}:root.light .z-variable.z-language.z-fenced.z-markdown{color:#676c72}:root.light .z-markup.z-inserted.z-git_gutter{color:#497700}:root.light .z-markup.z-changed.z-git_gutter{color:#007492}:root.light .z-markup.z-deleted.z-git_gutter{color:#da0001}:root.light .z-markup.z-ignored.z-git_gutter{color:#696b6c}:root.light .z-markup.z-untracked.z-git_gutter{color:#696b6c}:root.light .z-gutter_color{color:#fff}:root.light .z-acejump.z-label.z-blue{color:#fff;background-color:#007492}:root.light .z-acejump.z-label.z-green{color:#fff;background-color:#497700}:root.light .z-acejump.z-label.z-orange{color:#fff;background-color:#0062e8}:root.light .z-acejump.z-label.z-purple{color:#fff;background-color:#b94046}:root.light .z-sublimelinter.z-mark.z-warning{color:#007492}:root.light .z-sublimelinter.z-gutter-mark{color:#fff}:root.light .z-sublimelinter.z-mark.z-error{color:#da0001}:root:not(.light){--f1: #ccc;--f2: #ddd;--c1: #111;--c2: #222;--c3: #333;--c4: #888;--a1: #09f;--a2: #0bf;--a3: #0af;--cg: #593;--cr: #e33}:root.light{--f1: #444;--f2: #333;--c1: #fff;--c2: #eee;--c3: #ddd;--c4: #677;--a1: #06e;--a2: #09f;--a3: #07f;--cg: #373;--cr: #d33} \ No newline at end of file diff --git a/abridge-blue.css b/abridge-blue.css new file mode 100644 index 000000000..f972227c3 --- /dev/null +++ b/abridge-blue.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}:root .z-code{color:#bfbab0;background-color:#191919}:root .z-comment,:root .z-punctuation.z-definition.z-comment{color:#87929f;font-style:italic}:root .z-variable{color:#bfbab0}:root .z-string,:root .z-constant.z-other.z-symbol{color:#c2d94c}:root .z-constant.z-numeric{color:#f29718}:root .z-string.z-regexp,:root .z-constant.z-character.z-escape{color:#95e6cb}:root .z-constant.z-language{color:#f29718}:root .z-constant.z-character,:root .z-constant.z-other{color:#f29718}:root .z-variable.z-member{color:#fe7d83}:root .z-keyword,:root .z-keyword.z-operator.z-word{color:#0bf}:root .z-keyword.z-operator{color:#f29668}:root .z-punctuation.z-separator,:root .z-punctuation.z-terminator{color:#bfbab0}:root .z-punctuation.z-section{color:#bfbab0}:root .z-punctuation.z-accessor{color:#f29668}:root .z-punctuation.z-definition.z-annotation{color:#bfbab0}:root .z-variable.z-other.z-dollar.z-only.z-js,:root .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root .z-variable.z-type.z-dollar.z-only.z-js,:root .z-support.z-class.z-dollar.z-only.z-js{color:#e6b673}:root .z-storage{color:#0bf}:root .z-storage.z-type{color:#0bf}:root .z-entity.z-name.z-function{color:#ffb454}:root .z-entity.z-name,:root .z-entity.z-name.z-tag,:root .z-entity.z-name.z-label{color:#59c2ff}:root .z-entity.z-other.z-inherited-class{color:#59c2ff;text-decoration:underline}:root .z-variable.z-parameter{color:#f29718}:root .z-variable.z-language{color:#39bae6;font-style:italic}:root .z-entity.z-name.z-tag,:root .z-meta.z-tag.z-sgml{color:#39bae6}:root .z-punctuation.z-definition.z-tag.z-end,:root .z-punctuation.z-definition.z-tag.z-begin,:root .z-punctuation.z-definition.z-tag{color:#39bae6}:root .z-entity.z-other.z-attribute-name{color:#ffb454}:root .z-variable.z-function,:root .z-variable.z-annotation{color:#ffb454}:root .z-support.z-function,:root .z-support.z-macro{color:#fe7d83}:root .z-support.z-constant{color:#f29668;font-style:italic}:root .z-support.z-type,:root .z-support.z-class{color:#39bae6;font-style:italic}:root .z-invalid{color:#ff7c6d}:root .z-invalid.z-deprecated{color:#fff;background-color:#0bf}:root .z-meta.z-diff,:root .z-meta.z-diff.z-header{color:#c594c5}:root .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#ffb454}:root .z-source.z-css .z-entity.z-name.z-tag,:root .z-source.z-sass .z-entity.z-name.z-tag,:root .z-source.z-scss .z-entity.z-name.z-tag,:root .z-source.z-less .z-entity.z-name.z-tag,:root .z-source.z-stylus .z-entity.z-name.z-tag{color:#59c2ff}:root .z-source.z-css .z-support.z-type,:root .z-source.z-sass .z-support.z-type,:root .z-source.z-scss .z-support.z-type,:root .z-source.z-less .z-support.z-type,:root .z-source.z-stylus .z-support.z-type{color:#798491}:root .z-support.z-type.z-property-name{color:#39bae6}:root .z-constant.z-numeric.z-line-number.z-find-in-files{color:#798491}:root .z-constant.z-numeric.z-line-number.z-match{color:#0bf}:root .z-entity.z-name.z-filename.z-find-in-files{color:#c2d94c}:root .z-message.z-error{color:#ff7c6d}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-markup.z-heading{color:#0bf;font-weight:bold}:root .z-string.z-other.z-link,:root .z-markup.z-underline.z-link{color:#95e6cb;text-decoration:underline;font-style:italic}:root .z-punctuation.z-definition.z-image{color:#ffb454}:root .z-markup.z-italic{color:#fe7d83;font-style:italic}:root .z-markup.z-bold{color:#fe7d83;font-weight:bold}:root .z-markup.z-italic .z-markup.z-bold,:root .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root .z-markup.z-raw{background-color:#bfbab0}:root .z-markup.z-raw.z-inline{background-color:#bfbab0}:root .z-meta.z-separator{color:#798491;background-color:#bfbab0;font-weight:bold}:root .z-markup.z-quote{color:#f29718;font-style:italic}:root .z-markup.z-list.z-numbered.z-bullet,:root .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#95e6cb}:root .z-markup.z-inserted{color:#c2d94c}:root .z-markup.z-changed{color:#39bae6}:root .z-markup.z-deleted{color:#fe7d83}:root .z-markup.z-strike{color:#e6b673}:root .z-markup.z-table{color:#39bae6;background-color:#bfbab0}:root .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#f29668}:root .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#798491}:root .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#bfbab0;background-color:#bfbab0}:root .z-punctuation.z-definition.z-fenced.z-markdown,:root .z-variable.z-language.z-fenced.z-markdown{color:#798491;background-color:#bfbab0}:root .z-variable.z-language.z-fenced.z-markdown{color:#798491}:root .z-markup.z-inserted.z-git_gutter{color:#c2d94c}:root .z-markup.z-changed.z-git_gutter{color:#39bae6}:root .z-markup.z-deleted.z-git_gutter{color:#ff7c6d}:root .z-markup.z-ignored.z-git_gutter{color:#20272c}:root .z-markup.z-untracked.z-git_gutter{color:#20272c}:root .z-gutter_color{color:#fff}:root .z-acejump.z-label.z-blue{color:#fff;background-color:#39bae6}:root .z-acejump.z-label.z-green{color:#fff;background-color:#c2d94c}:root .z-acejump.z-label.z-orange{color:#fff;background-color:#0bf}:root .z-acejump.z-label.z-purple{color:#fff;background-color:#fe7d83}:root .z-sublimelinter.z-mark.z-warning{color:#39bae6}:root .z-sublimelinter.z-gutter-mark{color:#fff}:root .z-sublimelinter.z-mark.z-error{color:#ff7c6d}@media (prefers-color-scheme: light){:root .z-code{color:#50565a;background-color:#fafafa}:root .z-comment,:root .z-punctuation.z-definition.z-comment{color:#676c72;font-style:italic}:root .z-variable{color:#50565a}:root .z-string,:root .z-constant.z-other.z-symbol{color:#497700}:root .z-constant.z-numeric{color:#b04e00}:root .z-string.z-regexp,:root .z-constant.z-character.z-escape{color:#007b59}:root .z-constant.z-language{color:#b04e00}:root .z-constant.z-character,:root .z-constant.z-other{color:#b04e00}:root .z-variable.z-member{color:#c33947}:root .z-keyword,:root .z-keyword.z-operator.z-word{color:#0062e8}:root .z-keyword.z-operator{color:#a4552c}:root .z-punctuation.z-separator,:root .z-punctuation.z-terminator{color:#50565a}:root .z-punctuation.z-section{color:#50565a}:root .z-punctuation.z-accessor{color:#a4552c}:root .z-punctuation.z-definition.z-annotation{color:#50565a}:root .z-variable.z-other.z-dollar.z-only.z-js,:root .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root .z-variable.z-type.z-dollar.z-only.z-js,:root .z-support.z-class.z-dollar.z-only.z-js{color:#8b6426}:root .z-storage{color:#0062e8}:root .z-storage.z-type{color:#0062e8}:root .z-entity.z-name.z-function{color:#a45600}:root .z-entity.z-name,:root .z-entity.z-name.z-tag,:root .z-entity.z-name.z-label{color:#0070b3}:root .z-entity.z-other.z-inherited-class{color:#0070b3;text-decoration:underline}:root .z-variable.z-parameter{color:#b04e00}:root .z-variable.z-language{color:#007492;font-style:italic}:root .z-entity.z-name.z-tag,:root .z-meta.z-tag.z-sgml{color:#007492}:root .z-punctuation.z-definition.z-tag.z-end,:root .z-punctuation.z-definition.z-tag.z-begin,:root .z-punctuation.z-definition.z-tag{color:#007492}:root .z-entity.z-other.z-attribute-name{color:#a45600}:root .z-variable.z-function,:root .z-variable.z-annotation{color:#a45600}:root .z-support.z-function,:root .z-support.z-macro{color:#b94046}:root .z-support.z-constant{color:#a4552c;font-style:italic}:root .z-support.z-type,:root .z-support.z-class{color:#007492;font-style:italic}:root .z-invalid{color:#da0001}:root .z-invalid.z-deprecated{color:#fff;background-color:#0062e8}:root .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#a45600}:root .z-source.z-css .z-entity.z-name.z-tag,:root .z-source.z-sass .z-entity.z-name.z-tag,:root .z-source.z-scss .z-entity.z-name.z-tag,:root .z-source.z-less .z-entity.z-name.z-tag,:root .z-source.z-stylus .z-entity.z-name.z-tag{color:#0070b3}:root .z-source.z-css .z-support.z-type,:root .z-source.z-sass .z-support.z-type,:root .z-source.z-scss .z-support.z-type,:root .z-source.z-less .z-support.z-type,:root .z-source.z-stylus .z-support.z-type{color:#676c72}:root .z-support.z-type.z-property-name{color:#007492}:root .z-constant.z-numeric.z-line-number.z-find-in-files{color:#676c72}:root .z-constant.z-numeric.z-line-number.z-match{color:#0062e8}:root .z-entity.z-name.z-filename.z-find-in-files{color:#497700}:root .z-message.z-error{color:#da0001}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-markup.z-heading{color:#0062e8;font-weight:bold}:root .z-string.z-other.z-link,:root .z-markup.z-underline.z-link{color:#007b59;text-decoration:underline;font-style:italic}:root .z-punctuation.z-definition.z-image{color:#a45600}:root .z-markup.z-italic{color:#b94046;font-style:italic}:root .z-markup.z-bold{color:#b94046;font-weight:bold}:root .z-markup.z-italic .z-markup.z-bold,:root .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root .z-markup.z-raw{background-color:#50565a}:root .z-markup.z-raw.z-inline{background-color:#50565a}:root .z-meta.z-separator{color:#676c72;background-color:#50565a;font-weight:bold}:root .z-markup.z-quote{color:#b04e00;font-style:italic}:root .z-markup.z-list.z-numbered.z-bullet,:root .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#007b59}:root .z-markup.z-inserted{color:#497700}:root .z-markup.z-changed{color:#007492}:root .z-markup.z-deleted{color:#b94046}:root .z-markup.z-strike{color:#8b6426}:root .z-markup.z-table{color:#007492;background-color:#50565a}:root .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#a4552c}:root .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#676c72}:root .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#50565a;background-color:#50565a}:root .z-punctuation.z-definition.z-fenced.z-markdown,:root .z-variable.z-language.z-fenced.z-markdown{color:#676c72;background-color:#50565a}:root .z-variable.z-language.z-fenced.z-markdown{color:#676c72}:root .z-markup.z-inserted.z-git_gutter{color:#497700}:root .z-markup.z-changed.z-git_gutter{color:#007492}:root .z-markup.z-deleted.z-git_gutter{color:#da0001}:root .z-markup.z-ignored.z-git_gutter{color:#696b6c}:root .z-markup.z-untracked.z-git_gutter{color:#696b6c}:root .z-gutter_color{color:#fff}:root .z-acejump.z-label.z-blue{color:#fff;background-color:#007492}:root .z-acejump.z-label.z-green{color:#fff;background-color:#497700}:root .z-acejump.z-label.z-orange{color:#fff;background-color:#0062e8}:root .z-acejump.z-label.z-purple{color:#fff;background-color:#b94046}:root .z-sublimelinter.z-mark.z-warning{color:#007492}:root .z-sublimelinter.z-gutter-mark{color:#fff}:root .z-sublimelinter.z-mark.z-error{color:#da0001}}:root{--f1: #ccc;--f2: #ddd;--c1: #111;--c2: #222;--c3: #333;--c4: #888;--a1: #09f;--a2: #0bf;--a3: #0af;--cg: #593;--cr: #e33}@media (prefers-color-scheme: light){:root{--f1: #444;--f2: #333;--c1: #fff;--c2: #eee;--c3: #ddd;--c4: #677;--a1: #06e;--a2: #09f;--a3: #07f;--cg: #373;--cr: #d33}} \ No newline at end of file diff --git a/abridge-blueshade-dark.css b/abridge-blueshade-dark.css new file mode 100644 index 000000000..0b7f5caef --- /dev/null +++ b/abridge-blueshade-dark.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}.z-code{color:#bfbab0;background-color:#191919}.z-comment,.z-punctuation.z-definition.z-comment{color:#87929f;font-style:italic}.z-variable{color:#bfbab0}.z-string,.z-constant.z-other.z-symbol{color:#c2d94c}.z-constant.z-numeric{color:#f29718}.z-string.z-regexp,.z-constant.z-character.z-escape{color:#95e6cb}.z-constant.z-language{color:#f29718}.z-constant.z-character,.z-constant.z-other{color:#f29718}.z-variable.z-member{color:#fe7d83}.z-keyword,.z-keyword.z-operator.z-word{color:#0bf}.z-keyword.z-operator{color:#f29668}.z-punctuation.z-separator,.z-punctuation.z-terminator{color:#bfbab0}.z-punctuation.z-section{color:#bfbab0}.z-punctuation.z-accessor{color:#f29668}.z-punctuation.z-definition.z-annotation{color:#bfbab0}.z-variable.z-other.z-dollar.z-only.z-js,.z-variable.z-other.z-object.z-dollar.z-only.z-js,.z-variable.z-type.z-dollar.z-only.z-js,.z-support.z-class.z-dollar.z-only.z-js{color:#e6b673}.z-storage{color:#0bf}.z-storage.z-type{color:#0bf}.z-entity.z-name.z-function{color:#ffb454}.z-entity.z-name,.z-entity.z-name.z-tag,.z-entity.z-name.z-label{color:#59c2ff}.z-entity.z-other.z-inherited-class{color:#59c2ff;text-decoration:underline}.z-variable.z-parameter{color:#f29718}.z-variable.z-language{color:#39bae6;font-style:italic}.z-entity.z-name.z-tag,.z-meta.z-tag.z-sgml{color:#39bae6}.z-punctuation.z-definition.z-tag.z-end,.z-punctuation.z-definition.z-tag.z-begin,.z-punctuation.z-definition.z-tag{color:#39bae6}.z-entity.z-other.z-attribute-name{color:#ffb454}.z-variable.z-function,.z-variable.z-annotation{color:#ffb454}.z-support.z-function,.z-support.z-macro{color:#fe7d83}.z-support.z-constant{color:#f29668;font-style:italic}.z-support.z-type,.z-support.z-class{color:#39bae6;font-style:italic}.z-invalid{color:#ff7c6d}.z-invalid.z-deprecated{color:#fff;background-color:#0bf}.z-meta.z-diff,.z-meta.z-diff.z-header{color:#c594c5}.z-source.z-ruby .z-variable.z-other.z-readwrite{color:#ffb454}.z-source.z-css .z-entity.z-name.z-tag,.z-source.z-sass .z-entity.z-name.z-tag,.z-source.z-scss .z-entity.z-name.z-tag,.z-source.z-less .z-entity.z-name.z-tag,.z-source.z-stylus .z-entity.z-name.z-tag{color:#59c2ff}.z-source.z-css .z-support.z-type,.z-source.z-sass .z-support.z-type,.z-source.z-scss .z-support.z-type,.z-source.z-less .z-support.z-type,.z-source.z-stylus .z-support.z-type{color:#798491}.z-support.z-type.z-property-name{color:#39bae6}.z-constant.z-numeric.z-line-number.z-find-in-files{color:#798491}.z-constant.z-numeric.z-line-number.z-match{color:#0bf}.z-entity.z-name.z-filename.z-find-in-files{color:#c2d94c}.z-message.z-error{color:#ff7c6d}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-markup.z-heading{color:#0bf;font-weight:bold}.z-string.z-other.z-link,.z-markup.z-underline.z-link{color:#95e6cb;text-decoration:underline;font-style:italic}.z-punctuation.z-definition.z-image{color:#ffb454}.z-markup.z-italic{color:#fe7d83;font-style:italic}.z-markup.z-bold{color:#fe7d83;font-weight:bold}.z-markup.z-italic .z-markup.z-bold,.z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}.z-markup.z-raw{background-color:#bfbab0}.z-markup.z-raw.z-inline{background-color:#bfbab0}.z-meta.z-separator{color:#798491;background-color:#bfbab0;font-weight:bold}.z-markup.z-quote{color:#f29718;font-style:italic}.z-markup.z-list.z-numbered.z-bullet,.z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#95e6cb}.z-markup.z-inserted{color:#c2d94c}.z-markup.z-changed{color:#39bae6}.z-markup.z-deleted{color:#fe7d83}.z-markup.z-strike{color:#e6b673}.z-markup.z-table{color:#39bae6;background-color:#bfbab0}.z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#f29668}.z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#798491}.z-markup.z-raw.z-block.z-fenced.z-markdown{color:#bfbab0;background-color:#bfbab0}.z-punctuation.z-definition.z-fenced.z-markdown,.z-variable.z-language.z-fenced.z-markdown{color:#798491;background-color:#bfbab0}.z-variable.z-language.z-fenced.z-markdown{color:#798491}.z-markup.z-inserted.z-git_gutter{color:#c2d94c}.z-markup.z-changed.z-git_gutter{color:#39bae6}.z-markup.z-deleted.z-git_gutter{color:#ff7c6d}.z-markup.z-ignored.z-git_gutter{color:#20272c}.z-markup.z-untracked.z-git_gutter{color:#20272c}.z-gutter_color{color:#fff}.z-acejump.z-label.z-blue{color:#fff;background-color:#39bae6}.z-acejump.z-label.z-green{color:#fff;background-color:#c2d94c}.z-acejump.z-label.z-orange{color:#fff;background-color:#0bf}.z-acejump.z-label.z-purple{color:#fff;background-color:#fe7d83}.z-sublimelinter.z-mark.z-warning{color:#39bae6}.z-sublimelinter.z-gutter-mark{color:#fff}.z-sublimelinter.z-mark.z-error{color:#ff7c6d}:root{--f1: #ccc;--f2: #ddd;--c1: #111;--c2: #123;--c3: #345;--c4: #789;--a1: #09f;--a2: #0bf;--a3: #0af;--cg: #593;--cr: #e33} \ No newline at end of file diff --git a/abridge-blueshade-light.css b/abridge-blueshade-light.css new file mode 100644 index 000000000..a9afdb12f --- /dev/null +++ b/abridge-blueshade-light.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}.z-code{color:#50565a;background-color:#fafafa}.z-comment,.z-punctuation.z-definition.z-comment{color:#676c72;font-style:italic}.z-variable{color:#50565a}.z-string,.z-constant.z-other.z-symbol{color:#497700}.z-constant.z-numeric{color:#b04e00}.z-string.z-regexp,.z-constant.z-character.z-escape{color:#007b59}.z-constant.z-language{color:#b04e00}.z-constant.z-character,.z-constant.z-other{color:#b04e00}.z-variable.z-member{color:#c33947}.z-keyword,.z-keyword.z-operator.z-word{color:#0062e8}.z-keyword.z-operator{color:#a4552c}.z-punctuation.z-separator,.z-punctuation.z-terminator{color:#50565a}.z-punctuation.z-section{color:#50565a}.z-punctuation.z-accessor{color:#a4552c}.z-punctuation.z-definition.z-annotation{color:#50565a}.z-variable.z-other.z-dollar.z-only.z-js,.z-variable.z-other.z-object.z-dollar.z-only.z-js,.z-variable.z-type.z-dollar.z-only.z-js,.z-support.z-class.z-dollar.z-only.z-js{color:#8b6426}.z-storage{color:#0062e8}.z-storage.z-type{color:#0062e8}.z-entity.z-name.z-function{color:#a45600}.z-entity.z-name,.z-entity.z-name.z-tag,.z-entity.z-name.z-label{color:#0070b3}.z-entity.z-other.z-inherited-class{color:#0070b3;text-decoration:underline}.z-variable.z-parameter{color:#b04e00}.z-variable.z-language{color:#007492;font-style:italic}.z-entity.z-name.z-tag,.z-meta.z-tag.z-sgml{color:#007492}.z-punctuation.z-definition.z-tag.z-end,.z-punctuation.z-definition.z-tag.z-begin,.z-punctuation.z-definition.z-tag{color:#007492}.z-entity.z-other.z-attribute-name{color:#a45600}.z-variable.z-function,.z-variable.z-annotation{color:#a45600}.z-support.z-function,.z-support.z-macro{color:#b94046}.z-support.z-constant{color:#a4552c;font-style:italic}.z-support.z-type,.z-support.z-class{color:#007492;font-style:italic}.z-invalid{color:#da0001}.z-invalid.z-deprecated{color:#fff;background-color:#0062e8}.z-source.z-ruby .z-variable.z-other.z-readwrite{color:#a45600}.z-source.z-css .z-entity.z-name.z-tag,.z-source.z-sass .z-entity.z-name.z-tag,.z-source.z-scss .z-entity.z-name.z-tag,.z-source.z-less .z-entity.z-name.z-tag,.z-source.z-stylus .z-entity.z-name.z-tag{color:#0070b3}.z-source.z-css .z-support.z-type,.z-source.z-sass .z-support.z-type,.z-source.z-scss .z-support.z-type,.z-source.z-less .z-support.z-type,.z-source.z-stylus .z-support.z-type{color:#676c72}.z-support.z-type.z-property-name{color:#007492}.z-constant.z-numeric.z-line-number.z-find-in-files{color:#676c72}.z-constant.z-numeric.z-line-number.z-match{color:#0062e8}.z-entity.z-name.z-filename.z-find-in-files{color:#497700}.z-message.z-error{color:#da0001}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-markup.z-heading{color:#0062e8;font-weight:bold}.z-string.z-other.z-link,.z-markup.z-underline.z-link{color:#007b59;text-decoration:underline;font-style:italic}.z-punctuation.z-definition.z-image{color:#a45600}.z-markup.z-italic{color:#b94046;font-style:italic}.z-markup.z-bold{color:#b94046;font-weight:bold}.z-markup.z-italic .z-markup.z-bold,.z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}.z-markup.z-raw{background-color:#50565a}.z-markup.z-raw.z-inline{background-color:#50565a}.z-meta.z-separator{color:#676c72;background-color:#50565a;font-weight:bold}.z-markup.z-quote{color:#b04e00;font-style:italic}.z-markup.z-list.z-numbered.z-bullet,.z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#007b59}.z-markup.z-inserted{color:#497700}.z-markup.z-changed{color:#007492}.z-markup.z-deleted{color:#b94046}.z-markup.z-strike{color:#8b6426}.z-markup.z-table{color:#007492;background-color:#50565a}.z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#a4552c}.z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#676c72}.z-markup.z-raw.z-block.z-fenced.z-markdown{color:#50565a;background-color:#50565a}.z-punctuation.z-definition.z-fenced.z-markdown,.z-variable.z-language.z-fenced.z-markdown{color:#676c72;background-color:#50565a}.z-variable.z-language.z-fenced.z-markdown{color:#676c72}.z-markup.z-inserted.z-git_gutter{color:#497700}.z-markup.z-changed.z-git_gutter{color:#007492}.z-markup.z-deleted.z-git_gutter{color:#da0001}.z-markup.z-ignored.z-git_gutter{color:#696b6c}.z-markup.z-untracked.z-git_gutter{color:#696b6c}.z-gutter_color{color:#fff}.z-acejump.z-label.z-blue{color:#fff;background-color:#007492}.z-acejump.z-label.z-green{color:#fff;background-color:#497700}.z-acejump.z-label.z-orange{color:#fff;background-color:#0062e8}.z-acejump.z-label.z-purple{color:#fff;background-color:#b94046}.z-sublimelinter.z-mark.z-warning{color:#007492}.z-sublimelinter.z-gutter-mark{color:#fff}.z-sublimelinter.z-mark.z-error{color:#da0001}:root{--f1: #444;--f2: #333;--c1: #fff;--c2: #def;--c3: #137;--c4: #013;--a1: #06e;--a2: #09f;--a3: #07f;--cg: #373;--cr: #d33} \ No newline at end of file diff --git a/abridge-blueshade-switcher.css b/abridge-blueshade-switcher.css new file mode 100644 index 000000000..341ab19e1 --- /dev/null +++ b/abridge-blueshade-switcher.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}:root:not(.light) .z-code{color:#bfbab0;background-color:#191919}:root:not(.light) .z-comment,:root:not(.light) .z-punctuation.z-definition.z-comment{color:#87929f;font-style:italic}:root:not(.light) .z-variable{color:#bfbab0}:root:not(.light) .z-string,:root:not(.light) .z-constant.z-other.z-symbol{color:#c2d94c}:root:not(.light) .z-constant.z-numeric{color:#f29718}:root:not(.light) .z-string.z-regexp,:root:not(.light) .z-constant.z-character.z-escape{color:#95e6cb}:root:not(.light) .z-constant.z-language{color:#f29718}:root:not(.light) .z-constant.z-character,:root:not(.light) .z-constant.z-other{color:#f29718}:root:not(.light) .z-variable.z-member{color:#fe7d83}:root:not(.light) .z-keyword,:root:not(.light) .z-keyword.z-operator.z-word{color:#0bf}:root:not(.light) .z-keyword.z-operator{color:#f29668}:root:not(.light) .z-punctuation.z-separator,:root:not(.light) .z-punctuation.z-terminator{color:#bfbab0}:root:not(.light) .z-punctuation.z-section{color:#bfbab0}:root:not(.light) .z-punctuation.z-accessor{color:#f29668}:root:not(.light) .z-punctuation.z-definition.z-annotation{color:#bfbab0}:root:not(.light) .z-variable.z-other.z-dollar.z-only.z-js,:root:not(.light) .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root:not(.light) .z-variable.z-type.z-dollar.z-only.z-js,:root:not(.light) .z-support.z-class.z-dollar.z-only.z-js{color:#e6b673}:root:not(.light) .z-storage{color:#0bf}:root:not(.light) .z-storage.z-type{color:#0bf}:root:not(.light) .z-entity.z-name.z-function{color:#ffb454}:root:not(.light) .z-entity.z-name,:root:not(.light) .z-entity.z-name.z-tag,:root:not(.light) .z-entity.z-name.z-label{color:#59c2ff}:root:not(.light) .z-entity.z-other.z-inherited-class{color:#59c2ff;text-decoration:underline}:root:not(.light) .z-variable.z-parameter{color:#f29718}:root:not(.light) .z-variable.z-language{color:#39bae6;font-style:italic}:root:not(.light) .z-entity.z-name.z-tag,:root:not(.light) .z-meta.z-tag.z-sgml{color:#39bae6}:root:not(.light) .z-punctuation.z-definition.z-tag.z-end,:root:not(.light) .z-punctuation.z-definition.z-tag.z-begin,:root:not(.light) .z-punctuation.z-definition.z-tag{color:#39bae6}:root:not(.light) .z-entity.z-other.z-attribute-name{color:#ffb454}:root:not(.light) .z-variable.z-function,:root:not(.light) .z-variable.z-annotation{color:#ffb454}:root:not(.light) .z-support.z-function,:root:not(.light) .z-support.z-macro{color:#fe7d83}:root:not(.light) .z-support.z-constant{color:#f29668;font-style:italic}:root:not(.light) .z-support.z-type,:root:not(.light) .z-support.z-class{color:#39bae6;font-style:italic}:root:not(.light) .z-invalid{color:#ff7c6d}:root:not(.light) .z-invalid.z-deprecated{color:#fff;background-color:#0bf}:root:not(.light) .z-meta.z-diff,:root:not(.light) .z-meta.z-diff.z-header{color:#c594c5}:root:not(.light) .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#ffb454}:root:not(.light) .z-source.z-css .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-sass .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-scss .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-less .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-stylus .z-entity.z-name.z-tag{color:#59c2ff}:root:not(.light) .z-source.z-css .z-support.z-type,:root:not(.light) .z-source.z-sass .z-support.z-type,:root:not(.light) .z-source.z-scss .z-support.z-type,:root:not(.light) .z-source.z-less .z-support.z-type,:root:not(.light) .z-source.z-stylus .z-support.z-type{color:#798491}:root:not(.light) .z-support.z-type.z-property-name{color:#39bae6}:root:not(.light) .z-constant.z-numeric.z-line-number.z-find-in-files{color:#798491}:root:not(.light) .z-constant.z-numeric.z-line-number.z-match{color:#0bf}:root:not(.light) .z-entity.z-name.z-filename.z-find-in-files{color:#c2d94c}:root:not(.light) .z-message.z-error{color:#ff7c6d}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-markup.z-heading{color:#0bf;font-weight:bold}:root:not(.light) .z-string.z-other.z-link,:root:not(.light) .z-markup.z-underline.z-link{color:#95e6cb;text-decoration:underline;font-style:italic}:root:not(.light) .z-punctuation.z-definition.z-image{color:#ffb454}:root:not(.light) .z-markup.z-italic{color:#fe7d83;font-style:italic}:root:not(.light) .z-markup.z-bold{color:#fe7d83;font-weight:bold}:root:not(.light) .z-markup.z-italic .z-markup.z-bold,:root:not(.light) .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root:not(.light) .z-markup.z-raw{background-color:#bfbab0}:root:not(.light) .z-markup.z-raw.z-inline{background-color:#bfbab0}:root:not(.light) .z-meta.z-separator{color:#798491;background-color:#bfbab0;font-weight:bold}:root:not(.light) .z-markup.z-quote{color:#f29718;font-style:italic}:root:not(.light) .z-markup.z-list.z-numbered.z-bullet,:root:not(.light) .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#95e6cb}:root:not(.light) .z-markup.z-inserted{color:#c2d94c}:root:not(.light) .z-markup.z-changed{color:#39bae6}:root:not(.light) .z-markup.z-deleted{color:#fe7d83}:root:not(.light) .z-markup.z-strike{color:#e6b673}:root:not(.light) .z-markup.z-table{color:#39bae6;background-color:#bfbab0}:root:not(.light) .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#f29668}:root:not(.light) .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#798491}:root:not(.light) .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#bfbab0;background-color:#bfbab0}:root:not(.light) .z-punctuation.z-definition.z-fenced.z-markdown,:root:not(.light) .z-variable.z-language.z-fenced.z-markdown{color:#798491;background-color:#bfbab0}:root:not(.light) .z-variable.z-language.z-fenced.z-markdown{color:#798491}:root:not(.light) .z-markup.z-inserted.z-git_gutter{color:#c2d94c}:root:not(.light) .z-markup.z-changed.z-git_gutter{color:#39bae6}:root:not(.light) .z-markup.z-deleted.z-git_gutter{color:#ff7c6d}:root:not(.light) .z-markup.z-ignored.z-git_gutter{color:#20272c}:root:not(.light) .z-markup.z-untracked.z-git_gutter{color:#20272c}:root:not(.light) .z-gutter_color{color:#fff}:root:not(.light) .z-acejump.z-label.z-blue{color:#fff;background-color:#39bae6}:root:not(.light) .z-acejump.z-label.z-green{color:#fff;background-color:#c2d94c}:root:not(.light) .z-acejump.z-label.z-orange{color:#fff;background-color:#0bf}:root:not(.light) .z-acejump.z-label.z-purple{color:#fff;background-color:#fe7d83}:root:not(.light) .z-sublimelinter.z-mark.z-warning{color:#39bae6}:root:not(.light) .z-sublimelinter.z-gutter-mark{color:#fff}:root:not(.light) .z-sublimelinter.z-mark.z-error{color:#ff7c6d}:root.light .z-code{color:#50565a;background-color:#fafafa}:root.light .z-comment,:root.light .z-punctuation.z-definition.z-comment{color:#676c72;font-style:italic}:root.light .z-variable{color:#50565a}:root.light .z-string,:root.light .z-constant.z-other.z-symbol{color:#497700}:root.light .z-constant.z-numeric{color:#b04e00}:root.light .z-string.z-regexp,:root.light .z-constant.z-character.z-escape{color:#007b59}:root.light .z-constant.z-language{color:#b04e00}:root.light .z-constant.z-character,:root.light .z-constant.z-other{color:#b04e00}:root.light .z-variable.z-member{color:#c33947}:root.light .z-keyword,:root.light .z-keyword.z-operator.z-word{color:#0062e8}:root.light .z-keyword.z-operator{color:#a4552c}:root.light .z-punctuation.z-separator,:root.light .z-punctuation.z-terminator{color:#50565a}:root.light .z-punctuation.z-section{color:#50565a}:root.light .z-punctuation.z-accessor{color:#a4552c}:root.light .z-punctuation.z-definition.z-annotation{color:#50565a}:root.light .z-variable.z-other.z-dollar.z-only.z-js,:root.light .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root.light .z-variable.z-type.z-dollar.z-only.z-js,:root.light .z-support.z-class.z-dollar.z-only.z-js{color:#8b6426}:root.light .z-storage{color:#0062e8}:root.light .z-storage.z-type{color:#0062e8}:root.light .z-entity.z-name.z-function{color:#a45600}:root.light .z-entity.z-name,:root.light .z-entity.z-name.z-tag,:root.light .z-entity.z-name.z-label{color:#0070b3}:root.light .z-entity.z-other.z-inherited-class{color:#0070b3;text-decoration:underline}:root.light .z-variable.z-parameter{color:#b04e00}:root.light .z-variable.z-language{color:#007492;font-style:italic}:root.light .z-entity.z-name.z-tag,:root.light .z-meta.z-tag.z-sgml{color:#007492}:root.light .z-punctuation.z-definition.z-tag.z-end,:root.light .z-punctuation.z-definition.z-tag.z-begin,:root.light .z-punctuation.z-definition.z-tag{color:#007492}:root.light .z-entity.z-other.z-attribute-name{color:#a45600}:root.light .z-variable.z-function,:root.light .z-variable.z-annotation{color:#a45600}:root.light .z-support.z-function,:root.light .z-support.z-macro{color:#b94046}:root.light .z-support.z-constant{color:#a4552c;font-style:italic}:root.light .z-support.z-type,:root.light .z-support.z-class{color:#007492;font-style:italic}:root.light .z-invalid{color:#da0001}:root.light .z-invalid.z-deprecated{color:#fff;background-color:#0062e8}:root.light .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#a45600}:root.light .z-source.z-css .z-entity.z-name.z-tag,:root.light .z-source.z-sass .z-entity.z-name.z-tag,:root.light .z-source.z-scss .z-entity.z-name.z-tag,:root.light .z-source.z-less .z-entity.z-name.z-tag,:root.light .z-source.z-stylus .z-entity.z-name.z-tag{color:#0070b3}:root.light .z-source.z-css .z-support.z-type,:root.light .z-source.z-sass .z-support.z-type,:root.light .z-source.z-scss .z-support.z-type,:root.light .z-source.z-less .z-support.z-type,:root.light .z-source.z-stylus .z-support.z-type{color:#676c72}:root.light .z-support.z-type.z-property-name{color:#007492}:root.light .z-constant.z-numeric.z-line-number.z-find-in-files{color:#676c72}:root.light .z-constant.z-numeric.z-line-number.z-match{color:#0062e8}:root.light .z-entity.z-name.z-filename.z-find-in-files{color:#497700}:root.light .z-message.z-error{color:#da0001}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-markup.z-heading{color:#0062e8;font-weight:bold}:root.light .z-string.z-other.z-link,:root.light .z-markup.z-underline.z-link{color:#007b59;text-decoration:underline;font-style:italic}:root.light .z-punctuation.z-definition.z-image{color:#a45600}:root.light .z-markup.z-italic{color:#b94046;font-style:italic}:root.light .z-markup.z-bold{color:#b94046;font-weight:bold}:root.light .z-markup.z-italic .z-markup.z-bold,:root.light .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root.light .z-markup.z-raw{background-color:#50565a}:root.light .z-markup.z-raw.z-inline{background-color:#50565a}:root.light .z-meta.z-separator{color:#676c72;background-color:#50565a;font-weight:bold}:root.light .z-markup.z-quote{color:#b04e00;font-style:italic}:root.light .z-markup.z-list.z-numbered.z-bullet,:root.light .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#007b59}:root.light .z-markup.z-inserted{color:#497700}:root.light .z-markup.z-changed{color:#007492}:root.light .z-markup.z-deleted{color:#b94046}:root.light .z-markup.z-strike{color:#8b6426}:root.light .z-markup.z-table{color:#007492;background-color:#50565a}:root.light .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#a4552c}:root.light .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#676c72}:root.light .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#50565a;background-color:#50565a}:root.light .z-punctuation.z-definition.z-fenced.z-markdown,:root.light .z-variable.z-language.z-fenced.z-markdown{color:#676c72;background-color:#50565a}:root.light .z-variable.z-language.z-fenced.z-markdown{color:#676c72}:root.light .z-markup.z-inserted.z-git_gutter{color:#497700}:root.light .z-markup.z-changed.z-git_gutter{color:#007492}:root.light .z-markup.z-deleted.z-git_gutter{color:#da0001}:root.light .z-markup.z-ignored.z-git_gutter{color:#696b6c}:root.light .z-markup.z-untracked.z-git_gutter{color:#696b6c}:root.light .z-gutter_color{color:#fff}:root.light .z-acejump.z-label.z-blue{color:#fff;background-color:#007492}:root.light .z-acejump.z-label.z-green{color:#fff;background-color:#497700}:root.light .z-acejump.z-label.z-orange{color:#fff;background-color:#0062e8}:root.light .z-acejump.z-label.z-purple{color:#fff;background-color:#b94046}:root.light .z-sublimelinter.z-mark.z-warning{color:#007492}:root.light .z-sublimelinter.z-gutter-mark{color:#fff}:root.light .z-sublimelinter.z-mark.z-error{color:#da0001}:root:not(.light){--f1: #ccc;--f2: #ddd;--c1: #111;--c2: #123;--c3: #345;--c4: #789;--a1: #09f;--a2: #0bf;--a3: #0af;--cg: #593;--cr: #e33}:root.light{--f1: #444;--f2: #333;--c1: #fff;--c2: #def;--c3: #137;--c4: #013;--a1: #06e;--a2: #09f;--a3: #07f;--cg: #373;--cr: #d33} \ No newline at end of file diff --git a/abridge-blueshade.css b/abridge-blueshade.css new file mode 100644 index 000000000..c4e3a2169 --- /dev/null +++ b/abridge-blueshade.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}:root .z-code{color:#bfbab0;background-color:#191919}:root .z-comment,:root .z-punctuation.z-definition.z-comment{color:#87929f;font-style:italic}:root .z-variable{color:#bfbab0}:root .z-string,:root .z-constant.z-other.z-symbol{color:#c2d94c}:root .z-constant.z-numeric{color:#f29718}:root .z-string.z-regexp,:root .z-constant.z-character.z-escape{color:#95e6cb}:root .z-constant.z-language{color:#f29718}:root .z-constant.z-character,:root .z-constant.z-other{color:#f29718}:root .z-variable.z-member{color:#fe7d83}:root .z-keyword,:root .z-keyword.z-operator.z-word{color:#0bf}:root .z-keyword.z-operator{color:#f29668}:root .z-punctuation.z-separator,:root .z-punctuation.z-terminator{color:#bfbab0}:root .z-punctuation.z-section{color:#bfbab0}:root .z-punctuation.z-accessor{color:#f29668}:root .z-punctuation.z-definition.z-annotation{color:#bfbab0}:root .z-variable.z-other.z-dollar.z-only.z-js,:root .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root .z-variable.z-type.z-dollar.z-only.z-js,:root .z-support.z-class.z-dollar.z-only.z-js{color:#e6b673}:root .z-storage{color:#0bf}:root .z-storage.z-type{color:#0bf}:root .z-entity.z-name.z-function{color:#ffb454}:root .z-entity.z-name,:root .z-entity.z-name.z-tag,:root .z-entity.z-name.z-label{color:#59c2ff}:root .z-entity.z-other.z-inherited-class{color:#59c2ff;text-decoration:underline}:root .z-variable.z-parameter{color:#f29718}:root .z-variable.z-language{color:#39bae6;font-style:italic}:root .z-entity.z-name.z-tag,:root .z-meta.z-tag.z-sgml{color:#39bae6}:root .z-punctuation.z-definition.z-tag.z-end,:root .z-punctuation.z-definition.z-tag.z-begin,:root .z-punctuation.z-definition.z-tag{color:#39bae6}:root .z-entity.z-other.z-attribute-name{color:#ffb454}:root .z-variable.z-function,:root .z-variable.z-annotation{color:#ffb454}:root .z-support.z-function,:root .z-support.z-macro{color:#fe7d83}:root .z-support.z-constant{color:#f29668;font-style:italic}:root .z-support.z-type,:root .z-support.z-class{color:#39bae6;font-style:italic}:root .z-invalid{color:#ff7c6d}:root .z-invalid.z-deprecated{color:#fff;background-color:#0bf}:root .z-meta.z-diff,:root .z-meta.z-diff.z-header{color:#c594c5}:root .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#ffb454}:root .z-source.z-css .z-entity.z-name.z-tag,:root .z-source.z-sass .z-entity.z-name.z-tag,:root .z-source.z-scss .z-entity.z-name.z-tag,:root .z-source.z-less .z-entity.z-name.z-tag,:root .z-source.z-stylus .z-entity.z-name.z-tag{color:#59c2ff}:root .z-source.z-css .z-support.z-type,:root .z-source.z-sass .z-support.z-type,:root .z-source.z-scss .z-support.z-type,:root .z-source.z-less .z-support.z-type,:root .z-source.z-stylus .z-support.z-type{color:#798491}:root .z-support.z-type.z-property-name{color:#39bae6}:root .z-constant.z-numeric.z-line-number.z-find-in-files{color:#798491}:root .z-constant.z-numeric.z-line-number.z-match{color:#0bf}:root .z-entity.z-name.z-filename.z-find-in-files{color:#c2d94c}:root .z-message.z-error{color:#ff7c6d}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-markup.z-heading{color:#0bf;font-weight:bold}:root .z-string.z-other.z-link,:root .z-markup.z-underline.z-link{color:#95e6cb;text-decoration:underline;font-style:italic}:root .z-punctuation.z-definition.z-image{color:#ffb454}:root .z-markup.z-italic{color:#fe7d83;font-style:italic}:root .z-markup.z-bold{color:#fe7d83;font-weight:bold}:root .z-markup.z-italic .z-markup.z-bold,:root .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root .z-markup.z-raw{background-color:#bfbab0}:root .z-markup.z-raw.z-inline{background-color:#bfbab0}:root .z-meta.z-separator{color:#798491;background-color:#bfbab0;font-weight:bold}:root .z-markup.z-quote{color:#f29718;font-style:italic}:root .z-markup.z-list.z-numbered.z-bullet,:root .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#95e6cb}:root .z-markup.z-inserted{color:#c2d94c}:root .z-markup.z-changed{color:#39bae6}:root .z-markup.z-deleted{color:#fe7d83}:root .z-markup.z-strike{color:#e6b673}:root .z-markup.z-table{color:#39bae6;background-color:#bfbab0}:root .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#f29668}:root .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#798491}:root .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#bfbab0;background-color:#bfbab0}:root .z-punctuation.z-definition.z-fenced.z-markdown,:root .z-variable.z-language.z-fenced.z-markdown{color:#798491;background-color:#bfbab0}:root .z-variable.z-language.z-fenced.z-markdown{color:#798491}:root .z-markup.z-inserted.z-git_gutter{color:#c2d94c}:root .z-markup.z-changed.z-git_gutter{color:#39bae6}:root .z-markup.z-deleted.z-git_gutter{color:#ff7c6d}:root .z-markup.z-ignored.z-git_gutter{color:#20272c}:root .z-markup.z-untracked.z-git_gutter{color:#20272c}:root .z-gutter_color{color:#fff}:root .z-acejump.z-label.z-blue{color:#fff;background-color:#39bae6}:root .z-acejump.z-label.z-green{color:#fff;background-color:#c2d94c}:root .z-acejump.z-label.z-orange{color:#fff;background-color:#0bf}:root .z-acejump.z-label.z-purple{color:#fff;background-color:#fe7d83}:root .z-sublimelinter.z-mark.z-warning{color:#39bae6}:root .z-sublimelinter.z-gutter-mark{color:#fff}:root .z-sublimelinter.z-mark.z-error{color:#ff7c6d}@media (prefers-color-scheme: light){:root .z-code{color:#50565a;background-color:#fafafa}:root .z-comment,:root .z-punctuation.z-definition.z-comment{color:#676c72;font-style:italic}:root .z-variable{color:#50565a}:root .z-string,:root .z-constant.z-other.z-symbol{color:#497700}:root .z-constant.z-numeric{color:#b04e00}:root .z-string.z-regexp,:root .z-constant.z-character.z-escape{color:#007b59}:root .z-constant.z-language{color:#b04e00}:root .z-constant.z-character,:root .z-constant.z-other{color:#b04e00}:root .z-variable.z-member{color:#c33947}:root .z-keyword,:root .z-keyword.z-operator.z-word{color:#0062e8}:root .z-keyword.z-operator{color:#a4552c}:root .z-punctuation.z-separator,:root .z-punctuation.z-terminator{color:#50565a}:root .z-punctuation.z-section{color:#50565a}:root .z-punctuation.z-accessor{color:#a4552c}:root .z-punctuation.z-definition.z-annotation{color:#50565a}:root .z-variable.z-other.z-dollar.z-only.z-js,:root .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root .z-variable.z-type.z-dollar.z-only.z-js,:root .z-support.z-class.z-dollar.z-only.z-js{color:#8b6426}:root .z-storage{color:#0062e8}:root .z-storage.z-type{color:#0062e8}:root .z-entity.z-name.z-function{color:#a45600}:root .z-entity.z-name,:root .z-entity.z-name.z-tag,:root .z-entity.z-name.z-label{color:#0070b3}:root .z-entity.z-other.z-inherited-class{color:#0070b3;text-decoration:underline}:root .z-variable.z-parameter{color:#b04e00}:root .z-variable.z-language{color:#007492;font-style:italic}:root .z-entity.z-name.z-tag,:root .z-meta.z-tag.z-sgml{color:#007492}:root .z-punctuation.z-definition.z-tag.z-end,:root .z-punctuation.z-definition.z-tag.z-begin,:root .z-punctuation.z-definition.z-tag{color:#007492}:root .z-entity.z-other.z-attribute-name{color:#a45600}:root .z-variable.z-function,:root .z-variable.z-annotation{color:#a45600}:root .z-support.z-function,:root .z-support.z-macro{color:#b94046}:root .z-support.z-constant{color:#a4552c;font-style:italic}:root .z-support.z-type,:root .z-support.z-class{color:#007492;font-style:italic}:root .z-invalid{color:#da0001}:root .z-invalid.z-deprecated{color:#fff;background-color:#0062e8}:root .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#a45600}:root .z-source.z-css .z-entity.z-name.z-tag,:root .z-source.z-sass .z-entity.z-name.z-tag,:root .z-source.z-scss .z-entity.z-name.z-tag,:root .z-source.z-less .z-entity.z-name.z-tag,:root .z-source.z-stylus .z-entity.z-name.z-tag{color:#0070b3}:root .z-source.z-css .z-support.z-type,:root .z-source.z-sass .z-support.z-type,:root .z-source.z-scss .z-support.z-type,:root .z-source.z-less .z-support.z-type,:root .z-source.z-stylus .z-support.z-type{color:#676c72}:root .z-support.z-type.z-property-name{color:#007492}:root .z-constant.z-numeric.z-line-number.z-find-in-files{color:#676c72}:root .z-constant.z-numeric.z-line-number.z-match{color:#0062e8}:root .z-entity.z-name.z-filename.z-find-in-files{color:#497700}:root .z-message.z-error{color:#da0001}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-markup.z-heading{color:#0062e8;font-weight:bold}:root .z-string.z-other.z-link,:root .z-markup.z-underline.z-link{color:#007b59;text-decoration:underline;font-style:italic}:root .z-punctuation.z-definition.z-image{color:#a45600}:root .z-markup.z-italic{color:#b94046;font-style:italic}:root .z-markup.z-bold{color:#b94046;font-weight:bold}:root .z-markup.z-italic .z-markup.z-bold,:root .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root .z-markup.z-raw{background-color:#50565a}:root .z-markup.z-raw.z-inline{background-color:#50565a}:root .z-meta.z-separator{color:#676c72;background-color:#50565a;font-weight:bold}:root .z-markup.z-quote{color:#b04e00;font-style:italic}:root .z-markup.z-list.z-numbered.z-bullet,:root .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#007b59}:root .z-markup.z-inserted{color:#497700}:root .z-markup.z-changed{color:#007492}:root .z-markup.z-deleted{color:#b94046}:root .z-markup.z-strike{color:#8b6426}:root .z-markup.z-table{color:#007492;background-color:#50565a}:root .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#a4552c}:root .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#676c72}:root .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#50565a;background-color:#50565a}:root .z-punctuation.z-definition.z-fenced.z-markdown,:root .z-variable.z-language.z-fenced.z-markdown{color:#676c72;background-color:#50565a}:root .z-variable.z-language.z-fenced.z-markdown{color:#676c72}:root .z-markup.z-inserted.z-git_gutter{color:#497700}:root .z-markup.z-changed.z-git_gutter{color:#007492}:root .z-markup.z-deleted.z-git_gutter{color:#da0001}:root .z-markup.z-ignored.z-git_gutter{color:#696b6c}:root .z-markup.z-untracked.z-git_gutter{color:#696b6c}:root .z-gutter_color{color:#fff}:root .z-acejump.z-label.z-blue{color:#fff;background-color:#007492}:root .z-acejump.z-label.z-green{color:#fff;background-color:#497700}:root .z-acejump.z-label.z-orange{color:#fff;background-color:#0062e8}:root .z-acejump.z-label.z-purple{color:#fff;background-color:#b94046}:root .z-sublimelinter.z-mark.z-warning{color:#007492}:root .z-sublimelinter.z-gutter-mark{color:#fff}:root .z-sublimelinter.z-mark.z-error{color:#da0001}}:root{--f1: #ccc;--f2: #ddd;--c1: #111;--c2: #123;--c3: #345;--c4: #789;--a1: #09f;--a2: #0bf;--a3: #0af;--cg: #593;--cr: #e33}@media (prefers-color-scheme: light){:root{--f1: #444;--f2: #333;--c1: #fff;--c2: #def;--c3: #137;--c4: #013;--a1: #06e;--a2: #09f;--a3: #07f;--cg: #373;--cr: #d33}} \ No newline at end of file diff --git a/abridge-bundle-nofacade.min.js b/abridge-bundle-nofacade.min.js new file mode 100644 index 000000000..405438b2f --- /dev/null +++ b/abridge-bundle-nofacade.min.js @@ -0,0 +1 @@ +const items=document.querySelectorAll(".preStyle");function closeSearchNow(){const e=document.querySelector("main");e.innerHTML=window.main}function goSearchNow(){const e=document.querySelector("main");window.main||(window.main=e.innerHTML);var t=document.getElementById("suggestions"),n=t.cloneNode(!0),o=(n.id="results",document.createElement("div")),i='

Results For: '.concat(document.getElementById("searchinput").value,"

");return o.innerHTML=i,n.insertBefore(o,n.firstChild),e.innerHTML=n.outerHTML,t.innerHTML="",document.getElementById("searchinput").value="",document.body.contains(document.closeSearch)&&(document.closeSearch.onsubmit=function(){closeSearchNow()}),!1}items.forEach(e=>{e.rel="stylesheet"}),document.getElementById("mode").addEventListener("click",()=>{document.documentElement.classList.toggle("light"),localStorage.setItem("theme",document.documentElement.classList.contains("light")?"light":"dark")}),function(){for(var e=document.getElementsByClassName("m-protected"),t=0;tasync function(e,t){var n=t.querySelectorAll("table")["length"];let o="";if(0 tr > td:last-child");i.forEach(e=>{o+=e.innerText})}else o=t.querySelector(":last-child > code").innerText;try{"granted"==(result=await navigator.permissions.query({name:"clipboard-write"})).state||"prompt"==result.state?await navigator.clipboard.writeText(o):r(o,t)}catch(e){r(o,t)}finally{e.innerHTML="Copied",setTimeout(function(){e.innerHTML="Copy"},2e3)}}(t,e)),document.createElement("div"));n.className="ccw",n.appendChild(t),e.parentNode.insertBefore(n,e),n.appendChild(e)}function r(e,t){const n=document.createElement("textArea"),o=(n.contentEditable="true",n.readOnly="false",n.className="copyable-text-area",n.value=e,t.insertBefore(n,t.firstChild),document.createRange()),i=(o.selectNodeContents(n),window.getSelection());i.removeAllRanges(),i.addRange(o),n.setSelectionRange(0,999999),document.execCommand("copy"),t.removeChild(n)}document.querySelectorAll("pre").forEach(e=>t(e))}(),function(){function m(e){var t=new m.Index;return t.pipeline.add(m.trimmer,m.stopWordFilter,m.stemmer),e&&e.call(t,t),t}var a,c,e,t,d,h,f,p,g,y,v,S,x,w,b,E,I,C,D,F,N,L,k,_,n;m.version="0.9.5",((lunr=m).utils={}).warn=(n=this,function(e){n.console&&console.warn&&console.warn(e)}),m.utils.toString=function(e){return null==e?"":e.toString()},(m.EventEmitter=function(){this.events={}}).prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop();if("function"!=typeof t)throw new TypeError("last argument must be a function");e.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},m.EventEmitter.prototype.removeListener=function(e,t){this.hasHandler(e)&&-1!==(t=this.events[e].indexOf(t))&&(this.events[e].splice(t,1),0==this.events[e].length&&delete this.events[e])},m.EventEmitter.prototype.emit=function(e){var t;this.hasHandler(e)&&(t=Array.prototype.slice.call(arguments,1),this.events[e].forEach(function(e){e.apply(void 0,t)},this))},m.EventEmitter.prototype.hasHandler=function(e){return e in this.events},(m.tokenizer=function(e){return arguments.length&&null!=e?Array.isArray(e)?(t=(t=e.filter(function(e){return null!=e})).map(function(e){return m.utils.toString(e).toLowerCase()}),n=[],t.forEach(function(e){e=e.split(m.tokenizer.seperator);n=n.concat(e)},this),n):e.toString().trim().toLowerCase().split(m.tokenizer.seperator):[];var t,n}).defaultSeperator=/[\s\-]+/,m.tokenizer.seperator=m.tokenizer.defaultSeperator,m.tokenizer.setSeperator=function(e){null!=e&&"object"==typeof e&&(m.tokenizer.seperator=e)},m.tokenizer.resetSeperator=function(){m.tokenizer.seperator=m.tokenizer.defaultSeperator},m.tokenizer.getSeperator=function(){return m.tokenizer.seperator},(m.Pipeline=function(){this._queue=[]}).registeredFunctions={},m.Pipeline.registerFunction=function(e,t){t in m.Pipeline.registeredFunctions&&m.utils.warn("Overwriting existing registered function: "+t),e.label=t,m.Pipeline.registeredFunctions[t]=e},m.Pipeline.getRegisteredFunction=function(e){return e in m.Pipeline.registeredFunctions!=1?null:m.Pipeline.registeredFunctions[e]},m.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||m.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},m.Pipeline.load=function(e){var n=new m.Pipeline;return e.forEach(function(e){var t=m.Pipeline.getRegisteredFunction(e);if(!t)throw new Error("Cannot load un-registered function: "+e);n.add(t)}),n},m.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach(function(e){m.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},m.Pipeline.prototype.after=function(e,t){m.Pipeline.warnIfFunctionNotRegistered(t);e=this._queue.indexOf(e);if(-1===e)throw new Error("Cannot find existingFn");this._queue.splice(e+1,0,t)},m.Pipeline.prototype.before=function(e,t){m.Pipeline.warnIfFunctionNotRegistered(t);e=this._queue.indexOf(e);if(-1===e)throw new Error("Cannot find existingFn");this._queue.splice(e,0,t)},m.Pipeline.prototype.remove=function(e){e=this._queue.indexOf(e);-1!==e&&this._queue.splice(e,1)},m.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,o=this._queue.length,i=0;iu[o]&&o++:(t.add(s[n]),n++,o++);return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){for(var t,e=this.length>=e.length?(t=this,e):(t=e,this),n=t.clone(),o=0,i=e.toArray();o",a=n.querySelector("a"),t=n.querySelector("span:first-child"),d=n.querySelector("span:nth-child(2)"),a.href=e.ref,t.textContent=e.doc.title,d.innerHTML=function(e,t){var n=t.map(function(e){return elasticlunr.stemmer(e.toLowerCase())}),o=!1,i=0,r=[],s=e.toLowerCase().split(". ");for(p in s){var u,l=s[p].split(/[\s\n]/),a=8;for(u in l){if(0<(x=l[u]).length){for(var c in n)elasticlunr.stemmer(x).startsWith(n[c])&&(a=40,o=!0);r.push([x,a,i]),a=2}i=i+x.length+1}i+=1}if(0===r.length)return void 0!==e.length&&300m&&(m=d[p],g=p);for(var y=[],v=r[g][2],p=g;p"),v=x[2]+x[0].length;40!==x[1]&&12<=x[0].length&&!/^[\x00-\xff]+$/.test(x[0])?(S=substringByByte(e.substring(x[2],v),12),y.push(S)):y.push(e.substring(x[2],v)),40===x[1]&&y.push("")}return y.push("…"),y.join("")}(e.doc.body,s),suggestions.appendChild(n))});for(;i.length>r;)suggestions.removeChild(i[0])},!0),suggestions.addEventListener("click",function(){for(;suggestions.lastChild;)suggestions.removeChild(suggestions.lastChild);return!1},!0),document.body.contains(document.goSearch)&&(document.goSearch.onsubmit=function(){return goSearchNow()})}(); \ No newline at end of file diff --git a/abridge-bundle-noswitcher.min.js b/abridge-bundle-noswitcher.min.js new file mode 100644 index 000000000..b78beee69 --- /dev/null +++ b/abridge-bundle-noswitcher.min.js @@ -0,0 +1 @@ +const items=document.querySelectorAll(".preStyle");function closeSearchNow(){const e=document.querySelector("main");e.innerHTML=window.main}function goSearchNow(){const e=document.querySelector("main");window.main||(window.main=e.innerHTML);var t=document.getElementById("suggestions"),n=t.cloneNode(!0),o=(n.id="results",document.createElement("div")),i='

Results For: '.concat(document.getElementById("searchinput").value,"

");return o.innerHTML=i,n.insertBefore(o,n.firstChild),e.innerHTML=n.outerHTML,t.innerHTML="",document.getElementById("searchinput").value="",document.body.contains(document.closeSearch)&&(document.closeSearch.onsubmit=function(){closeSearchNow()}),!1}items.forEach(e=>{e.rel="stylesheet"}),function(){for(var e=document.getElementsByClassName("m-protected"),t=0;tasync function(e,t){var n=t.querySelectorAll("table")["length"];let o="";if(0 tr > td:last-child");i.forEach(e=>{o+=e.innerText})}else o=t.querySelector(":last-child > code").innerText;try{"granted"==(result=await navigator.permissions.query({name:"clipboard-write"})).state||"prompt"==result.state?await navigator.clipboard.writeText(o):r(o,t)}catch(e){r(o,t)}finally{e.innerHTML="Copied",setTimeout(function(){e.innerHTML="Copy"},2e3)}}(t,e)),document.createElement("div"));n.className="ccw",n.appendChild(t),e.parentNode.insertBefore(n,e),n.appendChild(e)}function r(e,t){const n=document.createElement("textArea"),o=(n.contentEditable="true",n.readOnly="false",n.className="copyable-text-area",n.value=e,t.insertBefore(n,t.firstChild),document.createRange()),i=(o.selectNodeContents(n),window.getSelection());i.removeAllRanges(),i.addRange(o),n.setSelectionRange(0,999999),document.execCommand("copy"),t.removeChild(n)}document.querySelectorAll("pre").forEach(e=>t(e))}(),function(){function m(e){var t=new m.Index;return t.pipeline.add(m.trimmer,m.stopWordFilter,m.stemmer),e&&e.call(t,t),t}var l,c,e,t,d,h,f,p,g,y,v,S,x,w,b,E,I,C,D,F,N,k,L,_,n;m.version="0.9.5",((lunr=m).utils={}).warn=(n=this,function(e){n.console&&console.warn&&console.warn(e)}),m.utils.toString=function(e){return null==e?"":e.toString()},(m.EventEmitter=function(){this.events={}}).prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop();if("function"!=typeof t)throw new TypeError("last argument must be a function");e.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},m.EventEmitter.prototype.removeListener=function(e,t){this.hasHandler(e)&&-1!==(t=this.events[e].indexOf(t))&&(this.events[e].splice(t,1),0==this.events[e].length&&delete this.events[e])},m.EventEmitter.prototype.emit=function(e){var t;this.hasHandler(e)&&(t=Array.prototype.slice.call(arguments,1),this.events[e].forEach(function(e){e.apply(void 0,t)},this))},m.EventEmitter.prototype.hasHandler=function(e){return e in this.events},(m.tokenizer=function(e){return arguments.length&&null!=e?Array.isArray(e)?(t=(t=e.filter(function(e){return null!=e})).map(function(e){return m.utils.toString(e).toLowerCase()}),n=[],t.forEach(function(e){e=e.split(m.tokenizer.seperator);n=n.concat(e)},this),n):e.toString().trim().toLowerCase().split(m.tokenizer.seperator):[];var t,n}).defaultSeperator=/[\s\-]+/,m.tokenizer.seperator=m.tokenizer.defaultSeperator,m.tokenizer.setSeperator=function(e){null!=e&&"object"==typeof e&&(m.tokenizer.seperator=e)},m.tokenizer.resetSeperator=function(){m.tokenizer.seperator=m.tokenizer.defaultSeperator},m.tokenizer.getSeperator=function(){return m.tokenizer.seperator},(m.Pipeline=function(){this._queue=[]}).registeredFunctions={},m.Pipeline.registerFunction=function(e,t){t in m.Pipeline.registeredFunctions&&m.utils.warn("Overwriting existing registered function: "+t),e.label=t,m.Pipeline.registeredFunctions[t]=e},m.Pipeline.getRegisteredFunction=function(e){return e in m.Pipeline.registeredFunctions!=1?null:m.Pipeline.registeredFunctions[e]},m.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||m.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},m.Pipeline.load=function(e){var n=new m.Pipeline;return e.forEach(function(e){var t=m.Pipeline.getRegisteredFunction(e);if(!t)throw new Error("Cannot load un-registered function: "+e);n.add(t)}),n},m.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach(function(e){m.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},m.Pipeline.prototype.after=function(e,t){m.Pipeline.warnIfFunctionNotRegistered(t);e=this._queue.indexOf(e);if(-1===e)throw new Error("Cannot find existingFn");this._queue.splice(e+1,0,t)},m.Pipeline.prototype.before=function(e,t){m.Pipeline.warnIfFunctionNotRegistered(t);e=this._queue.indexOf(e);if(-1===e)throw new Error("Cannot find existingFn");this._queue.splice(e,0,t)},m.Pipeline.prototype.remove=function(e){e=this._queue.indexOf(e);-1!==e&&this._queue.splice(e,1)},m.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,o=this._queue.length,i=0;iu[o]&&o++:(t.add(s[n]),n++,o++);return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){for(var t,e=this.length>=e.length?(t=this,e):(t=e,this),n=t.clone(),o=0,i=e.toArray();o",a=n.querySelector("a"),t=n.querySelector("span:first-child"),d=n.querySelector("span:nth-child(2)"),a.href=e.ref,t.textContent=e.doc.title,d.innerHTML=function(e,t){var n=t.map(function(e){return elasticlunr.stemmer(e.toLowerCase())}),o=!1,i=0,r=[],s=e.toLowerCase().split(". ");for(p in s){var u,a=s[p].split(/[\s\n]/),l=8;for(u in a){if(0<(x=a[u]).length){for(var c in n)elasticlunr.stemmer(x).startsWith(n[c])&&(l=40,o=!0);r.push([x,l,i]),l=2}i=i+x.length+1}i+=1}if(0===r.length)return void 0!==e.length&&300m&&(m=d[p],g=p);for(var y=[],v=r[g][2],p=g;p"),v=x[2]+x[0].length;40!==x[1]&&12<=x[0].length&&!/^[\x00-\xff]+$/.test(x[0])?(S=substringByByte(e.substring(x[2],v),12),y.push(S)):y.push(e.substring(x[2],v)),40===x[1]&&y.push("")}return y.push("…"),y.join("")}(e.doc.body,s),suggestions.appendChild(n))});for(;i.length>r;)suggestions.removeChild(i[0])},!0),suggestions.addEventListener("click",function(){for(;suggestions.lastChild;)suggestions.removeChild(suggestions.lastChild);return!1},!0),document.body.contains(document.goSearch)&&(document.goSearch.onsubmit=function(){return goSearchNow()})}(); \ No newline at end of file diff --git a/abridge-bundle-searchonly.min.js b/abridge-bundle-searchonly.min.js new file mode 100644 index 000000000..6f79f1b0f --- /dev/null +++ b/abridge-bundle-searchonly.min.js @@ -0,0 +1 @@ +function closeSearchNow(){const e=document.querySelector("main");e.innerHTML=window.main}function goSearchNow(){const e=document.querySelector("main");window.main||(window.main=e.innerHTML);var t=document.getElementById("suggestions"),n=t.cloneNode(!0),o=(n.id="results",document.createElement("div")),i='

Results For: '.concat(document.getElementById("searchinput").value,"

");return o.innerHTML=i,n.insertBefore(o,n.firstChild),e.innerHTML=n.outerHTML,t.innerHTML="",document.getElementById("searchinput").value="",document.body.contains(document.closeSearch)&&(document.closeSearch.onsubmit=function(){closeSearchNow()}),!1}!function(){function m(e){var t=new m.Index;return t.pipeline.add(m.trimmer,m.stopWordFilter,m.stemmer),e&&e.call(t,t),t}var l,c,e,t,d,h,f,p,g,y,v,S,x,w,b,I,E,D,F,C,_,k,N,L,n;m.version="0.9.5",((lunr=m).utils={}).warn=(n=this,function(e){n.console&&console.warn&&console.warn(e)}),m.utils.toString=function(e){return null==e?"":e.toString()},(m.EventEmitter=function(){this.events={}}).prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop();if("function"!=typeof t)throw new TypeError("last argument must be a function");e.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},m.EventEmitter.prototype.removeListener=function(e,t){this.hasHandler(e)&&-1!==(t=this.events[e].indexOf(t))&&(this.events[e].splice(t,1),0==this.events[e].length&&delete this.events[e])},m.EventEmitter.prototype.emit=function(e){var t;this.hasHandler(e)&&(t=Array.prototype.slice.call(arguments,1),this.events[e].forEach(function(e){e.apply(void 0,t)},this))},m.EventEmitter.prototype.hasHandler=function(e){return e in this.events},(m.tokenizer=function(e){return arguments.length&&null!=e?Array.isArray(e)?(t=(t=e.filter(function(e){return null!=e})).map(function(e){return m.utils.toString(e).toLowerCase()}),n=[],t.forEach(function(e){e=e.split(m.tokenizer.seperator);n=n.concat(e)},this),n):e.toString().trim().toLowerCase().split(m.tokenizer.seperator):[];var t,n}).defaultSeperator=/[\s\-]+/,m.tokenizer.seperator=m.tokenizer.defaultSeperator,m.tokenizer.setSeperator=function(e){null!=e&&"object"==typeof e&&(m.tokenizer.seperator=e)},m.tokenizer.resetSeperator=function(){m.tokenizer.seperator=m.tokenizer.defaultSeperator},m.tokenizer.getSeperator=function(){return m.tokenizer.seperator},(m.Pipeline=function(){this._queue=[]}).registeredFunctions={},m.Pipeline.registerFunction=function(e,t){t in m.Pipeline.registeredFunctions&&m.utils.warn("Overwriting existing registered function: "+t),e.label=t,m.Pipeline.registeredFunctions[t]=e},m.Pipeline.getRegisteredFunction=function(e){return e in m.Pipeline.registeredFunctions!=1?null:m.Pipeline.registeredFunctions[e]},m.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||m.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},m.Pipeline.load=function(e){var n=new m.Pipeline;return e.forEach(function(e){var t=m.Pipeline.getRegisteredFunction(e);if(!t)throw new Error("Cannot load un-registered function: "+e);n.add(t)}),n},m.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach(function(e){m.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},m.Pipeline.prototype.after=function(e,t){m.Pipeline.warnIfFunctionNotRegistered(t);e=this._queue.indexOf(e);if(-1===e)throw new Error("Cannot find existingFn");this._queue.splice(e+1,0,t)},m.Pipeline.prototype.before=function(e,t){m.Pipeline.warnIfFunctionNotRegistered(t);e=this._queue.indexOf(e);if(-1===e)throw new Error("Cannot find existingFn");this._queue.splice(e,0,t)},m.Pipeline.prototype.remove=function(e){e=this._queue.indexOf(e);-1!==e&&this._queue.splice(e,1)},m.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,o=this._queue.length,i=0;iu[o]&&o++:(t.add(s[n]),n++,o++);return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){for(var t,e=this.length>=e.length?(t=this,e):(t=e,this),n=t.clone(),o=0,i=e.toArray();o",a=n.querySelector("a"),t=n.querySelector("span:first-child"),d=n.querySelector("span:nth-child(2)"),a.href=e.ref,t.textContent=e.doc.title,d.innerHTML=function(e,t){var n=t.map(function(e){return elasticlunr.stemmer(e.toLowerCase())}),o=!1,i=0,r=[],s=e.toLowerCase().split(". ");for(p in s){var u,a=s[p].split(/[\s\n]/),l=8;for(u in a){if(0<(x=a[u]).length){for(var c in n)elasticlunr.stemmer(x).startsWith(n[c])&&(l=40,o=!0);r.push([x,l,i]),l=2}i=i+x.length+1}i+=1}if(0===r.length)return void 0!==e.length&&300m&&(m=d[p],g=p);for(var y=[],v=r[g][2],p=g;p"),v=x[2]+x[0].length;40!==x[1]&&12<=x[0].length&&!/^[\x00-\xff]+$/.test(x[0])?(S=substringByByte(e.substring(x[2],v),12),y.push(S)):y.push(e.substring(x[2],v)),40===x[1]&&y.push("")}return y.push("…"),y.join("")}(e.doc.body,s),suggestions.appendChild(n))});for(;i.length>r;)suggestions.removeChild(i[0])},!0),suggestions.addEventListener("click",function(){for(;suggestions.lastChild;)suggestions.removeChild(suggestions.lastChild);return!1},!0),document.body.contains(document.goSearch)&&(document.goSearch.onsubmit=function(){return goSearchNow()})}(); \ No newline at end of file diff --git a/abridge-bundle-stork.min.js b/abridge-bundle-stork.min.js new file mode 100644 index 000000000..ec2c45fa0 --- /dev/null +++ b/abridge-bundle-stork.min.js @@ -0,0 +1 @@ +const items=document.querySelectorAll(".preStyle");items.forEach(e=>{e.rel="stylesheet"}),document.getElementById("mode").addEventListener("click",()=>{document.documentElement.classList.toggle("light"),localStorage.setItem("theme",document.documentElement.classList.contains("light")?"light":"dark")}),window.onload=function(){document.getElementById("searchinput").onclick=function(){var e=document.querySelector("meta[name='base']").getAttribute("content"),t=("/"==e.slice(-1)&&(e=e.slice(0,-1)),document.createElement("script"));t.src=e+"/search_bundle_stork.min.js?h=07a791ddc469ec9b7e93fa64a81899b6c12bb3143e8bd0d1aee0b6dacc885b7e",t.setAttribute("integrity","sha384-ePgzx2d0I+A6dkB+OTuOp13dsBEsL9f847ocaay/uDpwIyj0DUwOm7sEB01VpEiL"),t.setAttribute("type","module"),document.head.appendChild(t),document.getElementById("searchinput").onclick=""}},function(){for(var e=document.getElementsByClassName("m-protected"),t=0;tasync function(e,t){var n=t.querySelectorAll("table")["length"];let c="";if(0 tr > td:last-child");a.forEach(e=>{c+=e.innerText})}else c=t.querySelector(":last-child > code").innerText;try{"granted"==(result=await navigator.permissions.query({name:"clipboard-write"})).state||"prompt"==result.state?await navigator.clipboard.writeText(c):o(c,t)}catch(e){o(c,t)}finally{e.innerHTML="Copied",setTimeout(function(){e.innerHTML="Copy"},2e3)}}(t,e)),document.createElement("div"));n.className="ccw",n.appendChild(t),e.parentNode.insertBefore(n,e),n.appendChild(e)}function o(e,t){const n=document.createElement("textArea"),c=(n.contentEditable="true",n.readOnly="false",n.className="copyable-text-area",n.value=e,t.insertBefore(n,t.firstChild),document.createRange()),a=(c.selectNodeContents(n),window.getSelection());a.removeAllRanges(),a.addRange(c),n.setSelectionRange(0,999999),document.execCommand("copy"),t.removeChild(n)}document.querySelectorAll("pre").forEach(e=>t(e))}(); \ No newline at end of file diff --git a/abridge-bundle-tinysearch.min.js b/abridge-bundle-tinysearch.min.js new file mode 100644 index 000000000..2b3cbc906 --- /dev/null +++ b/abridge-bundle-tinysearch.min.js @@ -0,0 +1 @@ +const items=document.querySelectorAll(".preStyle");items.forEach(e=>{e.rel="stylesheet"}),document.getElementById("mode").addEventListener("click",()=>{document.documentElement.classList.toggle("light"),localStorage.setItem("theme",document.documentElement.classList.contains("light")?"light":"dark")}),window.onload=function(){document.getElementById("searchinput").onclick=function(){var e=document.querySelector("meta[name='base']").getAttribute("content"),t=("/"==e.slice(-1)&&(e=e.slice(0,-1)),document.createElement("script"));t.src=e+"/search_bundle_tinysearch.min.js?h=1532d7e7d8292eec3ae8364d3d76029049533141d0674e4a02b1a17986e5f8ef",t.setAttribute("integrity","sha384-POHXtCCwUbHtLT1Hn4+cEysiGJyU7RbnIQKfucRPc9gAquQsFc6j4Zca1HoWo+GS"),t.setAttribute("type","module"),document.head.appendChild(t),document.getElementById("searchinput").onclick=""}},function(){for(var e=document.getElementsByClassName("m-protected"),t=0;tasync function(e,t){var n=t.querySelectorAll("table")["length"];let c="";if(0 tr > td:last-child");o.forEach(e=>{c+=e.innerText})}else c=t.querySelector(":last-child > code").innerText;try{"granted"==(result=await navigator.permissions.query({name:"clipboard-write"})).state||"prompt"==result.state?await navigator.clipboard.writeText(c):a(c,t)}catch(e){a(c,t)}finally{e.innerHTML="Copied",setTimeout(function(){e.innerHTML="Copy"},2e3)}}(t,e)),document.createElement("div"));n.className="ccw",n.appendChild(t),e.parentNode.insertBefore(n,e),n.appendChild(e)}function a(e,t){const n=document.createElement("textArea"),c=(n.contentEditable="true",n.readOnly="false",n.className="copyable-text-area",n.value=e,t.insertBefore(n,t.firstChild),document.createRange()),o=(c.selectNodeContents(n),window.getSelection());o.removeAllRanges(),o.addRange(c),n.setSelectionRange(0,999999),document.execCommand("copy"),t.removeChild(n)}document.querySelectorAll("pre").forEach(e=>t(e))}(); \ No newline at end of file diff --git a/abridge-bundle.min.js b/abridge-bundle.min.js new file mode 100644 index 000000000..56caa4487 --- /dev/null +++ b/abridge-bundle.min.js @@ -0,0 +1 @@ +const items=document.querySelectorAll(".preStyle");items.forEach(e=>{e.rel="stylesheet"}),document.getElementById("mode").addEventListener("click",()=>{document.documentElement.classList.toggle("light"),localStorage.setItem("theme",document.documentElement.classList.contains("light")?"light":"dark")}),window.onload=function(){document.getElementById("searchinput").onclick=function(){var e=document.querySelector("meta[name='base']").getAttribute("content"),t=("/"==e.slice(-1)&&(e=e.slice(0,-1)),document.createElement("script"));t.src=e+"/search_bundle.min.js?h=a5da49e60765868acc42bc230eda18acb050d762201feab3275bd8bf8b87b4e6",t.setAttribute("integrity","sha384-CoyxM6A7vQBhuCq0adbhanggafzE/H35VciKh5wTASR4wKO76duaSRzF0+QEsq8b"),document.head.appendChild(t),document.getElementById("searchinput").onclick=""}},function(){for(var e=document.getElementsByClassName("m-protected"),t=0;tasync function(e,t){var n=t.querySelectorAll("table")["length"];let c="";if(0 tr > td:last-child");a.forEach(e=>{c+=e.innerText})}else c=t.querySelector(":last-child > code").innerText;try{"granted"==(result=await navigator.permissions.query({name:"clipboard-write"})).state||"prompt"==result.state?await navigator.clipboard.writeText(c):o(c,t)}catch(e){o(c,t)}finally{e.innerHTML="Copied",setTimeout(function(){e.innerHTML="Copy"},2e3)}}(t,e)),document.createElement("div"));n.className="ccw",n.appendChild(t),e.parentNode.insertBefore(n,e),n.appendChild(e)}function o(e,t){const n=document.createElement("textArea"),c=(n.contentEditable="true",n.readOnly="false",n.className="copyable-text-area",n.value=e,t.insertBefore(n,t.firstChild),document.createRange()),a=(c.selectNodeContents(n),window.getSelection());a.removeAllRanges(),a.addRange(c),n.setSelectionRange(0,999999),document.execCommand("copy"),t.removeChild(n)}document.querySelectorAll("pre").forEach(e=>t(e))}(); \ No newline at end of file diff --git a/abridge-dark.css b/abridge-dark.css new file mode 100644 index 000000000..0ed9a23b9 --- /dev/null +++ b/abridge-dark.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}.z-code{color:#bfbab0;background-color:#191919}.z-comment,.z-punctuation.z-definition.z-comment{color:#87929f;font-style:italic}.z-variable{color:#bfbab0}.z-string,.z-constant.z-other.z-symbol{color:#c2d94c}.z-constant.z-numeric{color:#f29718}.z-string.z-regexp,.z-constant.z-character.z-escape{color:#95e6cb}.z-constant.z-language{color:#f29718}.z-constant.z-character,.z-constant.z-other{color:#f29718}.z-variable.z-member{color:#fe7d83}.z-keyword,.z-keyword.z-operator.z-word{color:#0bf}.z-keyword.z-operator{color:#f29668}.z-punctuation.z-separator,.z-punctuation.z-terminator{color:#bfbab0}.z-punctuation.z-section{color:#bfbab0}.z-punctuation.z-accessor{color:#f29668}.z-punctuation.z-definition.z-annotation{color:#bfbab0}.z-variable.z-other.z-dollar.z-only.z-js,.z-variable.z-other.z-object.z-dollar.z-only.z-js,.z-variable.z-type.z-dollar.z-only.z-js,.z-support.z-class.z-dollar.z-only.z-js{color:#e6b673}.z-storage{color:#0bf}.z-storage.z-type{color:#0bf}.z-entity.z-name.z-function{color:#ffb454}.z-entity.z-name,.z-entity.z-name.z-tag,.z-entity.z-name.z-label{color:#59c2ff}.z-entity.z-other.z-inherited-class{color:#59c2ff;text-decoration:underline}.z-variable.z-parameter{color:#f29718}.z-variable.z-language{color:#39bae6;font-style:italic}.z-entity.z-name.z-tag,.z-meta.z-tag.z-sgml{color:#39bae6}.z-punctuation.z-definition.z-tag.z-end,.z-punctuation.z-definition.z-tag.z-begin,.z-punctuation.z-definition.z-tag{color:#39bae6}.z-entity.z-other.z-attribute-name{color:#ffb454}.z-variable.z-function,.z-variable.z-annotation{color:#ffb454}.z-support.z-function,.z-support.z-macro{color:#fe7d83}.z-support.z-constant{color:#f29668;font-style:italic}.z-support.z-type,.z-support.z-class{color:#39bae6;font-style:italic}.z-invalid{color:#ff7c6d}.z-invalid.z-deprecated{color:#fff;background-color:#0bf}.z-meta.z-diff,.z-meta.z-diff.z-header{color:#c594c5}.z-source.z-ruby .z-variable.z-other.z-readwrite{color:#ffb454}.z-source.z-css .z-entity.z-name.z-tag,.z-source.z-sass .z-entity.z-name.z-tag,.z-source.z-scss .z-entity.z-name.z-tag,.z-source.z-less .z-entity.z-name.z-tag,.z-source.z-stylus .z-entity.z-name.z-tag{color:#59c2ff}.z-source.z-css .z-support.z-type,.z-source.z-sass .z-support.z-type,.z-source.z-scss .z-support.z-type,.z-source.z-less .z-support.z-type,.z-source.z-stylus .z-support.z-type{color:#798491}.z-support.z-type.z-property-name{color:#39bae6}.z-constant.z-numeric.z-line-number.z-find-in-files{color:#798491}.z-constant.z-numeric.z-line-number.z-match{color:#0bf}.z-entity.z-name.z-filename.z-find-in-files{color:#c2d94c}.z-message.z-error{color:#ff7c6d}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}.z-markup.z-heading{color:#0bf;font-weight:bold}.z-string.z-other.z-link,.z-markup.z-underline.z-link{color:#95e6cb;text-decoration:underline;font-style:italic}.z-punctuation.z-definition.z-image{color:#ffb454}.z-markup.z-italic{color:#fe7d83;font-style:italic}.z-markup.z-bold{color:#fe7d83;font-weight:bold}.z-markup.z-italic .z-markup.z-bold,.z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}.z-markup.z-raw{background-color:#bfbab0}.z-markup.z-raw.z-inline{background-color:#bfbab0}.z-meta.z-separator{color:#798491;background-color:#bfbab0;font-weight:bold}.z-markup.z-quote{color:#f29718;font-style:italic}.z-markup.z-list.z-numbered.z-bullet,.z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#95e6cb}.z-markup.z-inserted{color:#c2d94c}.z-markup.z-changed{color:#39bae6}.z-markup.z-deleted{color:#fe7d83}.z-markup.z-strike{color:#e6b673}.z-markup.z-table{color:#39bae6;background-color:#bfbab0}.z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#f29668}.z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#798491}.z-markup.z-raw.z-block.z-fenced.z-markdown{color:#bfbab0;background-color:#bfbab0}.z-punctuation.z-definition.z-fenced.z-markdown,.z-variable.z-language.z-fenced.z-markdown{color:#798491;background-color:#bfbab0}.z-variable.z-language.z-fenced.z-markdown{color:#798491}.z-markup.z-inserted.z-git_gutter{color:#c2d94c}.z-markup.z-changed.z-git_gutter{color:#39bae6}.z-markup.z-deleted.z-git_gutter{color:#ff7c6d}.z-markup.z-ignored.z-git_gutter{color:#20272c}.z-markup.z-untracked.z-git_gutter{color:#20272c}.z-gutter_color{color:#fff}.z-acejump.z-label.z-blue{color:#fff;background-color:#39bae6}.z-acejump.z-label.z-green{color:#fff;background-color:#c2d94c}.z-acejump.z-label.z-orange{color:#fff;background-color:#0bf}.z-acejump.z-label.z-purple{color:#fff;background-color:#fe7d83}.z-sublimelinter.z-mark.z-warning{color:#39bae6}.z-sublimelinter.z-gutter-mark{color:#fff}.z-sublimelinter.z-mark.z-error{color:#ff7c6d}:root{--f1: #ccc;--f2: #ddd;--c1: #111;--c2: #222;--c3: #333;--c4: #888;--a1: #f90;--a2: #fb0;--a3: #f90;--cg: #593;--cr: #e33} \ No newline at end of file diff --git a/abridge-light.css b/abridge-light.css new file mode 100644 index 000000000..ab87a2aac --- /dev/null +++ b/abridge-light.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}.z-code{color:#50565a;background-color:#fafafa}.z-comment,.z-punctuation.z-definition.z-comment{color:#676c72;font-style:italic}.z-variable{color:#50565a}.z-string,.z-constant.z-other.z-symbol{color:#497700}.z-constant.z-numeric{color:#b04e00}.z-string.z-regexp,.z-constant.z-character.z-escape{color:#007b59}.z-constant.z-language{color:#b04e00}.z-constant.z-character,.z-constant.z-other{color:#b04e00}.z-variable.z-member{color:#c33947}.z-keyword,.z-keyword.z-operator.z-word{color:#0062e8}.z-keyword.z-operator{color:#a4552c}.z-punctuation.z-separator,.z-punctuation.z-terminator{color:#50565a}.z-punctuation.z-section{color:#50565a}.z-punctuation.z-accessor{color:#a4552c}.z-punctuation.z-definition.z-annotation{color:#50565a}.z-variable.z-other.z-dollar.z-only.z-js,.z-variable.z-other.z-object.z-dollar.z-only.z-js,.z-variable.z-type.z-dollar.z-only.z-js,.z-support.z-class.z-dollar.z-only.z-js{color:#8b6426}.z-storage{color:#0062e8}.z-storage.z-type{color:#0062e8}.z-entity.z-name.z-function{color:#a45600}.z-entity.z-name,.z-entity.z-name.z-tag,.z-entity.z-name.z-label{color:#0070b3}.z-entity.z-other.z-inherited-class{color:#0070b3;text-decoration:underline}.z-variable.z-parameter{color:#b04e00}.z-variable.z-language{color:#007492;font-style:italic}.z-entity.z-name.z-tag,.z-meta.z-tag.z-sgml{color:#007492}.z-punctuation.z-definition.z-tag.z-end,.z-punctuation.z-definition.z-tag.z-begin,.z-punctuation.z-definition.z-tag{color:#007492}.z-entity.z-other.z-attribute-name{color:#a45600}.z-variable.z-function,.z-variable.z-annotation{color:#a45600}.z-support.z-function,.z-support.z-macro{color:#b94046}.z-support.z-constant{color:#a4552c;font-style:italic}.z-support.z-type,.z-support.z-class{color:#007492;font-style:italic}.z-invalid{color:#da0001}.z-invalid.z-deprecated{color:#fff;background-color:#0062e8}.z-source.z-ruby .z-variable.z-other.z-readwrite{color:#a45600}.z-source.z-css .z-entity.z-name.z-tag,.z-source.z-sass .z-entity.z-name.z-tag,.z-source.z-scss .z-entity.z-name.z-tag,.z-source.z-less .z-entity.z-name.z-tag,.z-source.z-stylus .z-entity.z-name.z-tag{color:#0070b3}.z-source.z-css .z-support.z-type,.z-source.z-sass .z-support.z-type,.z-source.z-scss .z-support.z-type,.z-source.z-less .z-support.z-type,.z-source.z-stylus .z-support.z-type{color:#676c72}.z-support.z-type.z-property-name{color:#007492}.z-constant.z-numeric.z-line-number.z-find-in-files{color:#676c72}.z-constant.z-numeric.z-line-number.z-match{color:#0062e8}.z-entity.z-name.z-filename.z-find-in-files{color:#497700}.z-message.z-error{color:#da0001}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,.z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}.z-markup.z-heading{color:#0062e8;font-weight:bold}.z-string.z-other.z-link,.z-markup.z-underline.z-link{color:#007b59;text-decoration:underline;font-style:italic}.z-punctuation.z-definition.z-image{color:#a45600}.z-markup.z-italic{color:#b94046;font-style:italic}.z-markup.z-bold{color:#b94046;font-weight:bold}.z-markup.z-italic .z-markup.z-bold,.z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}.z-markup.z-raw{background-color:#50565a}.z-markup.z-raw.z-inline{background-color:#50565a}.z-meta.z-separator{color:#676c72;background-color:#50565a;font-weight:bold}.z-markup.z-quote{color:#b04e00;font-style:italic}.z-markup.z-list.z-numbered.z-bullet,.z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#007b59}.z-markup.z-inserted{color:#497700}.z-markup.z-changed{color:#007492}.z-markup.z-deleted{color:#b94046}.z-markup.z-strike{color:#8b6426}.z-markup.z-table{color:#007492;background-color:#50565a}.z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#a4552c}.z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#676c72}.z-markup.z-raw.z-block.z-fenced.z-markdown{color:#50565a;background-color:#50565a}.z-punctuation.z-definition.z-fenced.z-markdown,.z-variable.z-language.z-fenced.z-markdown{color:#676c72;background-color:#50565a}.z-variable.z-language.z-fenced.z-markdown{color:#676c72}.z-markup.z-inserted.z-git_gutter{color:#497700}.z-markup.z-changed.z-git_gutter{color:#007492}.z-markup.z-deleted.z-git_gutter{color:#da0001}.z-markup.z-ignored.z-git_gutter{color:#696b6c}.z-markup.z-untracked.z-git_gutter{color:#696b6c}.z-gutter_color{color:#fff}.z-acejump.z-label.z-blue{color:#fff;background-color:#007492}.z-acejump.z-label.z-green{color:#fff;background-color:#497700}.z-acejump.z-label.z-orange{color:#fff;background-color:#0062e8}.z-acejump.z-label.z-purple{color:#fff;background-color:#b94046}.z-sublimelinter.z-mark.z-warning{color:#007492}.z-sublimelinter.z-gutter-mark{color:#fff}.z-sublimelinter.z-mark.z-error{color:#da0001}:root{--f1: #444;--f2: #333;--c1: #fff;--c2: #eee;--c3: #ddd;--c4: #677;--a1: #c40;--a2: #e60;--a3: #f90;--cg: #373;--cr: #d33} \ No newline at end of file diff --git a/abridge-searchonly.min.js b/abridge-searchonly.min.js new file mode 100644 index 000000000..6f79f1b0f --- /dev/null +++ b/abridge-searchonly.min.js @@ -0,0 +1 @@ +function closeSearchNow(){const e=document.querySelector("main");e.innerHTML=window.main}function goSearchNow(){const e=document.querySelector("main");window.main||(window.main=e.innerHTML);var t=document.getElementById("suggestions"),n=t.cloneNode(!0),o=(n.id="results",document.createElement("div")),i='

Results For: '.concat(document.getElementById("searchinput").value,"

");return o.innerHTML=i,n.insertBefore(o,n.firstChild),e.innerHTML=n.outerHTML,t.innerHTML="",document.getElementById("searchinput").value="",document.body.contains(document.closeSearch)&&(document.closeSearch.onsubmit=function(){closeSearchNow()}),!1}!function(){function m(e){var t=new m.Index;return t.pipeline.add(m.trimmer,m.stopWordFilter,m.stemmer),e&&e.call(t,t),t}var l,c,e,t,d,h,f,p,g,y,v,S,x,w,b,I,E,D,F,C,_,k,N,L,n;m.version="0.9.5",((lunr=m).utils={}).warn=(n=this,function(e){n.console&&console.warn&&console.warn(e)}),m.utils.toString=function(e){return null==e?"":e.toString()},(m.EventEmitter=function(){this.events={}}).prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop();if("function"!=typeof t)throw new TypeError("last argument must be a function");e.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},m.EventEmitter.prototype.removeListener=function(e,t){this.hasHandler(e)&&-1!==(t=this.events[e].indexOf(t))&&(this.events[e].splice(t,1),0==this.events[e].length&&delete this.events[e])},m.EventEmitter.prototype.emit=function(e){var t;this.hasHandler(e)&&(t=Array.prototype.slice.call(arguments,1),this.events[e].forEach(function(e){e.apply(void 0,t)},this))},m.EventEmitter.prototype.hasHandler=function(e){return e in this.events},(m.tokenizer=function(e){return arguments.length&&null!=e?Array.isArray(e)?(t=(t=e.filter(function(e){return null!=e})).map(function(e){return m.utils.toString(e).toLowerCase()}),n=[],t.forEach(function(e){e=e.split(m.tokenizer.seperator);n=n.concat(e)},this),n):e.toString().trim().toLowerCase().split(m.tokenizer.seperator):[];var t,n}).defaultSeperator=/[\s\-]+/,m.tokenizer.seperator=m.tokenizer.defaultSeperator,m.tokenizer.setSeperator=function(e){null!=e&&"object"==typeof e&&(m.tokenizer.seperator=e)},m.tokenizer.resetSeperator=function(){m.tokenizer.seperator=m.tokenizer.defaultSeperator},m.tokenizer.getSeperator=function(){return m.tokenizer.seperator},(m.Pipeline=function(){this._queue=[]}).registeredFunctions={},m.Pipeline.registerFunction=function(e,t){t in m.Pipeline.registeredFunctions&&m.utils.warn("Overwriting existing registered function: "+t),e.label=t,m.Pipeline.registeredFunctions[t]=e},m.Pipeline.getRegisteredFunction=function(e){return e in m.Pipeline.registeredFunctions!=1?null:m.Pipeline.registeredFunctions[e]},m.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||m.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},m.Pipeline.load=function(e){var n=new m.Pipeline;return e.forEach(function(e){var t=m.Pipeline.getRegisteredFunction(e);if(!t)throw new Error("Cannot load un-registered function: "+e);n.add(t)}),n},m.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach(function(e){m.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},m.Pipeline.prototype.after=function(e,t){m.Pipeline.warnIfFunctionNotRegistered(t);e=this._queue.indexOf(e);if(-1===e)throw new Error("Cannot find existingFn");this._queue.splice(e+1,0,t)},m.Pipeline.prototype.before=function(e,t){m.Pipeline.warnIfFunctionNotRegistered(t);e=this._queue.indexOf(e);if(-1===e)throw new Error("Cannot find existingFn");this._queue.splice(e,0,t)},m.Pipeline.prototype.remove=function(e){e=this._queue.indexOf(e);-1!==e&&this._queue.splice(e,1)},m.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,o=this._queue.length,i=0;iu[o]&&o++:(t.add(s[n]),n++,o++);return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){for(var t,e=this.length>=e.length?(t=this,e):(t=e,this),n=t.clone(),o=0,i=e.toArray();o",a=n.querySelector("a"),t=n.querySelector("span:first-child"),d=n.querySelector("span:nth-child(2)"),a.href=e.ref,t.textContent=e.doc.title,d.innerHTML=function(e,t){var n=t.map(function(e){return elasticlunr.stemmer(e.toLowerCase())}),o=!1,i=0,r=[],s=e.toLowerCase().split(". ");for(p in s){var u,a=s[p].split(/[\s\n]/),l=8;for(u in a){if(0<(x=a[u]).length){for(var c in n)elasticlunr.stemmer(x).startsWith(n[c])&&(l=40,o=!0);r.push([x,l,i]),l=2}i=i+x.length+1}i+=1}if(0===r.length)return void 0!==e.length&&300m&&(m=d[p],g=p);for(var y=[],v=r[g][2],p=g;p"),v=x[2]+x[0].length;40!==x[1]&&12<=x[0].length&&!/^[\x00-\xff]+$/.test(x[0])?(S=substringByByte(e.substring(x[2],v),12),y.push(S)):y.push(e.substring(x[2],v)),40===x[1]&&y.push("")}return y.push("…"),y.join("")}(e.doc.body,s),suggestions.appendChild(n))});for(;i.length>r;)suggestions.removeChild(i[0])},!0),suggestions.addEventListener("click",function(){for(;suggestions.lastChild;)suggestions.removeChild(suggestions.lastChild);return!1},!0),document.body.contains(document.goSearch)&&(document.goSearch.onsubmit=function(){return goSearchNow()})}(); \ No newline at end of file diff --git a/abridge-switcher.css b/abridge-switcher.css new file mode 100644 index 000000000..b113f617f --- /dev/null +++ b/abridge-switcher.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}:root:not(.light) .z-code{color:#bfbab0;background-color:#191919}:root:not(.light) .z-comment,:root:not(.light) .z-punctuation.z-definition.z-comment{color:#87929f;font-style:italic}:root:not(.light) .z-variable{color:#bfbab0}:root:not(.light) .z-string,:root:not(.light) .z-constant.z-other.z-symbol{color:#c2d94c}:root:not(.light) .z-constant.z-numeric{color:#f29718}:root:not(.light) .z-string.z-regexp,:root:not(.light) .z-constant.z-character.z-escape{color:#95e6cb}:root:not(.light) .z-constant.z-language{color:#f29718}:root:not(.light) .z-constant.z-character,:root:not(.light) .z-constant.z-other{color:#f29718}:root:not(.light) .z-variable.z-member{color:#fe7d83}:root:not(.light) .z-keyword,:root:not(.light) .z-keyword.z-operator.z-word{color:#0bf}:root:not(.light) .z-keyword.z-operator{color:#f29668}:root:not(.light) .z-punctuation.z-separator,:root:not(.light) .z-punctuation.z-terminator{color:#bfbab0}:root:not(.light) .z-punctuation.z-section{color:#bfbab0}:root:not(.light) .z-punctuation.z-accessor{color:#f29668}:root:not(.light) .z-punctuation.z-definition.z-annotation{color:#bfbab0}:root:not(.light) .z-variable.z-other.z-dollar.z-only.z-js,:root:not(.light) .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root:not(.light) .z-variable.z-type.z-dollar.z-only.z-js,:root:not(.light) .z-support.z-class.z-dollar.z-only.z-js{color:#e6b673}:root:not(.light) .z-storage{color:#0bf}:root:not(.light) .z-storage.z-type{color:#0bf}:root:not(.light) .z-entity.z-name.z-function{color:#ffb454}:root:not(.light) .z-entity.z-name,:root:not(.light) .z-entity.z-name.z-tag,:root:not(.light) .z-entity.z-name.z-label{color:#59c2ff}:root:not(.light) .z-entity.z-other.z-inherited-class{color:#59c2ff;text-decoration:underline}:root:not(.light) .z-variable.z-parameter{color:#f29718}:root:not(.light) .z-variable.z-language{color:#39bae6;font-style:italic}:root:not(.light) .z-entity.z-name.z-tag,:root:not(.light) .z-meta.z-tag.z-sgml{color:#39bae6}:root:not(.light) .z-punctuation.z-definition.z-tag.z-end,:root:not(.light) .z-punctuation.z-definition.z-tag.z-begin,:root:not(.light) .z-punctuation.z-definition.z-tag{color:#39bae6}:root:not(.light) .z-entity.z-other.z-attribute-name{color:#ffb454}:root:not(.light) .z-variable.z-function,:root:not(.light) .z-variable.z-annotation{color:#ffb454}:root:not(.light) .z-support.z-function,:root:not(.light) .z-support.z-macro{color:#fe7d83}:root:not(.light) .z-support.z-constant{color:#f29668;font-style:italic}:root:not(.light) .z-support.z-type,:root:not(.light) .z-support.z-class{color:#39bae6;font-style:italic}:root:not(.light) .z-invalid{color:#ff7c6d}:root:not(.light) .z-invalid.z-deprecated{color:#fff;background-color:#0bf}:root:not(.light) .z-meta.z-diff,:root:not(.light) .z-meta.z-diff.z-header{color:#c594c5}:root:not(.light) .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#ffb454}:root:not(.light) .z-source.z-css .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-sass .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-scss .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-less .z-entity.z-name.z-tag,:root:not(.light) .z-source.z-stylus .z-entity.z-name.z-tag{color:#59c2ff}:root:not(.light) .z-source.z-css .z-support.z-type,:root:not(.light) .z-source.z-sass .z-support.z-type,:root:not(.light) .z-source.z-scss .z-support.z-type,:root:not(.light) .z-source.z-less .z-support.z-type,:root:not(.light) .z-source.z-stylus .z-support.z-type{color:#798491}:root:not(.light) .z-support.z-type.z-property-name{color:#39bae6}:root:not(.light) .z-constant.z-numeric.z-line-number.z-find-in-files{color:#798491}:root:not(.light) .z-constant.z-numeric.z-line-number.z-match{color:#0bf}:root:not(.light) .z-entity.z-name.z-filename.z-find-in-files{color:#c2d94c}:root:not(.light) .z-message.z-error{color:#ff7c6d}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root:not(.light) .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root:not(.light) .z-markup.z-heading{color:#0bf;font-weight:bold}:root:not(.light) .z-string.z-other.z-link,:root:not(.light) .z-markup.z-underline.z-link{color:#95e6cb;text-decoration:underline;font-style:italic}:root:not(.light) .z-punctuation.z-definition.z-image{color:#ffb454}:root:not(.light) .z-markup.z-italic{color:#fe7d83;font-style:italic}:root:not(.light) .z-markup.z-bold{color:#fe7d83;font-weight:bold}:root:not(.light) .z-markup.z-italic .z-markup.z-bold,:root:not(.light) .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root:not(.light) .z-markup.z-raw{background-color:#bfbab0}:root:not(.light) .z-markup.z-raw.z-inline{background-color:#bfbab0}:root:not(.light) .z-meta.z-separator{color:#798491;background-color:#bfbab0;font-weight:bold}:root:not(.light) .z-markup.z-quote{color:#f29718;font-style:italic}:root:not(.light) .z-markup.z-list.z-numbered.z-bullet,:root:not(.light) .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#95e6cb}:root:not(.light) .z-markup.z-inserted{color:#c2d94c}:root:not(.light) .z-markup.z-changed{color:#39bae6}:root:not(.light) .z-markup.z-deleted{color:#fe7d83}:root:not(.light) .z-markup.z-strike{color:#e6b673}:root:not(.light) .z-markup.z-table{color:#39bae6;background-color:#bfbab0}:root:not(.light) .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#f29668}:root:not(.light) .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#798491}:root:not(.light) .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#bfbab0;background-color:#bfbab0}:root:not(.light) .z-punctuation.z-definition.z-fenced.z-markdown,:root:not(.light) .z-variable.z-language.z-fenced.z-markdown{color:#798491;background-color:#bfbab0}:root:not(.light) .z-variable.z-language.z-fenced.z-markdown{color:#798491}:root:not(.light) .z-markup.z-inserted.z-git_gutter{color:#c2d94c}:root:not(.light) .z-markup.z-changed.z-git_gutter{color:#39bae6}:root:not(.light) .z-markup.z-deleted.z-git_gutter{color:#ff7c6d}:root:not(.light) .z-markup.z-ignored.z-git_gutter{color:#20272c}:root:not(.light) .z-markup.z-untracked.z-git_gutter{color:#20272c}:root:not(.light) .z-gutter_color{color:#fff}:root:not(.light) .z-acejump.z-label.z-blue{color:#fff;background-color:#39bae6}:root:not(.light) .z-acejump.z-label.z-green{color:#fff;background-color:#c2d94c}:root:not(.light) .z-acejump.z-label.z-orange{color:#fff;background-color:#0bf}:root:not(.light) .z-acejump.z-label.z-purple{color:#fff;background-color:#fe7d83}:root:not(.light) .z-sublimelinter.z-mark.z-warning{color:#39bae6}:root:not(.light) .z-sublimelinter.z-gutter-mark{color:#fff}:root:not(.light) .z-sublimelinter.z-mark.z-error{color:#ff7c6d}:root.light .z-code{color:#50565a;background-color:#fafafa}:root.light .z-comment,:root.light .z-punctuation.z-definition.z-comment{color:#676c72;font-style:italic}:root.light .z-variable{color:#50565a}:root.light .z-string,:root.light .z-constant.z-other.z-symbol{color:#497700}:root.light .z-constant.z-numeric{color:#b04e00}:root.light .z-string.z-regexp,:root.light .z-constant.z-character.z-escape{color:#007b59}:root.light .z-constant.z-language{color:#b04e00}:root.light .z-constant.z-character,:root.light .z-constant.z-other{color:#b04e00}:root.light .z-variable.z-member{color:#c33947}:root.light .z-keyword,:root.light .z-keyword.z-operator.z-word{color:#0062e8}:root.light .z-keyword.z-operator{color:#a4552c}:root.light .z-punctuation.z-separator,:root.light .z-punctuation.z-terminator{color:#50565a}:root.light .z-punctuation.z-section{color:#50565a}:root.light .z-punctuation.z-accessor{color:#a4552c}:root.light .z-punctuation.z-definition.z-annotation{color:#50565a}:root.light .z-variable.z-other.z-dollar.z-only.z-js,:root.light .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root.light .z-variable.z-type.z-dollar.z-only.z-js,:root.light .z-support.z-class.z-dollar.z-only.z-js{color:#8b6426}:root.light .z-storage{color:#0062e8}:root.light .z-storage.z-type{color:#0062e8}:root.light .z-entity.z-name.z-function{color:#a45600}:root.light .z-entity.z-name,:root.light .z-entity.z-name.z-tag,:root.light .z-entity.z-name.z-label{color:#0070b3}:root.light .z-entity.z-other.z-inherited-class{color:#0070b3;text-decoration:underline}:root.light .z-variable.z-parameter{color:#b04e00}:root.light .z-variable.z-language{color:#007492;font-style:italic}:root.light .z-entity.z-name.z-tag,:root.light .z-meta.z-tag.z-sgml{color:#007492}:root.light .z-punctuation.z-definition.z-tag.z-end,:root.light .z-punctuation.z-definition.z-tag.z-begin,:root.light .z-punctuation.z-definition.z-tag{color:#007492}:root.light .z-entity.z-other.z-attribute-name{color:#a45600}:root.light .z-variable.z-function,:root.light .z-variable.z-annotation{color:#a45600}:root.light .z-support.z-function,:root.light .z-support.z-macro{color:#b94046}:root.light .z-support.z-constant{color:#a4552c;font-style:italic}:root.light .z-support.z-type,:root.light .z-support.z-class{color:#007492;font-style:italic}:root.light .z-invalid{color:#da0001}:root.light .z-invalid.z-deprecated{color:#fff;background-color:#0062e8}:root.light .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#a45600}:root.light .z-source.z-css .z-entity.z-name.z-tag,:root.light .z-source.z-sass .z-entity.z-name.z-tag,:root.light .z-source.z-scss .z-entity.z-name.z-tag,:root.light .z-source.z-less .z-entity.z-name.z-tag,:root.light .z-source.z-stylus .z-entity.z-name.z-tag{color:#0070b3}:root.light .z-source.z-css .z-support.z-type,:root.light .z-source.z-sass .z-support.z-type,:root.light .z-source.z-scss .z-support.z-type,:root.light .z-source.z-less .z-support.z-type,:root.light .z-source.z-stylus .z-support.z-type{color:#676c72}:root.light .z-support.z-type.z-property-name{color:#007492}:root.light .z-constant.z-numeric.z-line-number.z-find-in-files{color:#676c72}:root.light .z-constant.z-numeric.z-line-number.z-match{color:#0062e8}:root.light .z-entity.z-name.z-filename.z-find-in-files{color:#497700}:root.light .z-message.z-error{color:#da0001}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root.light .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root.light .z-markup.z-heading{color:#0062e8;font-weight:bold}:root.light .z-string.z-other.z-link,:root.light .z-markup.z-underline.z-link{color:#007b59;text-decoration:underline;font-style:italic}:root.light .z-punctuation.z-definition.z-image{color:#a45600}:root.light .z-markup.z-italic{color:#b94046;font-style:italic}:root.light .z-markup.z-bold{color:#b94046;font-weight:bold}:root.light .z-markup.z-italic .z-markup.z-bold,:root.light .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root.light .z-markup.z-raw{background-color:#50565a}:root.light .z-markup.z-raw.z-inline{background-color:#50565a}:root.light .z-meta.z-separator{color:#676c72;background-color:#50565a;font-weight:bold}:root.light .z-markup.z-quote{color:#b04e00;font-style:italic}:root.light .z-markup.z-list.z-numbered.z-bullet,:root.light .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#007b59}:root.light .z-markup.z-inserted{color:#497700}:root.light .z-markup.z-changed{color:#007492}:root.light .z-markup.z-deleted{color:#b94046}:root.light .z-markup.z-strike{color:#8b6426}:root.light .z-markup.z-table{color:#007492;background-color:#50565a}:root.light .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#a4552c}:root.light .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#676c72}:root.light .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#50565a;background-color:#50565a}:root.light .z-punctuation.z-definition.z-fenced.z-markdown,:root.light .z-variable.z-language.z-fenced.z-markdown{color:#676c72;background-color:#50565a}:root.light .z-variable.z-language.z-fenced.z-markdown{color:#676c72}:root.light .z-markup.z-inserted.z-git_gutter{color:#497700}:root.light .z-markup.z-changed.z-git_gutter{color:#007492}:root.light .z-markup.z-deleted.z-git_gutter{color:#da0001}:root.light .z-markup.z-ignored.z-git_gutter{color:#696b6c}:root.light .z-markup.z-untracked.z-git_gutter{color:#696b6c}:root.light .z-gutter_color{color:#fff}:root.light .z-acejump.z-label.z-blue{color:#fff;background-color:#007492}:root.light .z-acejump.z-label.z-green{color:#fff;background-color:#497700}:root.light .z-acejump.z-label.z-orange{color:#fff;background-color:#0062e8}:root.light .z-acejump.z-label.z-purple{color:#fff;background-color:#b94046}:root.light .z-sublimelinter.z-mark.z-warning{color:#007492}:root.light .z-sublimelinter.z-gutter-mark{color:#fff}:root.light .z-sublimelinter.z-mark.z-error{color:#da0001}:root:not(.light){--f1: #ccc;--f2: #ddd;--c1: #111;--c2: #222;--c3: #333;--c4: #888;--a1: #f90;--a2: #fb0;--a3: #f90;--cg: #593;--cr: #e33}:root.light{--f1: #444;--f2: #333;--c1: #fff;--c2: #eee;--c3: #ddd;--c4: #677;--a1: #c40;--a2: #e60;--a3: #f90;--cg: #373;--cr: #d33} \ No newline at end of file diff --git a/abridge.css b/abridge.css new file mode 100644 index 000000000..719015aba --- /dev/null +++ b/abridge.css @@ -0,0 +1 @@ +:root{--ff: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Noto Sans", Helvetica, Arial, sans-serif;--fm: ui-monospace, Menlo, Monaco, Consolas, "SF Mono", "Cascadia Mono", "Segoe UI Mono", "DejaVu Sans Mono", "Liberation Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Ubuntu Mono", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", Courier, monospace;--s1: 1rem;--s2: 1rem;--rc: .5rem;--br: 0.25rem;--bw: 0.0625rem;--ow: 0.1875rem;--fs: 1rem;--lh: 1.5;--lhh: 1.2;--fw: 400;--fh: 700}@media (min-width: 576px){:root{--fs: 1rem}}@media (min-width: 768px){:root{--fs: 1.04rem}}@media (min-width: 992px){:root{--fs: 1.08rem}}@media (min-width: 1200px){:root{--fs: 1.12rem}}*,*::before,*::after{box-sizing:border-box}html{text-rendering:optimizeLegibility;background-color:var(--c1);color:var(--f1);font-family:var(--ff);font-weight:var(--fw);font-size:var(--fs);line-height:var(--lh)}.c{text-align:center}h1,h2,h3,h4,h5,h6{padding-left:0;color:var(--f2);margin-bottom:var(--s1);margin-top:var(--s2);font-weight:var(--fh);font-size:var(--fs);line-height:var(--lhh)}h1{font-size:2rem}h2{font-size:1.75rem}h3{font-size:1.5rem}h4{font-size:1.25rem}h5{font-size:1.125rem}header h1{margin-top:0}a{color:var(--a1);text-decoration:none}a:hover{color:var(--a2);text-decoration:underline}h1 a,h2 a,main nav a{color:var(--f2);text-decoration:none}h1 a:hover,h2 a:hover,main nav a:hover{color:var(--a3);text-decoration:none}article{padding-bottom:.2rem}abbr[title]{border-bottom:var(--bw) dotted;text-decoration:none;cursor:help}mark{background-color:var(--c4);color:var(--c1);vertical-align:baseline;padding:.1rem .4rem}blockquote{margin-left:0;padding:.5rem 0 .5rem 1.5rem;border-left:.25rem solid var(--c3)}blockquote>:last-child{margin-bottom:0}small{font-size:.875rem}.footnote-definition sup,.footnote-definition p{display:inline}sub,sup{font-size:.75em;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin:.7rem 0;color:var(--f1);font-style:normal;font-weight:var(--fw);font-size:var(--fs)}ul,ol{padding-right:0;padding-left:var(--s2)}li{margin-bottom:var(--s1)}ul li{list-style:square}ins{color:var(--cg);text-decoration:none}del{color:var(--cr)}main{display:flex}main article,main div{flex:1 1 0;min-width:0}body{width:100%;margin:0}header,main,footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--s1)}@media (min-width: 1200px){header,main,footer{min-width:1200px;max-width:90%}}header,main{padding-top:0;margin-top:0;padding-bottom:0;margin-bottom:0}header hr,main hr{margin:.1rem 0}footer{line-height:var(--lhh)}footer hr,footer p{margin:.1rem 0 .3rem}main nav a,main nav a:visited{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br);padding:.1rem var(--s1)}main nav a:hover{border-color:var(--a3)}main nav a:hover .svgh{background:var(--a3);opacity:1}header>nav>div:first-of-type{display:inline;min-width:fit-content;padding-right:var(--s1)}header>nav>div:nth-child(2){margin-left:auto;padding-right:var(--s1)}nav>div{margin:var(--s1) 0}nav>div ul,nav>div h2{line-height:1.9;margin:0;padding:0}nav{align-items:center;justify-content:center;display:flex}nav div h2{font-size:1rem}nav div h2:hover{color:var(--a3)}nav h1{margin-bottom:0;margin-top:.2rem}nav li{display:inline-block;margin:0 .3rem}main nav{margin-top:var(--s2)}main nav ul{display:flex;padding-left:0}main nav li{margin:.2rem}main nav li.inp{padding-top:.1rem}.outp{padding:0 .26rem .2rem}.off{color:var(--c4);font-weight:var(--fh);border:.1rem solid var(--c3);border-radius:var(--br)}.off .svgh{background:var(--c3);opacity:1}.on{font-weight:var(--fh);border:.1rem solid var(--c4);border-radius:var(--br)}.mode:hover,.cnav{color:var(--a1)}footer nav ul{margin:0;padding:0}footer nav li{margin:0 .2rem .4rem}@media (max-width: 768px){header nav{display:flex;flex-direction:column}header nav h1{margin:var(--s2) 0 var(--s1)}header nav div{margin:auto}}.yvi{position:absolute;top:0;left:0}.yv{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}img,video,svg{max-width:100%;height:auto}embed,iframe,object{max-width:100%}iframe{border-style:none;width:100%;height:100%;border:0;overflow:hidden}table{border-collapse:collapse;width:100%;text-indent:0;}table caption{margin-bottom:.5rem}tr{border-bottom:var(--bw) solid var(--c3)}td,th{padding:var(--s1)}th{text-align:left}tbody tr:nth-child(even){background-color:var(--c2)}thead tr{border-top:var(--bw) solid var(--c3);background-color:var(--c2)}pre,code,kbd,samp,tt,var{border-radius:var(--br);background:var(--c2);font-family:var(--fm);line-height:initial;font-size:.8rem;padding:.3rem .2rem}pre{display:block;overflow-x:auto;-ms-overflow-style:scrollbar;white-space:pre}pre>code{display:block;background:rgba(0,0,0,0)}kbd{background-color:var(--f2);color:var(--c1);vertical-align:baseline;font-size:1rem;padding:.2rem}hr{box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid var(--f1)}header hr,footer hr{border-top:1px solid var(--c4)}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:var(--s1) 0;color:var(--c4)}button,input,select,textarea{margin:0;padding:.2rem var(--s1);max-width:100%;background:var(--c2);border:0;border-radius:.25rem;font:inherit;line-height:var(--fs);color:var(--f1)}button.del{color:var(--cr)}button,[type=button i],[type=submit i],[type=reset i]{display:inline-block;text-align:center;white-space:nowrap;color:var(--f1);border:0;cursor:pointer;transition:opacity .25s}button:hover,[type=button i]:hover,[type=submit i]:hover,[type=reset i]:hover{opacity:.75}button[disabled],[type=button i][disabled],[type=submit i][disabled],[type=reset i][disabled]{opacity:.5}fieldset{padding:.5rem .75rem;border:var(--bw) solid var(--c3);border-radius:.25rem}legend{padding:0 .25rem}label{cursor:pointer;display:block;margin-bottom:.25rem}select,input:not([size]):not([type=button i]):not([type=submit i]):not([type=reset i]):not([type=checkbox i]):not([type=radio i]){width:100%}[type=color i]{min-height:2.125rem}select:not([multiple]):not([size]){padding-right:1.5rem;background-repeat:no-repeat;background-position:right .5rem center;-moz-appearance:none;-webkit-appearance:none;appearance:none}textarea{width:100%;resize:vertical}textarea:not([rows]){height:8rem}.topout{position:sticky;bottom:1px;padding:20px;place-self:end;margin-top:110vh;pointer-events:none}.topleft{margin-left:calc(100% - 80px)}.top{pointer-events:all;padding:9px;border-radius:9px;font-weight:700;color:var(--a1);background:var(--c2)}.top:hover{text-decoration:none;color:var(--c2);background:var(--a1)}.top:hover .svgh{background:var(--c2);opacity:1}div:empty{display:none}.stork-close-button{display:none}.stork-title p{color:var(--a1);font-weight:var(--fh)}#suggestions{z-index:9;background:var(--c1);border:2px solid var(--c3);position:absolute;right:0;margin-top:var(--s1);width:500px;max-height:500px;overflow:auto}#suggestions a,#results a{display:block;text-decoration:none;padding:var(--s1);margin:0 var(--s1)}#suggestions a:hover,#suggestions a:focus,#results a:hover,#results a:focus{background:var(--c2)}#suggestions span,#results span{line-height:1.5;display:block}#suggestions span:first-child,#results span:first-child{font-weight:var(--fh)}#suggestions span:nth-child(2),#results span:nth-child(2){color:var(--f1)}nav>div>form>div:last-of-type{display:block;position:relative;width:100%}.searchd{display:flex;align-items:center;white-space:nowrap}.searchd>input{max-width:15.3rem;padding-right:2.4rem}.searchd>button{margin-left:-2.4rem}@media (max-width: 768px){.searchd>input{max-width:100%;flex-grow:1}#suggestions{position:static;left:0;width:100%}}main .toc{max-width:15rem;min-width:14rem;margin-left:var(--s1);margin-right:var(--s1)}main .toc-item{padding:.4rem 0;color:var(--f1)}main .toc-item a,main .toc-item-child a{color:var(--f1)}main .toc-item a:hover,main .toc-item-child a:hover{cursor:pointer;color:var(--a2);text-decoration:underline}main .toc-item a.active,main .toc-item-child a.active{color:var(--a2)}main .toc-item-child{padding:0 var(--s1);color:var(--f1)}.toc-sticky{border-radius:var(--br);border-top:5px solid var(--a1);background-color:var(--c2);position:sticky;top:var(--s2);margin-top:var(--s2);padding:0 var(--s2) var(--s2);max-height:100vh;overflow:auto}@media (max-width: 768px){.toc{display:none}}.adjust{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='1' fill='%23000' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C6 0 0 6 0 12s5 12 12 12 12-5 12-12S19 0 12 0Zm0 4c5 0 8 3 8 8s-3 8-8 8V4Z'/%3E%3C/svg%3E");background:var(--f2)}.angl{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m16 4-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angll{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m11 4-8 8 8 8m9-16-8 8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.angr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 4 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angrr{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 4 8 8-8 8m9-16 8 8-8 8'/%3E%3C/svg%3E");background:var(--f2)}.angu{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m4 16 8-8 8 8'/%3E%3C/svg%3E");background:var(--f2)}.search{-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23000' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Ccircle cx='9.5' cy='9.5' r='8'/%3E%3Cpath d='m23 23-9-9'/%3E%3C/svg%3E");background:var(--f2)}.bitbucket{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2328f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M14.2 15.3H9.8L8.7 8.7h6.6ZM2.8 3.2A.7.7 0 0 0 2 4l3.4 16c.1.4.6.8 1 .8h11a.7.7 0 0 0 .6-.6l4-16.1a.7.7 0 0 0-.7-.9Z'/%3E%3C/svg%3E")}.buymeacoffee{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fd0' d='m7.9 11.7.8 8.3c.2 2 .8 2 3.6 2 2.3 0 2.8-.1 3-2l.8-9.3c-3.3-1-4 2-8.2 1z'/%3E%3Cpath fill='%23777' d='M18.8 4.3c-.6-.1-.6-1-.7-1.9-.2-1.6-1.2-2-4-2.2-3-.4-8.6-.2-8.5 1.6 0 1.7 4.8 2.2 9.7 1.6.8-.1.6-1.5-.2-1.4-3.6.5-7.4 0-7.4-.2 0-.3 3.3-.5 5-.4 4.5.3 3.7.3 4.2 2.2.2 1 0 .9-.7 1-3 .3-6 .2-9-.2C4.7 4 4.3 4.4 4 6c-.8 2.7 1 2.8 2.1 3 4.8.7 7.7.3 10.3.2.8-.1.6.5.6 1.2l-1.3 10.8c-.1 1.4-1.4 1.4-4 1.5-2.7.2-3.3-.5-3.5-1.6L7.1 10c-.1-1-1.5-.6-1.4.3l1.1 10.8C7.1 24 9.4 24 12.2 24c2.6 0 4.6-.3 5-3.2l1-11.3c.2-.9.3-.7 1-.9 1.8-.8 1-4.2-.4-4.3zm-.3 3a38 38 0 0 1-12.6.2c-1.4-.2-.9-2 0-1.9 4.5.7 8.7.7 12 0 1.4-.2 1.1 1.7.6 1.8z' /%3E%3C/svg%3E")}.docker{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2329e' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 19.8S7 20 8 18m-4-7h3v3H4Zm3 0h3v3H7Zm3 0h3v3h-3ZM7 8h3v3H7Zm3 0h3v3h-3Zm0-3h3v3h-3Zm10 8c-1 0-1 0-1.4-1.9C18.5 10 17 10 17 12c0 1 0 2-3 2H1a9 9 0 0 0 3 6c3 2 5 2 9 1a10.8 10.8 90 0 0 5-4c1-2 1-1 3-2s1-2 0-2Z'/%3E%3C/svg%3E%0A")}.element{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%231c8' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C5 0 0 6 0 12s6 12 12 12 12-6 12-12A12 12 0 0 0 12 0Zm-1 4c4 0 6 3 6 6 0 2-2 2-2 0s-2-4-4-4-2-2 0-2Zm-7 9c0-4 3-6 6-6 2 0 2 2 0 2s-4 2-4 4-2 2-2 0Zm9 7c-4 0-6-3-6-6 0-2 2-2 2 0s2.4 4 4 4c2 0 2 2 0 2Zm1-3c-2 0-2-2 0-2s4-2 4-4 2-2 2 0c0 4-3 6-6 6Z'/%3E%3C/svg%3E")}.facebook{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23359' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z'/%3E%3C/svg%3E")}.github{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M9 19c-5 1.5-5-2.5-7-3m14 6v-3.9a3.4 3.4 0 0 0-1-2.6c3.2-.3 6.5-1.5 6.5-7A5.4 5.4 0 0 0 20 4.8 5 5 0 0 0 20 1s-1.3-.3-4 1.5a13.4 13.4 0 0 0-7 0C6.3.6 5 1 5 1a5 5 0 0 0 0 3.8 5.4 5.4 0 0 0-1.5 3.7c0 5.5 3.3 6.7 6.4 7a3.4 3.4 0 0 0-.9 2.6V22'/%3E%3C/svg%3E")}.github-sponsor{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23c49' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M20 4c-5-3-8 2-8 4 0-2-3-7-8-4-4 2-6 10 8 18 14-8 12-16 8-18z'/%3E%3C/svg%3E")}.gitlab{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e62' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M22.6 14.4 12 22 1.3 14.4a.8.8 0 0 1-.3-1l1.3-3.7 2.4-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 .1.2L8 9.7h8l2.5-7.5a.4.4 0 0 1 .1-.2.4.4 0 0 1 .6 0 .4.4 0 0 1 0 .2l2.5 7.5 1.3 3.8a.8.8 0 0 1-.3.9z'/%3E%3C/svg%3E")}.instagram{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e07' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Crect x='2' y='2' width='20' height='20' rx='5' ry='5'/%3E%3Cpath d='M16 11.4A4 4 0 1 1 12.6 8a4 4 0 0 1 3.4 3.4zm1.5-4.9h.01'/%3E%3C/svg%3E")}.linkedin{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%2326a' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6zM2 9h4v12H2z'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E")}.mail{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23888' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m22 6-10 7L2 6m2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2Z'/%3E%3C/svg%3E")}.mastodon{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2328c' viewBox='0 0 24 24'%3E%3Cpath d='M2 8c0 5.7-.2 12.6 5 14 2 .6 3.7.7 5 .6 2.4-.1 3.8-.9 3.8-.9l-.1-1.8s-1.7.6-3.7.5c-1.9 0-4-.2-4.2-2.6a5 5 90 0 1 0-.7c4 1 7.5.5 8.4.4 2.7-.4 5-2 5.3-3.6.5-2.4.4-5.8.4-5.8C22 3.4 19 2 19 2 15.9.6 8 .6 5.1 2c0 0-3 1.4-3 6zm4.5-2.3c1.2-1.4 3.8-1.5 5 .3l.5.9.6-1c1.1-1.7 3.7-1.6 4.9-.2 1.1 1.3.9 2.5.9 8.4H16V8.6c0-2.4-3-2.5-3 .3v3h-2V9c0-2.8-3-2.7-3-.3V14H5.6c0-5.9-.2-7.1 1-8.4z'/%3E%3C/svg%3E")}.pinterest{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23b01' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m8 20 4-9m-1.3 3c.4 1.3 1.4 2 2.5 2 2.1 0 3.8-1.6 3.8-4a5 5 0 1 0-9.7 1.7'/%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E")}.python{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2326a' d='M17 6c0 4-1 5-6 5-4 0-5 1-5 6-4 0-5-1-5-6 0-3 1-4.5 4-4.5h7c0-.5 0-.5-1-.5H6c0-3 0-5 6-5 5 0 5 2 5 5ZM9 3C7.5 3 7.5 5 9 5s1.5-2 0-2Z'/%3E%3Cpath fill='%23fc1' d='M23 12c0 3-1 4.6-4 4.5h-7v.5h6c0 4 0 6-6 6-5 0-5-2-5-6s1-5 6-5c4 0 5-1 5-6 4 0 5 1 5 6Zm-8 7c-1.5 0-1.5 2 0 2s1.5-2 0-2Z' /%3E%3C/svg%3E")}.researchgate{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='none' stroke-width='2' fill='%230db' viewBox='0 0 24 24'%3E%3Cpath d='M16 5c0 3.5.7 5 3 5s3.7-1.3 3.3-5h-3v1.3H21c0 1.9-.7 2.7-2 2.5-1.3 0-1.8-.7-1.8-3.2 0-2.4.4-3.3 1.5-3.4 1-.2 1.7.2 2.2 1.1L22 3c-.4-1.3-1.4-2-2.9-2C17.2 1 16 2 16 5ZM8 6.2l-6 .2v.9c1 .3 2 0 2 2.2v11C4 22 3 22 2 22.2v.8h6.6v-.8C7 22 6 22 6 20.5v-5.2h2a46 46 0 0 0 4 5.7 5 5 0 0 0 5 2v-1c-3 0-5-5-7-7 6-1 6-10-2-8.8ZM6 14V7.6C14 6 13 14 8 14Z'/%3E%3C/svg%3E")}.rss{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e94' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16'/%3E%3Ccircle cx='5' cy='19' r='1'/%3E%3C/svg%3E")}.stack{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23e72' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M4 17v1a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-1M8 16h8m-7.7-3.4 8 .8M8.8 9.2l7.8 1.6m-6.5-5 7.6 2.4'/%3E%3C/svg%3E")}.twitch{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23a7f' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7'/%3E%3C/svg%3E")}.twitter{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%232ad' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M23 3a10.9 10.9 0 0 1-3.1 1.5 4.5 4.5 0 0 0-7.9 3v1A10.7 10.7 0 0 1 3 4s-4 9 5 13a11.6 11.6 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0 0-.8A7.7 7.7 0 0 0 23 3z'/%3E%3C/svg%3E")}.x{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='3' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='M21 3 3 21M3 3l18 18'/%3E%3C/svg%3E")}.youtube{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23f00' stroke-width='2' fill='none' viewBox='0 0 24 24'%3E%3Cpath d='m9.8 15 5.7-3.3-5.8-3.2V15Zm12.7-8.6a2.8 2.8 0 0 0-1.9-2C18.9 4 12 4 12 4s-6.9 0-8.6.5a2.8 2.8 0 0 0-2 2 29 29 0 0 0-.4 5.3 29 29 0 0 0 .5 5.3A2.8 2.8 0 0 0 3.4 19c1.7.5 8.6.5 8.6.5s6.9 0 8.6-.5a2.8 2.8 0 0 0 2-2 29 29 0 0 0 .4-5.3 29 29 0 0 0-.5-5.3z'/%3E%3C/svg%3E")}.svg{width:1.8rem;height:1.8rem;display:inline-block;text-align:center;vertical-align:middle}.svgs{width:var(--fs);height:var(--fs);display:inline-block;text-align:center;vertical-align:middle}.fa-a:hover{color:var(--a3);opacity:1}.sum,.sum p{margin:.2rem 0}.s95{font-size:.95em}.s90{font-size:.9em}.s85{font-size:.85em}.s80{font-size:.8em}.s75{font-size:.75em}.s70{font-size:.7em}.hpad{padding:0 .2rem}.rpad{padding-right:.2rem}.si{font-size:1.5em}pre code[data-lang]::before{color:var(--f1);text-transform:uppercase;content:" [" attr(data-lang) "] " " "}.ccw{position:relative}.ccw:hover .cc{opacity:1}.cc{opacity:0;z-index:9;position:absolute;right:9px;top:9px;font-size:.8rem}:root:not(.light) code table mark{filter:brightness(120%)}code table{font-size:.8rem;margin:0}code table mark{display:block;background-color:var(--c2);color:unset;padding:0}code td,code th,code tr{padding:0;border-bottom:none}code tbody td:first-child{text-align:center;user-select:none;min-width:60px}code tbody tr:nth-child(even),code thead tr{background-color:unset}:root .z-code{color:#bfbab0;background-color:#191919}:root .z-comment,:root .z-punctuation.z-definition.z-comment{color:#87929f;font-style:italic}:root .z-variable{color:#bfbab0}:root .z-string,:root .z-constant.z-other.z-symbol{color:#c2d94c}:root .z-constant.z-numeric{color:#f29718}:root .z-string.z-regexp,:root .z-constant.z-character.z-escape{color:#95e6cb}:root .z-constant.z-language{color:#f29718}:root .z-constant.z-character,:root .z-constant.z-other{color:#f29718}:root .z-variable.z-member{color:#fe7d83}:root .z-keyword,:root .z-keyword.z-operator.z-word{color:#0bf}:root .z-keyword.z-operator{color:#f29668}:root .z-punctuation.z-separator,:root .z-punctuation.z-terminator{color:#bfbab0}:root .z-punctuation.z-section{color:#bfbab0}:root .z-punctuation.z-accessor{color:#f29668}:root .z-punctuation.z-definition.z-annotation{color:#bfbab0}:root .z-variable.z-other.z-dollar.z-only.z-js,:root .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root .z-variable.z-type.z-dollar.z-only.z-js,:root .z-support.z-class.z-dollar.z-only.z-js{color:#e6b673}:root .z-storage{color:#0bf}:root .z-storage.z-type{color:#0bf}:root .z-entity.z-name.z-function{color:#ffb454}:root .z-entity.z-name,:root .z-entity.z-name.z-tag,:root .z-entity.z-name.z-label{color:#59c2ff}:root .z-entity.z-other.z-inherited-class{color:#59c2ff;text-decoration:underline}:root .z-variable.z-parameter{color:#f29718}:root .z-variable.z-language{color:#39bae6;font-style:italic}:root .z-entity.z-name.z-tag,:root .z-meta.z-tag.z-sgml{color:#39bae6}:root .z-punctuation.z-definition.z-tag.z-end,:root .z-punctuation.z-definition.z-tag.z-begin,:root .z-punctuation.z-definition.z-tag{color:#39bae6}:root .z-entity.z-other.z-attribute-name{color:#ffb454}:root .z-variable.z-function,:root .z-variable.z-annotation{color:#ffb454}:root .z-support.z-function,:root .z-support.z-macro{color:#fe7d83}:root .z-support.z-constant{color:#f29668;font-style:italic}:root .z-support.z-type,:root .z-support.z-class{color:#39bae6;font-style:italic}:root .z-invalid{color:#ff7c6d}:root .z-invalid.z-deprecated{color:#fff;background-color:#0bf}:root .z-meta.z-diff,:root .z-meta.z-diff.z-header{color:#c594c5}:root .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#ffb454}:root .z-source.z-css .z-entity.z-name.z-tag,:root .z-source.z-sass .z-entity.z-name.z-tag,:root .z-source.z-scss .z-entity.z-name.z-tag,:root .z-source.z-less .z-entity.z-name.z-tag,:root .z-source.z-stylus .z-entity.z-name.z-tag{color:#59c2ff}:root .z-source.z-css .z-support.z-type,:root .z-source.z-sass .z-support.z-type,:root .z-source.z-scss .z-support.z-type,:root .z-source.z-less .z-support.z-type,:root .z-source.z-stylus .z-support.z-type{color:#798491}:root .z-support.z-type.z-property-name{color:#39bae6}:root .z-constant.z-numeric.z-line-number.z-find-in-files{color:#798491}:root .z-constant.z-numeric.z-line-number.z-match{color:#0bf}:root .z-entity.z-name.z-filename.z-find-in-files{color:#c2d94c}:root .z-message.z-error{color:#ff7c6d}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#39bae6}:root .z-markup.z-heading{color:#0bf;font-weight:bold}:root .z-string.z-other.z-link,:root .z-markup.z-underline.z-link{color:#95e6cb;text-decoration:underline;font-style:italic}:root .z-punctuation.z-definition.z-image{color:#ffb454}:root .z-markup.z-italic{color:#fe7d83;font-style:italic}:root .z-markup.z-bold{color:#fe7d83;font-weight:bold}:root .z-markup.z-italic .z-markup.z-bold,:root .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root .z-markup.z-raw{background-color:#bfbab0}:root .z-markup.z-raw.z-inline{background-color:#bfbab0}:root .z-meta.z-separator{color:#798491;background-color:#bfbab0;font-weight:bold}:root .z-markup.z-quote{color:#f29718;font-style:italic}:root .z-markup.z-list.z-numbered.z-bullet,:root .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#95e6cb}:root .z-markup.z-inserted{color:#c2d94c}:root .z-markup.z-changed{color:#39bae6}:root .z-markup.z-deleted{color:#fe7d83}:root .z-markup.z-strike{color:#e6b673}:root .z-markup.z-table{color:#39bae6;background-color:#bfbab0}:root .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#f29668}:root .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#798491}:root .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#bfbab0;background-color:#bfbab0}:root .z-punctuation.z-definition.z-fenced.z-markdown,:root .z-variable.z-language.z-fenced.z-markdown{color:#798491;background-color:#bfbab0}:root .z-variable.z-language.z-fenced.z-markdown{color:#798491}:root .z-markup.z-inserted.z-git_gutter{color:#c2d94c}:root .z-markup.z-changed.z-git_gutter{color:#39bae6}:root .z-markup.z-deleted.z-git_gutter{color:#ff7c6d}:root .z-markup.z-ignored.z-git_gutter{color:#20272c}:root .z-markup.z-untracked.z-git_gutter{color:#20272c}:root .z-gutter_color{color:#fff}:root .z-acejump.z-label.z-blue{color:#fff;background-color:#39bae6}:root .z-acejump.z-label.z-green{color:#fff;background-color:#c2d94c}:root .z-acejump.z-label.z-orange{color:#fff;background-color:#0bf}:root .z-acejump.z-label.z-purple{color:#fff;background-color:#fe7d83}:root .z-sublimelinter.z-mark.z-warning{color:#39bae6}:root .z-sublimelinter.z-gutter-mark{color:#fff}:root .z-sublimelinter.z-mark.z-error{color:#ff7c6d}@media (prefers-color-scheme: light){:root .z-code{color:#50565a;background-color:#fafafa}:root .z-comment,:root .z-punctuation.z-definition.z-comment{color:#676c72;font-style:italic}:root .z-variable{color:#50565a}:root .z-string,:root .z-constant.z-other.z-symbol{color:#497700}:root .z-constant.z-numeric{color:#b04e00}:root .z-string.z-regexp,:root .z-constant.z-character.z-escape{color:#007b59}:root .z-constant.z-language{color:#b04e00}:root .z-constant.z-character,:root .z-constant.z-other{color:#b04e00}:root .z-variable.z-member{color:#c33947}:root .z-keyword,:root .z-keyword.z-operator.z-word{color:#0062e8}:root .z-keyword.z-operator{color:#a4552c}:root .z-punctuation.z-separator,:root .z-punctuation.z-terminator{color:#50565a}:root .z-punctuation.z-section{color:#50565a}:root .z-punctuation.z-accessor{color:#a4552c}:root .z-punctuation.z-definition.z-annotation{color:#50565a}:root .z-variable.z-other.z-dollar.z-only.z-js,:root .z-variable.z-other.z-object.z-dollar.z-only.z-js,:root .z-variable.z-type.z-dollar.z-only.z-js,:root .z-support.z-class.z-dollar.z-only.z-js{color:#8b6426}:root .z-storage{color:#0062e8}:root .z-storage.z-type{color:#0062e8}:root .z-entity.z-name.z-function{color:#a45600}:root .z-entity.z-name,:root .z-entity.z-name.z-tag,:root .z-entity.z-name.z-label{color:#0070b3}:root .z-entity.z-other.z-inherited-class{color:#0070b3;text-decoration:underline}:root .z-variable.z-parameter{color:#b04e00}:root .z-variable.z-language{color:#007492;font-style:italic}:root .z-entity.z-name.z-tag,:root .z-meta.z-tag.z-sgml{color:#007492}:root .z-punctuation.z-definition.z-tag.z-end,:root .z-punctuation.z-definition.z-tag.z-begin,:root .z-punctuation.z-definition.z-tag{color:#007492}:root .z-entity.z-other.z-attribute-name{color:#a45600}:root .z-variable.z-function,:root .z-variable.z-annotation{color:#a45600}:root .z-support.z-function,:root .z-support.z-macro{color:#b94046}:root .z-support.z-constant{color:#a4552c;font-style:italic}:root .z-support.z-type,:root .z-support.z-class{color:#007492;font-style:italic}:root .z-invalid{color:#da0001}:root .z-invalid.z-deprecated{color:#fff;background-color:#0062e8}:root .z-source.z-ruby .z-variable.z-other.z-readwrite{color:#a45600}:root .z-source.z-css .z-entity.z-name.z-tag,:root .z-source.z-sass .z-entity.z-name.z-tag,:root .z-source.z-scss .z-entity.z-name.z-tag,:root .z-source.z-less .z-entity.z-name.z-tag,:root .z-source.z-stylus .z-entity.z-name.z-tag{color:#0070b3}:root .z-source.z-css .z-support.z-type,:root .z-source.z-sass .z-support.z-type,:root .z-source.z-scss .z-support.z-type,:root .z-source.z-less .z-support.z-type,:root .z-source.z-stylus .z-support.z-type{color:#676c72}:root .z-support.z-type.z-property-name{color:#007492}:root .z-constant.z-numeric.z-line-number.z-find-in-files{color:#676c72}:root .z-constant.z-numeric.z-line-number.z-match{color:#0062e8}:root .z-entity.z-name.z-filename.z-find-in-files{color:#497700}:root .z-message.z-error{color:#da0001}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-string.z-quoted.z-double.z-json,:root .z-source.z-json .z-meta.z-structure.z-dictionary.z-json .z-punctuation.z-definition.z-string{color:#007492}:root .z-markup.z-heading{color:#0062e8;font-weight:bold}:root .z-string.z-other.z-link,:root .z-markup.z-underline.z-link{color:#007b59;text-decoration:underline;font-style:italic}:root .z-punctuation.z-definition.z-image{color:#a45600}:root .z-markup.z-italic{color:#b94046;font-style:italic}:root .z-markup.z-bold{color:#b94046;font-weight:bold}:root .z-markup.z-italic .z-markup.z-bold,:root .z-markup.z-bold .z-markup.z-italic{font-weight:bold;font-style:italic}:root .z-markup.z-raw{background-color:#50565a}:root .z-markup.z-raw.z-inline{background-color:#50565a}:root .z-meta.z-separator{color:#676c72;background-color:#50565a;font-weight:bold}:root .z-markup.z-quote{color:#b04e00;font-style:italic}:root .z-markup.z-list.z-numbered.z-bullet,:root .z-markup.z-list .z-punctuation.z-definition.z-list_item{color:#007b59}:root .z-markup.z-inserted{color:#497700}:root .z-markup.z-changed{color:#007492}:root .z-markup.z-deleted{color:#b94046}:root .z-markup.z-strike{color:#8b6426}:root .z-markup.z-table{color:#007492;background-color:#50565a}:root .z-text.z-html.z-markdown .z-markup.z-raw.z-inline{color:#a4552c}:root .z-text.z-html.z-markdown .z-meta.z-dummy.z-line-break{color:#676c72}:root .z-markup.z-raw.z-block.z-fenced.z-markdown{color:#50565a;background-color:#50565a}:root .z-punctuation.z-definition.z-fenced.z-markdown,:root .z-variable.z-language.z-fenced.z-markdown{color:#676c72;background-color:#50565a}:root .z-variable.z-language.z-fenced.z-markdown{color:#676c72}:root .z-markup.z-inserted.z-git_gutter{color:#497700}:root .z-markup.z-changed.z-git_gutter{color:#007492}:root .z-markup.z-deleted.z-git_gutter{color:#da0001}:root .z-markup.z-ignored.z-git_gutter{color:#696b6c}:root .z-markup.z-untracked.z-git_gutter{color:#696b6c}:root .z-gutter_color{color:#fff}:root .z-acejump.z-label.z-blue{color:#fff;background-color:#007492}:root .z-acejump.z-label.z-green{color:#fff;background-color:#497700}:root .z-acejump.z-label.z-orange{color:#fff;background-color:#0062e8}:root .z-acejump.z-label.z-purple{color:#fff;background-color:#b94046}:root .z-sublimelinter.z-mark.z-warning{color:#007492}:root .z-sublimelinter.z-gutter-mark{color:#fff}:root .z-sublimelinter.z-mark.z-error{color:#da0001}}:root{--f1: #ccc;--f2: #ddd;--c1: #111;--c2: #222;--c3: #333;--c4: #888;--a1: #f90;--a2: #fb0;--a3: #f90;--cg: #593;--cr: #e33}@media (prefers-color-scheme: light){:root{--f1: #444;--f2: #333;--c1: #fff;--c2: #eee;--c3: #ddd;--c4: #677;--a1: #c40;--a2: #e60;--a3: #f90;--cg: #373;--cr: #d33}} \ No newline at end of file diff --git a/android-chrome-192x192.png b/android-chrome-192x192.png new file mode 100644 index 000000000..1461945c1 Binary files /dev/null and b/android-chrome-192x192.png differ diff --git a/android-chrome-192x192m.png b/android-chrome-192x192m.png new file mode 100644 index 000000000..f7e37a23c Binary files /dev/null and b/android-chrome-192x192m.png differ diff --git a/android-chrome-512x512.png b/android-chrome-512x512.png new file mode 100644 index 000000000..f859fdf8d Binary files /dev/null and b/android-chrome-512x512.png differ diff --git a/apple-touch-icon.png b/apple-touch-icon.png new file mode 100644 index 000000000..31e01b120 Binary files /dev/null and b/apple-touch-icon.png differ diff --git a/authors/index.html b/authors/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/authors/jeff-banks/index.html b/authors/jeff-banks/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/auto-render.min.js b/auto-render.min.js new file mode 100644 index 000000000..c169ec639 --- /dev/null +++ b/auto-render.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var a=r[e];if(void 0!==a)return a.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var a={};return function(){n.d(a,{default:function(){return s}});var e=n(771),t=n.n(e),r=function(e,t,r){for(var n=r,a=0,i=e.length;n0&&(a.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=i.test(d)?d:e.slice(t[l].left.length,n);a.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&a.push({type:"text",data:e}),a},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var a=document.createDocumentFragment(),i=0;i + + + + + + + + + + + + + + + CQL Starter | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

CQL-Starter

+cql-starter +

Author: Jeff Banks (DataStax)

+

 

+

Introduction

+

Welcome to the NoSQLBench Quick Byte, the first session in a “Getting Started” series for +NoSQLBench. This session introduces a new Cassandra Query Language (CQL) starter workload now +available in version 5 of NoSQLBench.

+
    +
  • If you haven't heard of NoSQLBench, checkout our introduction material
  • +
  • If you already have a foundation with NoSQLBench and would like to understand what's included +in the most recent version, checkout the release notes.
  • +
+

This session illustrates use of CQL, using NoSQLBench v5, along with a Docker deployment of +Apache Cassandra 4.1 using its latest image.

+

Let’s get rolling …

+

Setup

+

This session was tested with:

+
    +
  • Ubuntu (v20.4)
  • +
  • Docker (v20.10.18)
  • +
  • NoSQLBench (v5.17.2)
  • +
  • Apache Cassandra (v4.1)
  • +
+

Install Docker

+

Ensure Docker is installed on your operating system. You can download it from +here

+

Get NB5

+

Obtain official NB5 release, if you don't already have it, from +latest nb5 release, +and then chmod +x nb5.

+

See get nosqlbench for other download options.

+

You should be able to see your version installed using:

+
./nb5 --version
+
+

Run Cassandra

+

Run the latest Cassandra 4.* docker.

+
docker run --name cass4 -p 9042:9042 -d cassandra
+
+

If you have issues, more details can be found at +Apache Cassandra on docker hub.

+

Verify Cassandra is started from logs:

+
docker container logs cass4
+
+

Running the scenario

+

Now, we are ready to run the cql-starter NoSQLBench scenario.

+

Locate NB5

+

Navigate via your local command line to where the nb5 binary was previously downloaded.

+

Verify

+

Ensure that issuing the following command identifies the workload used for this session.

+
./nb5 --list-workloads | grep cql-starter
+
+

Example output:

+
/activities/baselines/cql-starter.yaml
+
+

Optional step

+

An alternative is to copy the workload configuration listed below to your own local file in a +folder of your choosing. You can name it whatever you like, as you will specify the absolute +file path directly when issuing the scenario command.

+

CQL workload template

+

This YAML file is designed as a basic foundation for continuing to learn NoSQLBench +capabilities as well as a starting point for customizing for your own testing needs.

+

You will notice that the number of cycles are minimal to support local testing to ensure that +your configuration is constructed properly. When customizing these for real-world tests, the +values can be set to millions or more! That is where the full power of NoSQLBench shines to +generate critical metrics for analysis to make a system more robust.

+

+description: >2
+ A cql-starter workload.
+ * Cassandra: 3.x, 4.x.
+ * DataStax Enterprise: 6.8.x.
+ * DataStax Astra.
+
+scenarios:
+ default:
+   schema: run driver=cql tags==block:schema threads==1 cycles==UNDEF
+   rampup: run driver=cql tags==block:rampup cycles===TEMPLATE(rampup-cycles,1) threads=auto
+   main: run driver=cql tags==block:"main.*" cycles===TEMPLATE(main-cycles,10) threads=auto
+   # rampdown: run driver=cql tags==block:rampdown threads==1 cycles==UNDEF
+ astra:
+   schema: run driver=cql tags==block:schema-astra threads==1 cycles==UNDEF
+   rampup: run driver=cql tags==block:rampup cycles===TEMPLATE(rampup-cycles,10) threads=auto
+   main: run driver=cql tags==block:"main.*" cycles===TEMPLATE(main-cycles,10) threads=auto
+
+params:
+ a_param: "value"
+
+bindings:
+ machine_id: ElapsedNanoTime(); ToHashedUUID() -> java.util.UUID
+ message: Discard(); TextOfFile('data/cql-starter-message.txt');
+ rampup_message: ToString();
+ time: ElapsedNanoTime(); Mul(1000); ToJavaInstant();
+ ts: ElapsedNanoTime(); Mul(1000);
+
+blocks: 
+ schema:
+   params:
+     prepared: false
+   ops:
+     create-keyspace: |
+       create keyspace if not exists <<keyspace:starter>>
+       WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '<<rf:1>>'}
+       AND durable_writes = true;
+     create-table: |
+       create table if not exists <<keyspace:starter>>.<<table:cqlstarter>> (
+       machine_id UUID, 
+       message text,   
+       time timestamp,         
+       PRIMARY KEY ((machine_id), time)
+       ) WITH CLUSTERING ORDER BY (time DESC);
+
+ schema-astra:
+   params:
+     prepared: false
+   ops:
+     create-table-astra: |
+       create table if not exists <<keyspace:starter>>.<<table:cqlstarter>> (
+       machine_id UUID,
+       message text,
+       time timestamp,
+       PRIMARY KEY ((machine_id), time)
+       ) WITH CLUSTERING ORDER BY (time DESC);
+
+ rampup:
+   params:
+     cl: <<write_cl:LOCAL_QUORUM>>
+     idempotent: true
+   ops:
+     insert-rampup: |
+       insert into  <<keyspace:starter>>.<<table:cqlstarter>> (machine_id, message, time)
+       values ({machine_id}, {rampup_message}, {time}) using timestamp {ts};
+
+ rampdown:
+   ops:
+     truncate-table: |
+       truncate table <<keyspace:starter>>.<<table:cqlstarter>>;
+
+ main-read:
+   params:
+     ratio: <<read_ratio:1>>
+     cl: <<read_cl:LOCAL_QUORUM>>
+   ops:
+     select-read: |
+       select * from <<keyspace:starter>>.<<table:cqlstarter>>
+       where machine_id={machine_id};
+ main-write:
+   params:
+     ratio: <<write_ratio:9>>
+     cl: <<write_cl:LOCAL_QUORUM>>
+     idempotent: true
+   ops:
+     insert-main: |
+       insert into <<keyspace:starter>>.<<table:cqlstarter>>
+       (machine_id, message, time) values ({machine_id}, {message}, {time}) using timestamp {ts};
+
+

Before running NoSQLBench scenario, let’s take a look at the layout of the file. Most of this +will be the same layout structure used in all NB5 workload files so this helps to reveal a +large amount of the basics. This is called a workload template.

+

Starting from the top of the workload template, the primary sections include:

+
    +
  • Description - A way to describe what the workload does.
  • +
  • Scenarios - A set of named scenarios for detailing the intent of the workload and defines that for various blocks (e.g. schema, rampup, main, etc.).
  • +
  • Params - Optional parameters of interest to reference for applying values.
  • +
  • Bindings - Named recipes for generated data. These are referenced in block operations.
  • +
  • Blocks - Where the labeled operations reside (e.g. schema, rampup, and main). +
      +
    • Schema - A block section where the schema is actually defined and created.
    • +
    • Rampup - A block section for data setup that becomes the backdrop for testing; it’s the density of data outside the metrics collected in the main block.
    • +
    • Main - A block section that is the target of metrics collection activities.
    • +
    +
  • +
+

This may look overwhelming at first glance, but the magic of what can be done for load testing target resources becomes more apparent as settings are tweaked for various test cases.

+

Basic Operations

+

The workload operations in the cql-starter are quite basic, and this is on purpose. The intent +is to focus on a simple set of read and write operations to understand how to work with +NoSQLBench and Cassandra using basic, direct CQL.

+

Table and Keyspace

+

For the default scenario workload, a simple table named ‘cqlstarter’ will be created with a keyspace +named ‘starter’. There will be three fields for our table:

+
    +
  • machine_id
  • +
  • message
  • +
  • time
  • +
+

The machine_id is a unique identifier type, the message field is a text type, and the time is a +timestamp type.

+

Since the example is designed to be run locally, the Cassandra keyspace replication is defined +using a SimpleStrategy with a replication factor of one.

+
WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '<<rf:1>>'}
+
+

Default scenario

+

For this session, the ‘default’ scenario is being used.

+
    
+    scenarios:
+      default:
+        schema: run driver=cql tags==block:schema …
+        rampup: run driver=cql tags==block:rampup …
+        main: run driver=cql tags==block:"main.*" …
+
+

One may notice there is an ‘astra’ scenario included in the file with its own set of activities +defined (e.g. -astra). References to astra are simply there to show how additional +scenarios can be defined in a single workload file.

+
    
+    astra:
+      schema: run driver=cql tags==block:schema-astra threads==1 cycles==UNDEF      
+
+

This illustrates how flexible and customizable the workload file can become. The words are +customizable and can be tailored for understanding the test case for any business or technical domain.

+

Bindings

+

Values for our three fields during insert, will come from the bindings section of the file.
+Basic examples are included in the cql-starter, but this illustrates how bindings supply +values to be used by operations. Again, these are basic, just to illustrate how binding +functions can be utilized.

+

+    
+    bindings:
+      machine_id: ElapsedNanoTime(); ToHashedUUID() -> java.util.UUID
+      message: Discard(); TextOfFile('data/cql-starter-message.txt');
+      rampup_message: ToString();
+      time: ElapsedNanoTime(); Mul(1000); ToJavaInstant();
+      ts: ElapsedNanoTime(); Mul(1000);
+
+

Notice how we can reference text from a file to be used for our message value. Nothing fancy, +but illustrates how tests can leverage external information from files for decoupling input +from the workload file itself. Think of this for things like secret token references, etc. +that need to be referenced.

+
Discard(); TextOfFile('data/cql-starter-message.txt')
+
+

Note: The Discard() function is used to indicate a no-op as the initial message value. This +may change in the future, but for now it is a necessity due to the nature of bindings +defaulting to Long values. This is why the rampup_message was included for illustration as it uses a +ToString(); function assigning a string value. By default, the binding's value is 0L.

+

Hands on

+

Let’s run the cql-starter.

+

Running

+

Using the nb5 binary, issue the following command

+
./nb5 activities/baselines/cql-starter.yaml default hosts=localhost localdc=datacenter1
+
+

This command identifies that the default scenario workload is used with the key-value args passed along +for use by the cqld4 adapter.

+

Examine the results

+

After the workload has been run, let’s take a look at the results from Cassandra itself using cqlsh.

+
docker container exec -it cass4 sh
+cqlsh
+select * from starter.cqlstarter;
+
+

You should see the single rampup entry along main operation entries in the Cassandra table.

+

Customize

+

Now, let’s customize the cql-starter to make it a bit more your own.

+

Save the .yaml file to your local environment.

+

One easy way, is to utilize the nb5 --copy command.

+
./nb5 --copy cql-starter
+
+

This provides a fresh workload file for you for cql-starter.

+

Edit the file and uncomment under the default scenario the following entry:

+
# rampdown: run driver=cql tags==block:rampdown threads==1 cycles==UNDEF
+
+

When you want to customize the cql-starter, you can simply target the file outside the +NB5 distribution using:

+
./nb5 adapter-cqld4/<rel-path-to-customized-file>.yaml default hosts=localhost localdc=datacenter1
+
+

Also, if you would like to see more details in the output, add (-v, -vv, or -vvv) to the command.

+
./nb5 adapter-cqld4/<rel-path-to-customized-file>.yaml default hosts=localhost localdc=datacenter1 -v
+
+

When the workload is run after uncommenting the rampdown, selecting the content again using +cqlsh, returns a table that has been truncated.

+

Next Steps

+

Checkout the NoSQLBench getting started section and details for its +capabilities for your next testing initiative. This includes a number of +built-in workloads that you can start from for more +advanced scenarios.

+

Want to contribute?

+

It’s worth mentioning, NoSQLBench is open source and we are looking for contributions to expand +its features! Head on over to the contributions +page to find out more.

+

We will continue to have more Quick Bytes for NoSQLBench in the near future.

+

Stay tuned, and thank you for reading!

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/blog/cql-starter/quickstart-cql/index.html b/blog/cql-starter/quickstart-cql/index.html new file mode 100644 index 000000000..fa186b5c1 --- /dev/null +++ b/blog/cql-starter/quickstart-cql/index.html @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + Posts | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+

 

+

blog-image-not-provided 

+

CQL-Starter

+

Description: Learning CQL with a cql-starter.

+

Author: Jeff Banks

+

Published: 2023-03-28

+

 

 

+

blog-image-not-provided 

+

HTTP-Rest Starter w/ Stargate

+

Description: Learning http-rest using the Stargate date gateway.

+

Author: Jeff Banks

+

Published: 2023-04-07

+

 

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/blog/http-rest/httprestblog-768x461.jpg b/blog/http-rest/httprestblog-768x461.jpg new file mode 100644 index 000000000..90561e4ac Binary files /dev/null and b/blog/http-rest/httprestblog-768x461.jpg differ diff --git a/blog/http-rest/index.html b/blog/http-rest/index.html new file mode 100644 index 000000000..e592daa75 --- /dev/null +++ b/blog/http-rest/index.html @@ -0,0 +1,442 @@ + + + + + + + + + + + + + + + + HTTP-Rest Starter | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Http-Rest-Starter w/ Stargate

+Alt text +

Author: Jeff Banks (DataStax)

+

 

+

Introduction

+

Welcome to the NoSQLBench Quick Byte, second session in a “Getting Started” series for NoSQLBench. This session +introduces a new Http-Rest Starter workload now available in version 5 of NoSQLBench.

+
    +
  • +

    If you haven't heard of NoSQLBench, checkout our introduction material here.

    +
  • +
  • +

    If you already have a foundation with NoSQLBench and would like to understand what's included in the most recent +version, checkout the release notes here.

    +
  • +
  • +

    If you would like to start with the first session in the NoSQLBench “Getting Started” series, check it out here.

    +
  • +
+

This session illustrates use of http-rest methods, using NoSQLBench v5, along with a Docker deployment of an open source +data gateway called Stargate.
+For more information about Stargate, checkout the repository here.

+

In comparison to the previous cql-starter, this starter focuses on http-rest interactions with the data gateway itself instead +of via a CQL driver’s interaction with Cassandra.

+

Let’s get rolling and learn about http-rest operations!

+

Setup requirements

+

This session was tested with:

+
    +
  • Ubuntu (v20.4)
  • +
  • Docker(v20.10.18)
  • +
  • Stargate (v2.0.9)
  • +
  • NoSQLBench (v5.17.3+)
  • +
+

Ensure Docker is installed

+

Download from: here

+

Obtain the latest NB5 release

+

Download from: here

+

Ensure the NB5 binary is accessible

+

If so, you should be able to see your version installed using:

+
 ./nb5 --version 
+
+

Clone Stargate locally

+

Clone from: here

+

Run Stargate services in Docker

+

Navigate to your local Stargate repository and execute the specified script.

+
cd ./stargate/docker-compose/cassandra-4.0/
+
+./start_cass_40_dev_mode.sh
+
+

Verify the Stargate services are started and healthy.

+
7d0c9076153c stargateio/graphqlapi:v2 "/usr/local/s2i/run" - Up About a minute (healthy)
+
+2757157aa423  stargateio/restapi:v2  "/usr/local/s2i/run" - Up About a minute (healthy)
+
+b0c00f0bdd56   stargateio/docsapi:v2  "/usr/local/s2i/run" - Up About a minute (healthy)
+
+1ab290e89dc6  stargateio/coordinator-4_0:v2  "./starctl" - Up 2 minutes (healthy)
+
+

Running the scenario

+

Now, we are ready to run the http-rest-starter NoSQLBench scenario.

+ +
./nb5 --list-workloads | grep http-rest-starter
+
+

Example output:

+
/activities/baselines/http-rest-starter.yaml
+
+

Note: this scenario resides in the adapter-http parent directory for the repository.

+

Optional step

+

An alternative is to copy the workload configuration listed below to your own local file in a folder of your choosing. You can name it whatever you like, as you will specify the absolute file path directly when issuing the scenario command.

+

Workload file

+

This workload file is designed as a basic foundation for continuing to learn NoSQLBench capabilities as well as a starting point for customizing. You will notice the cycle values are minimal to support local testing. Adjust as needed for your own usage.

+

+min_version: "5.17.3"
+
+description: |
+  This starter workload uses an open source data gateway called Stargate,
+  which works with a simple key-value data model.
+  1. Create a keyspace.
+  2. Drop table if existing.
+  3. Create table
+
+scenarios:
+  default:
+    schema: run driver=http tags==block:"schema.*" threads==1 cycles==UNDEF
+    rampup: run driver=http tags==block:"rampup.*" cycles===10 threads=auto
+    main: run driver=http tags==block:"main.*" cycles===10 threads=auto
+
+bindings:
+  request_id: ToHashedUUID(); ToString();
+  token: Discard(); Token('<<auth_token:>>','<<auth_uri:http://localhost:8081/v1/auth>>', '<<auth_uid:cassandra>>', '<<auth_pswd:cassandra>>');
+
+  seq_key: Mod(10000000); ToString() -> String
+  seq_value: Hash(); Mod(1000000000); ToString() -> String
+
+  rw_key: Uniform(0,10000000)->int; ToString() -> String
+  rw_value: Hash(); Uniform(0,1000000000)->int; ToString() -> String
+
+
+blocks:
+  schema:
+    ops:
+      create-keyspace:
+        method: POST
+        uri: http://<<stargate_host>>:8082/v2/schemas/keyspaces
+        Accept: "application/json"
+        X-Cassandra-Request-Id: "{request_id}"
+        X-Cassandra-Token: "{token}"
+        Content-Type: "application/json"
+        body: >2
+          {
+            "name": "starter",
+            "replicas": 1
+          }
+
+      drop-table:
+        method: DELETE
+        uri: http://<<stargate_host>>:8082/v2/schemas/keyspaces/starter/tables/http_rest_starter
+        Accept: "application/json"
+        X-Cassandra-Request-Id: "{request_id}"
+        X-Cassandra-Token: "{token}"
+        Content-Type: "application/json"
+        ok-status: "[2-4][0-9][0-9]"
+
+      create-table:
+        method: POST
+        uri: http://<<stargate_host>>:8082/v2/schemas/keyspaces/starter/tables
+        Accept: "application/json"
+        X-Cassandra-Request-Id: "{request_id}"
+        X-Cassandra-Token: "{token}"
+        Content-Type: "application/json"
+        body: >2
+          {
+            "name": "http_rest_starter",
+            "columnDefinitions": [
+              {
+                "name": "key",
+                "typeDefinition": "text"
+              },
+              {
+                "name": "value",
+                "typeDefinition": "text"
+              }
+            ],
+            "primaryKey": {
+              "partitionKey": [
+                "key"
+              ]
+            },
+            "ifNotExists": true
+          }
+
+  rampup:
+    ops:
+      rampup-insert:
+        method: POST
+        uri: http://<<stargate_host>>:8082/v2/keyspaces/starter/http_rest_starter
+        Accept: "application/json"
+        X-Cassandra-Request-Id: "{request_id}"
+        X-Cassandra-Token: "{token}"
+        Content-Type: "application/json"
+        body: >2
+          {
+            "key": "{seq_key}",
+            "value": "{seq_value}"
+          }
+
+  main-read:
+    params:
+      ratio: 5
+    ops:
+      main-select:
+        method: GET
+        uri: http://<<stargate_host>>:8082/v2/keyspaces/starter/http_rest_starter/{rw_key}
+        Accept: "application/json"
+        X-Cassandra-Request-Id: "{request_id}"
+        X-Cassandra-Token: "{token}"
+        Content-Type: "application/json"
+        ok-status: "[2-4][0-9][0-9]"
+
+  main-write:
+    params:
+      ratio: 5
+    ops:
+      main-write:
+        method: POST
+        uri: http://<<stargate_host>>:8082/v2/keyspaces/starter/http_rest_starter
+        Accept: "application/json"
+        X-Cassandra-Request-Id: "{request_id}"
+        X-Cassandra-Token: "{token}"
+        Content-Type: "application/json"
+        body: >2
+          {
+            "key": "{rw_key}",
+            "value": "{rw_value}"
+          }
+
+
+

Before running the scenario, let’s take a look at the layout of the file. Most of this will be the same layout structure used in most workloads. As such, this example reveals a large amount of the foundational. In addition, this scenario introduces blocks having HTTP methods included such as:

+
    +
  • GET
  • +
  • POST
  • +
  • DELETE
  • +
+

Workload layout

+

As a review, the primary sections of a NoSQLBench workload file include:

+
    +
  • Description - A textual description of what the workload does.
  • +
  • Scenarios - Set of named scenarios for detailing the intent of the workload and defines that for various blocks (e.g. schema, rampup, main, etc.).
  • +
  • Params - Optional parameters of interest to reference for applying values.
  • +
  • Bindings - Named recipes for generated data. These are referenced in block operations.
  • +
  • Blocks - Where the labeled operations reside (e.g. schema, rampup, and main). +
      +
    • Schema - A block section where the schema is actually defined and created.
    • +
    +
  • +
  • Rampup - Block section for data setup that becomes the backdrop for testing; it’s the density of data outside the metrics collected in the main block.
  • +
  • Main - Block section that is the target of metrics collection activities.
  • +
+

Testing operations

+

The workload operations in the http-rest-starter are quite basic in form, and this is intentional.

+

The intent is to focus on a simple set of read, write, and delete operations to understand how to work with +NoSQLBench and Stargate (a data gateway) with http-rest operations.

+

Table and keyspace

+

For the default scenario, a simple table named http_rest_starter will be created with a keyspace named starter.

+

There will be two fields for our table, key and value, both with types of text.

+
{
+  "name": "key",
+     "typeDefinition": "text"
+}, 
+{
+   "name": "value",
+     "typeDefinition": "text"
+}
+
+

In this scenario, the key will become the value for partitioningKey:

+
"primaryKey": {
+  "partitionKey": [
+    "key"
+  ]
+}
+
+

Default scenario

+

For this session, the default scenario is being used. As such, all operations are set up to be targeted and executed.

+
scenarios:
+ default:
+   schema: run driver=http tags==block:"schema.*" threads==1 cycles==UNDEF       
+   rampup: run driver=http tags==block:"rampup.*" cycles===3 threads=auto
+   main: run driver=http tags==block:"main.*" cycles===3 threads=auto
+
+

Bindings

+

Values for fields during the schema, rampup, and main operations will come from the bindings section of the file.

+

Basic examples are included in the http-rest-starter, but this illustrates how bindings supply values to be used by the operations.

+

+
+bindings:
+
+ request_id: ToHashedUUID(); ToString();
+ token: Discard(); Token('<<auth_token:>>','<<auth_uri:http://localhost:8081/v1/auth>>', '<<auth_uid:cassandra>>', '<<auth_pswd:cassandra>>');
+
+ seq_key: Mod(10000000); ToString() -> String
+ seq_value: Hash(); Mod(1000000000); ToString() -> String
+
+ rw_key: Uniform(0,10000000)->int; ToString() -> String
+ rw_value: Hash(); Uniform(0,1000000000)->int; ToString() -> String
+ 
+
+

Let’s break down the bindings to understand how they will be used as values in various operations.

+
    +
  • request_id - represents a unique ID used when making the http-rest calls.
  • +
  • auto_gen_token - this binding uses a newly added function Token(), providing the generation of a +token required by Stargate. If an auth_token value is specified, the rest of the values passed to the Token function are ignored, as the logic to generate +a new token is not invoked. If the auth_token is not specified, the auth_uri can be specified along with the credentials used +for requesting a token generation. Note that the last 3 arguments all have defaults when customizations aren't required.
  • +
  • seq_key and seq_value - are values generated for use by rampup write operations.
  • +
  • rw_key and rw_value - are values generated for use by the main read and write operations.
  • +
+

Running a workload

+

Let’s run the http-rest-starter.

+

Run scenario

+
./nb5 activities/baselines/http-rest-starter.yaml default stargate_host=localhost
+
+

Here, the stargate_host is indicating we are targeting the local host services running in Docker. The port and other URL specifics are included in each of the block operations.

+

Examine results

+

After the workload has been run, let’s take a look at the results.

+
docker container exec -it cass40-stargate-coordinator-1 sh
+
+

Stargate log activity

+

Here you can poke around at the system.log to view the operations that were executed when running the http-rest-starter.

+
cd /stargate/log
+
+tail -100 system.log
+
+

Next steps

+

More getting started?

+

Checkout the NoSQLBench getting started section and details for its capabilities for your next testing initiative.
+You can find the starter details here.

+

More Http-Rest adapter information?

+

There are a number of http-rest examples in NoSQLBench.
+In fact, they expand on the use of the Stargate data gateway covering topics such as:

+
    +
  • Documents API
  • +
  • GraphQL (CQL first approach)
  • +
  • GraphQL (Schema first approach)
  • +
+

Want to contribute?

+

It’s worth mentioning, NoSQLBench is open source, and we are looking for contributions to expand its features!
+Head over to the contributions page to find out more.

+

Need more advanced scenarios?

+

There are a number of pre-built scenarios that exist here.

+

We will continue to have more Quick Bytes for NoSQLBench in the near future.

+

Stay tuned, and thank you for reading!

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/blog/http-rest/quickstart-http-rest/index.html b/blog/http-rest/quickstart-http-rest/index.html new file mode 100644 index 000000000..906adac66 --- /dev/null +++ b/blog/http-rest/quickstart-http-rest/index.html @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + Posts | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+

 

+

blog-image-not-provided 

+

CQL-Starter

+

Description: Learning CQL with a cql-starter.

+

Author: Jeff Banks

+

Published: 2023-03-28

+

 

 

+

blog-image-not-provided 

+

HTTP-Rest Starter w/ Stargate

+

Description: Learning http-rest using the Stargate date gateway.

+

Author: Jeff Banks

+

Published: 2023-04-07

+

 

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/blog/index.html b/blog/index.html new file mode 100644 index 000000000..b1e6e55ca --- /dev/null +++ b/blog/index.html @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + Blogs Published | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

NoSQLBench Blogs

+

Browse our NoSQLBench blogs, with content contributed by the NoSQLBench community.

+

Feel free to contribute your own content and/or provide input for future content.

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/blog/published/index.html b/blog/published/index.html new file mode 100644 index 000000000..5c38b239f --- /dev/null +++ b/blog/published/index.html @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + Posts | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+

 

+

blog-image-not-provided 

+

CQL-Starter

+

Description: Learning CQL with a cql-starter.

+

Author: Jeff Banks

+

Published: 2023-03-28

+

 

 

+

blog-image-not-provided 

+

HTTP-Rest Starter w/ Stargate

+

Description: Learning http-rest using the Stargate date gateway.

+

Author: Jeff Banks

+

Published: 2023-04-07

+

 

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/browserconfig.xml b/browserconfig.xml new file mode 100644 index 000000000..c76c07c4a --- /dev/null +++ b/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #333333 + + + diff --git a/codecopy.js b/codecopy.js new file mode 100644 index 000000000..c1f3a755c --- /dev/null +++ b/codecopy.js @@ -0,0 +1,76 @@ +// https://aaronluna.dev/blog/add-copy-button-to-code-blocks-hugo-chroma/ +// Further modified for Zola by Jieiku: https://github.com/Jieiku +(function() { + // create copy button + function ccb(highlightDiv) { + const button = document.createElement("button"); + button.className = "cc "; + button.type = "button"; + button.innerHTML = "Copy"; + button.addEventListener("click", () => + ccc(button, highlightDiv) + ); + + // addCopyButtonToDom + const wrapper = document.createElement("div"); + wrapper.className = "ccw"; + wrapper.appendChild(button); + highlightDiv.parentNode.insertBefore(wrapper, highlightDiv); + wrapper.appendChild(highlightDiv); + } + + // copy code clipboard + async function ccc(button, highlightDiv) { + //look for table, if so do it different + const { length } = highlightDiv.querySelectorAll("table"); + let codeToCopy = ""; + if (length > 0) { + const items = highlightDiv.querySelectorAll(":last-child > tr > td:last-child"); + items.forEach(item => { + codeToCopy = codeToCopy + item.innerText; + //console.log(codeToCopy); + }); + } else { + codeToCopy = highlightDiv.querySelector(":last-child > code").innerText; + } + try { + result = await navigator.permissions.query({ name: "clipboard-write" }); + if (result.state == "granted" || result.state == "prompt") { + await navigator.clipboard.writeText(codeToCopy); + } else { + cce(codeToCopy, highlightDiv);//copyCodeBlockExecCommand + } + } catch (_) { + cce(codeToCopy, highlightDiv);//copyCodeBlockExecCommand + } finally { + //codeWasCopied + //button.blur(); + button.innerHTML = "Copied"; + setTimeout(function () { + button.innerHTML = "Copy"; + }, 2000); + } + } + + //copyCodeBlockExecCommand + function cce(codeToCopy, highlightDiv) { + const textArea = document.createElement("textArea"); + textArea.contentEditable = "true"; + textArea.readOnly = "false"; + textArea.className = "copyable-text-area"; + textArea.value = codeToCopy; + highlightDiv.insertBefore(textArea, highlightDiv.firstChild); + const range = document.createRange(); + range.selectNodeContents(textArea); + const sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + textArea.setSelectionRange(0, 999999); + document.execCommand("copy"); + highlightDiv.removeChild(textArea); + } + + document + .querySelectorAll("pre") + .forEach((highlightDiv) => ccb(highlightDiv)); +})(); \ No newline at end of file diff --git a/dev-guide/contributing/coding-standards/index.html b/dev-guide/contributing/coding-standards/index.html new file mode 100644 index 000000000..febcf8b79 --- /dev/null +++ b/dev-guide/contributing/coding-standards/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + Coding Standards | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

In order to keep the code base tidy, here are the coding standards we try to observe:

+

Unit Tests

+

Unit Test Coverage

+

We really like unit tests where it makes sense. It usually makes sense to write unit tests! +However, we aren't chasing 100% code coverage. We do measure it, and we do intend to keep it +from going down past some reasonable level. We will start to pull up the code coverage +requirements for each module over time, but only to a reasonable level.

+

Unit Test Logging

+

Don't write to System.stdout or System.stderr in your unit tests. Instead, use a logger, as in

+
private final static Logger logger = LogManager.getLogger(MyClass.class);
+
+

The logging subsystem is used for nearly all console IO with NoSQLBench. This is a drastic +simplification for developers and maintainer. In general, users don't want to be notified of +anything except when the do, and when they do, they can simply use -v to turn the default +console logging level up from WARN to INFO and so on. This applies as well to tests. We can +keep console IO low for unit tests and even us async logging in the background to speed up +builds and keep the build output tidy for when you need to troubleshoot actual build errors.

+

Integrated Test Coverage

+

Since NB is a layered runtime design, we need to be specific when we are talking about +integrated tests. Once we have stabilized the new integrated test harness, it will be better +documented for contributors. This is a work in progress.

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/contributing/come-join-us/index.html b/dev-guide/contributing/come-join-us/index.html new file mode 100644 index 000000000..d525768fc --- /dev/null +++ b/dev-guide/contributing/come-join-us/index.html @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + Come Join Us | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

There are multiple ways to contribute to NoSQLBench. The project is growing, and it needs many +hands to help it be as awesome as it can be. Ways to contribute include: improving the +documentation, submitting bug reports, reproducing bugs, providing bugfixes, submitting ideas +for new features, helping with design discussion, contributing drivers or other core features, +or even improving the CI/CD in github actions.

+

There is also a need to get the word out and show new users how to use various features, so if +this is something you particularly enjoy, please jump in.

+

Other than that, we're always happy to find ways for contributors to get engaged, so if you are +interested but don't know how to get started, join us on our +discord server and we can figure something out.

+

CLA or contributor covenants

+

NoSQLBench does not presently have a contributor covenant or CLA (Contributor Licensing Agreement), +but this may be added if necessary. In general, we try to keep the friction low for new +contributors. The main two things you have to agree to contribute to NoSQLBench are:

+ +
1 +

If this is not agreeable to anybody, we will need to setup a CLA or something similar +to ensure that the project can evolve as needed without chasing down copyright holders or +replacing abandoned code in the future. We'd like to keep things simpler than this, but we will +consider it if significant contributions justify a change.

+
+ +
+
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/contributing/index.html b/dev-guide/contributing/index.html new file mode 100644 index 000000000..62e2bfbcf --- /dev/null +++ b/dev-guide/contributing/index.html @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + Come Join Us | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

There are multiple ways to contribute to NoSQLBench. The project is growing, and it needs many +hands to help it be as awesome as it can be. Ways to contribute include: improving the +documentation, submitting bug reports, reproducing bugs, providing bugfixes, submitting ideas +for new features, helping with design discussion, contributing drivers or other core features, +or even improving the CI/CD in github actions.

+

There is also a need to get the word out and show new users how to use various features, so if +this is something you particularly enjoy, please jump in.

+

Other than that, we're always happy to find ways for contributors to get engaged, so if you are +interested but don't know how to get started, join us on our +discord server and we can figure something out.

+

CLA or contributor covenants

+

NoSQLBench does not presently have a contributor covenant or CLA (Contributor Licensing Agreement), +but this may be added if necessary. In general, we try to keep the friction low for new +contributors. The main two things you have to agree to contribute to NoSQLBench are:

+ +
1 +

If this is not agreeable to anybody, we will need to setup a CLA or something similar +to ensure that the project can evolve as needed without chasing down copyright holders or +replacing abandoned code in the future. We'd like to keep things simpler than this, but we will +consider it if significant contributions justify a change.

+
+ +
+
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/contributing/new-maintainers/index.html b/dev-guide/contributing/new-maintainers/index.html new file mode 100644 index 000000000..35bd3eefc --- /dev/null +++ b/dev-guide/contributing/new-maintainers/index.html @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + New Maintainers | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

The NoSQLBench project has a few dedicated builders. We would like to diversify the +maintainer base of the project as well as build bridges to new communities in the NoSQL ecosystem.

+

This is good for the community and the maintainers, and helps foster trust in those that depend +on the project.

+

If you are looking for an interesting project to work on, we're eager to work with you. +Whether you are a seasoned builder or just starting out, there is a way for us to get you +included into the project that is fun and satisfying for everyone.

+

Just inquire within if you are interested.

+ +
+
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/contributing/pull-requests/index.html b/dev-guide/contributing/pull-requests/index.html new file mode 100644 index 000000000..e50aa94ed --- /dev/null +++ b/dev-guide/contributing/pull-requests/index.html @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + Pull Requests | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

All new changes to the project should be made in the form of a pull request. In certain cases, +project maintainers may push directly in order to fix a CI/CD issue or similar, but otherwise +everyone should expect to submit pull requests and get at least 1 maintainer approval before +having their code merged.

+

Maintainers may make suggestions to your PR before it can be approved. This is done via the +conversations feature directly in github. If there are required changes before approval, they +will be described clearly with a request to make the changes before further review. If you are +asked to make changes, all you have to do is refine the branch you submitted the PR from and +push the changes up.

+

note: If you are unsure of your branch, and want to work on it further before review or merge, +please submit it as a draft PR. This helps set expectations so that reviewers aren't studying +incomplete submissions.

+

In order to make sure related issues are closed, you can add +closing terms +to the description.

+

When you are ready for review, move your PR from draft to "ready for review", and request one of +the project maintainers for a review.

+

The rest of this page tells you what to expect from the maintainers during code review.

+

What is Accepted?

+

Generally speaking, any change which is non-trivial should already be discussed within the +project in order to make cooperation between contributors harmonious. Very trivial change which +are quick to review and very self-evident as to what they fix or improve may be accepted with +little pushback. Still, it is a courtesy to the rest of the developer community to document what +you are working on in an issue and assign yourself to it first.

+

Licensing

+

All code submitted should have the APLv2 license header at the top, with the copyright set as

+
/*
+ * Copyright (c) 2022 nosqlbench
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+

If this is not the case, then the build will fail. There is a handy way to fix this. +After this happens, the license checker will automatically create some prototype files +which include the changes needed. You can simply run a utility script in +scripts/accept_license.sh to write the updated files to the orignal names.

+

Coding Standards

+

Static Analysis

+

You should use a static analyzer if you have one. There is one that is used by the project for +every build. It may flag significant issues in your PR, which may also keep it from being merged. +It is always a good idea to leave your PR in draft mode until you get green light, as the CodeQL +feedback will already give you something to fix if it finds anything.

+

Test Coverage

+

Any contribution of code should have an appropriate amount of built-in testing. This can be +either as unit tests or as integrated tests. It is up to the judgement of the contributor what +constitutes a sufficient level of testing, although more may be requested by code review.

+

The code coverage in unit and integrated tests will be improved over time. There may be +build-time checks which warn you if the code coverage goes down with your added changes. This +could cause it to fail during merge checks, so try to have a reasonable amount of test coverage +in new code.

+

Dependencies

+

Be cautious about adding even more dependencies to the project. NoSQLBench is a rather large +project due to the scope of what it does, including many driver modes. If you add dependencies +without scanning for a suitable capability that is already in the project, it will cause +dependency creep. This is bad. Try to help us keep the dependency tree well trimmed.

+

What is (generally) Accepted?

+

Incremental Improvements

+

Changes which are complimentary or incremental to core NoSQLBench functionality are always good. +As long as a change doesn't compromise existing functionality or otherwise compromise the +integrity of the project it will generally be welcome.

+

Trivial Improvements

+

Changes which have already been discussed or are of such a trivial nature that they are +self-describing don't require substantial ceremony. Use your best judgement here. If you are +fixing a typo on the website, just do it. If you are adding a better description to some CI/CD +wiring, just do it. Again, just use your best judgement about what should be discussed or agreed +to beforehand.

+

Subsystem Enhancements

+

Changes which make the core of NoSQLBench easier, better, or more powerful for any user in the +NoSQL ecosystem are awesome. New driver are awesome. This includes drivers from vendors. All +changes will be subject to the platform standards and community guidelines, of course.

+

What is NOT Accepted?

+

Bad Dependencies

+

The platform standards are enforced in PRs.

+

Large Surprises

+

Large, surprising changes with no previous consensus or discussion may not be approved with +a request for discussion. This type of change is an unreasonable burden to any maintainer. If +you want to make large changes, you must work together with the NoSQLBench builder community to +make sure it fits well within the project, and is on-mission with the core outcomes of the project.

+

Untested or Untestable Code

+

You must design your contributions in a way that allows for testing.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/contributing/releases/index.html b/dev-guide/contributing/releases/index.html new file mode 100644 index 000000000..a9dd9bfa5 --- /dev/null +++ b/dev-guide/contributing/releases/index.html @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + Release Management | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

This is partly documenting the current flow, partly aspirational. Within the first few releases +of NB5, this should all be standard and reliable. This notice will be removed at that time.

+

Release Channels

+

We have a three track release system:

+ +

This is a system of incremental promotion from build to preview to release, with documentation +included. This allows us to preview new features and capabilities with the community in a safe +way, only accepting previews which are up to release standards.

+

Repositories

+

Of course, managing this flow requires a few more repositories than usual, since we are hosting +the docs sites on github pages. This means we need the main code repo for NoSQLBench, as well as +a separate repo for each of the three docs sites:

+

The main repo for nb5 is at nosqlbench.io. This is just a convenient +name for https://github.com/nosqlbench/nosqlbench.

+

This allows convenient access to issues, and +pull requests too.

+

The three docs sites and their corresponding +URLs are:

+
    +
  1. nosqlbench-build-docs, accessed at +http://builddocs.nosqlbench.io
  2. +
  3. nosqlbench-preview-docs, accessed at +http://previewdocs.nosqlbench.io
  4. +
  5. nosqlbench-docs, the main docs +site, at http://docs.nosqlbenhc.io
  6. +
+

Automation

+

All of the CI & CD build automation for NoSQLBench is hosted in github actions.

+

Release Criteria

+

Before a preview release can be promoted to a main release, the following must happen:

+
    +
  1. All high CVE alerts for potential issues must be addressed. We use multiple static analysis +tools for this. Any high severity issues are required to be addressed, even if this means +that they are flagged as a false positive after further review.
  2. +
  3. All integration test must pass.
  4. +
  5. New functionality must be documented in the docs site. Ideally this includes a what's new update.
  6. +
+

Release Notifications

+

When a new release is made, the community should be notified in the usual places. +This isn't active, yet but we intend to support:

+
    +
  • discord
  • +
  • this docs site
  • +
  • twitter and/or mastodon
  • +
  • corporate sponsor sites / blog feeds
  • +
+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/contributing/working-together/index.html b/dev-guide/contributing/working-together/index.html new file mode 100644 index 000000000..a8f108163 --- /dev/null +++ b/dev-guide/contributing/working-together/index.html @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + Working Together | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Routine Changes

+

Bugfixes, basic features, doc improvements, and any other change to the project that is +well-defined, of reasonably small scope, and easily tested can be managed through issues and +discussion on them. This is the most common way to make contributions to the project. Just +follow the community guidelines in this section and you'll be making changes in no time.

+

Big Ideas

+

Ideas which require a degree of planning and design work should be discussed with the community +and maintainers in discussions. There is an idea category +that is already used for this. This is to ensure that everyone is on the same page about how +something will work before work starts in earnest. Big ideas are awesome, but the hardest +work of landing them successfully is in building consensus for how they should fundamentally work.

+

Prototypes

+

If you want to build a prototype of something and then present it to the project, we are always +open to that. Sometimes a prototype is really the only way to effectively convey a vision. Still, +doing this comes with certain risks. It's possible that your big idea is already in the works or +in some form in the project already. If you aren't sure, it's always best to start a big idea +conversation or approach us on discord to discuss it.

+

Issues and Assignment

+

If you are making contributions, it is important to get aligned with the other contributors +before spending significant effort. One of the best ways to do this is to have an issue assigned +to yourself. It can be frustrating for other developers to work on an issue that is already +being solved.

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/how-tos/auto-apply-license-intellij/index.html b/dev-guide/how-tos/auto-apply-license-intellij/index.html new file mode 100644 index 000000000..5307e28f6 --- /dev/null +++ b/dev-guide/how-tos/auto-apply-license-intellij/index.html @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + Auto Apply License in IntelliJ | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Assumptions

+
    +
  • You are using IntelliJ to work with the NoSQLBench code base.
  • +
  • You want IntelliJ to automatically apply the license files when needed on files you edit.
  • +
+

Steps

+
    +
  1. Enable the bundled copyright plugin
  2. +
  3. Under File | Settings | Editor | Copyright | Copyright Profiles, add one named 'aplv2'.
  4. +
+
    +
  • Set the copyright text (velocity template) to:
  • +
+
Copyright (c) $originalComment.match("Copyright \(c\) (\d+)", 1, "-", "$today.year")$today.year nosqlbench
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
    +
  • Set the Regex to detect copyright in comments to:
  • +
+
.*Licensed under the Apache License, Version 2.0.*
+
+

You can click the validate button to confirm that the velocity template works.

+

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/how-tos/implement-an-adapter/index.html b/dev-guide/how-tos/implement-an-adapter/index.html new file mode 100644 index 000000000..58b035472 --- /dev/null +++ b/dev-guide/how-tos/implement-an-adapter/index.html @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + Implement an Adapter | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

NoSQLBench is composed of a sound architectural underpinning that makes the process of implementing new adapters as seamless and quick as possible. NoSQLBench provides a hierarchy of classes which can be extended and interfaces to be implemented, in order to avoid having to re-implement the application infrastructure and in so doing reduces both the complexity and demands on time involved in implementing a new adapter type. However, it is necessary to understand this existing architecture in order to effectively use the provided building blocks. The following is intended as a guide to developing new adapters to extend the functionality of NoSQLBench.

+

Prerequisites and Assumptions

+
    +
  • It is assumed that the developer(s) have familiarized themselves with the NoSqlBench core concepts provided in the NoSQLBench documentation.
  • +
  • The ability to code in Java is required. NoSQLBench makes extensive use of lambda functionality. It is a requirement to understand and be comfortable using these principles to develop an adapter.
  • +
  • This guide is not specific to any particular client. It is assumed that the developer(s) have familiarity with the client they are developing an adapter for.
  • +
+

Internal Dependencies

+

The NoSQLBench project as a whole is composed of numerous modules and packages. For the purpose of customer adapter implementation there are only two required; adapters-api and nb-annotations.

+
<dependency>
+	<groupId>io.nosqlbench</groupId>
+ 	<artifactId>adapters-api</artifactId>
+ 	<version>${revision}</version>
+ 	<scope>compile</scope>
+</dependency>
+	
+<dependency>
+    <groupId>io.nosqlbench</groupId>
+    <artifactId>nb-annotations</artifactId>
+    <version>${revision}</version>
+    <scope>compile</scope>
+</dependency>
+
+

The adapters-api and nb-annotations modules contain all of the base classes, interfaces and annotations required to implement a new adapter and flesh out its functionality.

+
    +
  • Adapters - Every new adapter will, of course, include an Adapter class. This class will be a descendent of the BaseDriverAdapter class found here. NoSQLBench uses the Java Service Provider Interface(SPI) to define service providers. If you don’t know what that is, don't worry about it now. The tl;dr is that extending the BaseDriverAdapter and annotating your driver adapter class with the Service annotation will result in that class being added to META-INF/services under the specified class name, making it available as a service provider. NoSQLBench takes care of all the rest!
  • +
  • Ops - NoSQLBench is built around the ability to define operations (“Ops”) in a generic fashion (the op template) and translate them into actions. All of the basic plumbing for this is handled in the adapters-api module, from the yaml file loader to the definition of the various types of ops available to implement. Along with the Op types the adapters-api package defines the base classes and interfaces for Op Dispensers, which do the work of creating the Op, and the Op Mappers, which map the appropriate functionality based on the Op type presented. We’re going to get into the details of the available implementations in the next section.
  • +
+

Your First Adapter

+
    +
  1. +

    Familiarize yourself with the native driver. You will need to know exactly what functionality you want to test and what the APIs for that functionality look like so you can plan for what your Op classes need to be able to do.

    +
  2. +
  3. +

    Create a new module in the root of the project using standard naming:

    +
      +
    • adapter-<typeName> where the chosen selector that will be used with driver=<typeName>, e.g. adapter-jdbc, adapter-pinecone, etc.
    • +
    • package naming should follow io.nosqlbench.adapter.<typeName>
    • +
    • A quick way to create module is to copy an existing adapter's pom.xml into a new directory as pod.xml, modify the naming elements, and then rename pod.xml to pom.xml
    • +
    • In most cases the only dependencies you should need are adapters-api and nb-annotations (as discussed in the previous section), as well as the api library published for the native driver you are adapting. If you find that you need to pull in additional dependencies, first verify whether they are included in another module already within the nb project to simplify the process.
    • +
    • Initially, do not add the module to the root pom.xml under modules. You can still build it and test it without requiring it to build for the main module to build. Once it is ready to be included under the main build, then you add it to the modules list. At that time, add it to the list of driver dependencies for the nb5 module, and it will be included in the runtime.
    • +
    +
  4. +
  5. +

    Implement your first Op.

    +
      +
    • Implement a POJO which implements one of the Op interfaces and represents a value type for a specific operation.
    • +
    • It is recommended to use RunnableOp by default. This means you only need to provide a run method to define whatever action this operation encapsulates. The op class itself should be extremely lightweight, as the logic for constructing the operation will take place in the dispenser.
    • +
    • As a value type it must be repeatable.
    • +
    • It should capture the details of a single operation for diagnostics and debugging purposes. In database terminology, for example, this might be “insert”, or “delete”, or “update”.
    • +
    +
  6. +
  7. +

    Implement a minimal Adapter Space.

    +
      +
    • Stub a POJO which can hold instances of your native driver. This is your context, or adapter space.
    • +
    • This class should contain any logic needed to establish connectivity as well as any type of initialization required for the native driver.
    • +
    • The constructor of the adapter space should take a String and an NBConfiguration instance as its parameters. Any variables needed to initialize the environment should be accessible to the adapter space through the NBConfiguration instance. The adapter space class must define what these variables are by implementing the static getConfigModel() method. See existing adapter space implementations for details on this.
    • +
    +
  8. +
  9. +

    Implement the DriverAdapter.

    +
      +
    • This class must extend the BaseDriverAdapter class. As the BaseDriverAdapter class is a templated type, this implementation should use the 2 classes previously created, i.e.
      +MyDriverAdapter extends BaseDriverAdapter<MyOp, MyAdapterSpace>
    • +
    • Add the @Service annotation that makes it available for runtime service looking and late binding.
      +@Service(value = DriverAdapter.class, selector = "nativedrivertype")
    • +
    • Minimally this class must implement 2 methods, both of which should specify that they are overriding the base class +
        +
      • getOpMapper - this method will return the OpMapper specific to the types of Op classes that will be created for this driver. As we have not yet implemented this class, for now it can be stubbed to simply return null. The signature should look like
        +public OpMapper<MyOp> getOpMapper()
      • +
      • getSpaceInitializer - this method accepts an NBConfiguration instance as an argument and will return a function that can be used to instantiate the previously defined adapter space. In its simplest form it will simply pass the configuration along to the constructor for the adapter space. The signature should look like
        +public Function<String, ? extends MyAdapterSpace> getSpaceInitializer(NBConfiguration cfg)
      • +
      +
    • +
    +
  10. +
  11. +

    Implement an OpDispenser for this Op type.

    +
      +
    • This must extend BaseOpDispenser, which is a templated class. The definition might look like this:
      +public class MyOpDispenser extends BaseOpDispenser<MyOp, MyAdapterSpace>
    • +
    • The constructor must accept at least a DriverAdapter and an Op of the specified type, and it must call the super constructor, which requires the DriverAdapter and Op to be provided.
    • +
    • The constructor for this class will need at least the function for retrieving the relevant Adapter Space to facilitate the creation of the Op to be dispensed, and a ParsedOp object which is the operation as derived from the source yaml/JSON file to be converted to the appropriate op type by the dispenser.
    • +
    • The OpDispenser must also override the apply method defined in the BaseOpDispenser. For each test cycle this apply method will be called, and the OpDispenser will need to return the created Op for that cycle. The typical pattern used in the implementation of the OpDispenser is that at the time of construction it defines a LongFunction to create the Op that is dispensed when the apply method is called. The apply method itself is minimal and applies the input value (the cycle) to this function and dispenses the Op returned.
    • +
    • This is another place where it should be noted that in an adapter of any complexity there will usually be multiple Op types, each of which will have its own OpDispenser class responsible for dispensing only that type of Op. Don’t implement a hierarchy of Op types and dispense them through a single OpDispenser via dynamic binding.
    • +
    +
  12. +
  13. +

    Implement an OpMapper to create the OpDispenser

    +
      +
    • The OpMapper has a very simple job in the case of having only a single OpDispenser type, it creates the OpDispenser. In more complicated use cases the OpMapper receives an Op and interrogates it to determine the appropriate OpDispenser to create. More on this below.
    • +
    • Your class should implement the OpMapper interface, with the templated type once again being your Op. It then needs to override the apply(ParsedOp) method to return the OpDispenser. The signature should look something like this:
      +public OpDispenser<? extends MyOp> apply(ParsedOp op)
    • +
    • At this point you can treat the apply method largely as a pass-through and simply return a new OpDispenser instance (although take a look at the existing implementations, you will probably want to emulate the use of the space cache to pass the dispenser the space object as well).
    • +
    • The constructor for this class doesn’t have any hard requirements, but if you look at the existing implementations you will notice most of them include as an argument a new class we haven’t talked about yet, the DriverSpaceCache. Not to worry, this is simply a cache to hold your associated context, the details of which are handled once again by the NoSQLBench plumbing. In the next step we will look at how this is used in the Adapter class.
    • +
    +
  14. +
  15. +

    Wire your classes together and get it to compile cleanly.

    +
      +
    • Go back to the Adapter type created in step 5. Now you’re going to fill in that getOpMapper method. If your code looks like the majority of implementations the method body will look like this:
    • +
    +
    DriverSpaceCache<? extends MyAdapterSpace> spaceCache = getSpaceCache();   
    +NBConfiguration config = getConfiguration();    
    +return new MyOpMapper(this, config, spaceCache); 
    +
    +
      +
    • As pointed out earlier this “just works” because NoSQLBench already provides the plumbing behind these calls. The BaseDriverAdapter handles the necessary initialization and storage of the appropriate type of space cache and NB configuration, and these can simply be passed in to the constructor for your OpMapper class!
    • +
    • You should now have: +
        +
      • An op class that implements the RunnableOp interface and defines a run method that does something specific to the native driver you are working with.
      • +
      • An adapter space class that encapsulates the context of the native driver and implements any logic necessary for initialization.
      • +
      • A driver adapter class that contains the logic to instantiate both the op mapper class and the adapter space class.
      • +
      • An op dispenser class that both contains the logic to construct instances of your op type from a ParsedOp object and implements the apply method to return new instances of your op type.
      • +
      • An op mapper class, as returned by the driver adapter, that implements the apply method to accept a ParsedOp instance and return an instance of the previously defined op dispenser class.
      • +
      +
    • +
    +
  16. +
+

Further Reading

+

Use Cases With Multiple Op Types

+

In most sophisticated use cases a single op type will not be sufficient. As in the canonical example of a database where a user may want to perform a number of different operations such as inserting new records, reading existing records, updating, deleting, etc. In these cases it is necessary to define more than a single Op class, defining a separate class for each of these operations. In these cases there should be a separate OpDispenser class defined for each Op type as well, with the OpMapper class creating the OpDispenser type appropriate for the operation being performed.

+

The Op classes should remain as compact as possible, implementing only the basic functionality they are ascribed. The OpDispenser classes remain similar in structure, with each creating a function specific to the Op type it is associated with, to be called by the apply method at the time when the Op needs to be created. The difference in implementation is largely confined to how the OpDispenser class interacts with the ParsedOp object it receives in its constructor. The ParsedOp represents a single operation as defined by the source configuration yaml file passed at runtime. The yaml might contain any arbitrary number of different ops, each of which will be interpreted and result in a ParsedOp to be passed to the Mapper and Dispenser at runtime. Each dispenser can query the ParsedOp for the existence of the fields it expects to find defined for instantiation of the Op type it is responsible for, and define the creation functionality based on what it finds to be present.

+

In the cases where multiple Op types are defined an OpType enum class should also be provided. This allows the OpMapper class to use the TypeAndTarget functionality provided by the ParsedOp API. getTypeAndTarget is a method exposed by the ParsedOp API which allows the caller to pass in as arguments the class of the enum, the expected class the resulting function should return, the type name and the value name and in return receive a TypeAndTarget Object containing the enum type identification and a target function that will return the value associated with the type. This target function can be thought of as providing the “key” for the Op type in question. For example in the pinecone adapter every operation needs to specify the database index the operation will run against. This is represented in the op definition as:

+
type: [query,delete,update…]
+index: <database index>. 
+
+

And the call to TypeAndTarget is:

+
op.getTypeAndTarget(PineconeOpTypes.class, String.class, "type", "index"). 
+
+

With this definition the target function will return the value of the database index for the given Op.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/how-tos/index.html b/dev-guide/how-tos/index.html new file mode 100644 index 000000000..c8034ada4 --- /dev/null +++ b/dev-guide/how-tos/index.html @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + Auto Apply License in IntelliJ | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Assumptions

+
    +
  • You are using IntelliJ to work with the NoSQLBench code base.
  • +
  • You want IntelliJ to automatically apply the license files when needed on files you edit.
  • +
+

Steps

+
    +
  1. Enable the bundled copyright plugin
  2. +
  3. Under File | Settings | Editor | Copyright | Copyright Profiles, add one named 'aplv2'.
  4. +
+
    +
  • Set the copyright text (velocity template) to:
  • +
+
Copyright (c) $originalComment.match("Copyright \(c\) (\d+)", 1, "-", "$today.year")$today.year nosqlbench
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
    +
  • Set the Regex to detect copyright in comments to:
  • +
+
.*Licensed under the Apache License, Version 2.0.*
+
+

You can click the validate button to confirm that the velocity template works.

+

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/how-tos/make-a-pull-request/index.html b/dev-guide/how-tos/make-a-pull-request/index.html new file mode 100644 index 000000000..9fc49f9ae --- /dev/null +++ b/dev-guide/how-tos/make-a-pull-request/index.html @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + Make a Pull Request | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

This is a detailed step-by-step explanation of how you would typically submit contributions to +the NoSQLBench project.

+

Assumptions

+
    +
  • You have a GitHub account
  • +
  • You know how to build NoSQLBench
  • +
+

Steps

+

Setup Workspace

+
    +
  1. configure your dev environment
  2. +
  3. clone the nosqlbench repo
  4. +
  5. clone your repo to your dev environment
  6. +
+

Own an issue

+
    +
  1. assign or ask for an issue
  2. +
  3. create a feature branch
  4. +
+

Make Change

+
    +
  1. add testing
  2. +
  3. add documentation
  4. +
  5. verify everything works
  6. +
+

Submit for Review

+
    +
  1. organize commits for easy PR reviews
  2. +
  3. make thematic incremental changes as you go
  4. +
  5. push your branch up to your clone
  6. +
  7. make a draft pull request
  8. +
  9. promote PR to ready-for-review
  10. +
  11. ask a contributor to review and merge your PR
  12. +
+

Iterate

+
    +
  1. resolve conversations or issues
  2. +
  3. repush and ask for review +
      +
    • You are done with this step once your PR is green, changes have been approved by +reviewers, and there are no unresolved issues.
    • +
    +
  4. +
+

Merge

+
    +
  1. merge the PR in GitHub
  2. +
+

Reset

+
    +
  1. delete the feature branch
  2. +
  3. delete your local feature branch
  4. +
  5. checkout main
  6. +
  7. pull main
  8. +
+

You're Done! Go again?

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/how-tos/recompile-less/index.html b/dev-guide/how-tos/recompile-less/index.html new file mode 100644 index 000000000..c2542f6e0 --- /dev/null +++ b/dev-guide/how-tos/recompile-less/index.html @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + Recompile Less | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

If you are working on the main nosqlbench code base, you don't have to rebuild everything. There +are a couple basic methods you can use to focus just on the module you are developing.

+

Dev Iteration

+

Maven Install

+

For driver development, it's best to build and install the existing artifacts from main to your Maven repo. +This puts all the libraries into your local maven artifact repo (typically under $HOME/.m2/repo) +and then allows you to build only the specific module you are working in.

+
# ensure you have java 17 on your path
+java -version
+# OR you have a java 17 in $JAVA_HOME/bin/java -version
+$JAVA_HOME/bin/java -version
+cd nosqlbench
+mvn install
+
+

You can then run mvn only in the module that you need.

+
cd adapter-mynewdriver
+mvn verify
+
+

Module Testing

+

NBLIBDIR

+

Another way to save time is to build the nbr module, which is the NoSQLBench Runtime Module. +This comes in jar form and executable form, but it is not built by default. To enable it, you'll +need to activate its run profile. You can either provide -Pnbr to mvn commands like mvn -Pnbr install, or set it in your IDE's Maven profile toggles.

+

Once you have nbr built, you can use it along with any DriverAdapter jars by setting the +NBLIBDIR environment variable.

+

When this is set, it is split by colon, just as the $PATH variable would be. +For each path, relative to the current working directory,

+
    +
  1. If it is a directory, then each jar file found under it is added to the classpath.
  2. +
  3. If it is a zip file, then each jar file found within it is added to the classpath.
  4. +
  5. If it is a jar file, then it is added directly to the class path.
  6. +
+

This allows you to provide your driver in a separate jar and invoke it with the NoSQLBench +runtime just as if it were bundled.

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/index.html b/dev-guide/index.html new file mode 100644 index 000000000..3575425de --- /dev/null +++ b/dev-guide/index.html @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + Come Join Us | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

There are multiple ways to contribute to NoSQLBench. The project is growing, and it needs many +hands to help it be as awesome as it can be. Ways to contribute include: improving the +documentation, submitting bug reports, reproducing bugs, providing bugfixes, submitting ideas +for new features, helping with design discussion, contributing drivers or other core features, +or even improving the CI/CD in github actions.

+

There is also a need to get the word out and show new users how to use various features, so if +this is something you particularly enjoy, please jump in.

+

Other than that, we're always happy to find ways for contributors to get engaged, so if you are +interested but don't know how to get started, join us on our +discord server and we can figure something out.

+

CLA or contributor covenants

+

NoSQLBench does not presently have a contributor covenant or CLA (Contributor Licensing Agreement), +but this may be added if necessary. In general, we try to keep the friction low for new +contributors. The main two things you have to agree to contribute to NoSQLBench are:

+ +
1 +

If this is not agreeable to anybody, we will need to setup a CLA or something similar +to ensure that the project can evolve as needed without chasing down copyright holders or +replacing abandoned code in the future. We'd like to keep things simpler than this, but we will +consider it if significant contributions justify a change.

+
+ +
+
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/project-standards/dependencies/index.html b/dev-guide/project-standards/dependencies/index.html new file mode 100644 index 000000000..8f29a346c --- /dev/null +++ b/dev-guide/project-standards/dependencies/index.html @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + Dependencies | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

With NoSQLBench 5 and newer, there are some compatibility standards that we observe for +dependencies. This is to ensure that various drivers and their upstream dependencies can work +harmoniously in one runtime.

+

Java LTS

+

The latest Java LTS release should be used for every new major version. In some cases, newer Java +LTS releases can be pulled into a minor release after sufficient testing.

+

The middle version number indicates the Java platform standard. For example nb5 version +5.17.0 uses Java 17, which is the latest LTS version. The NoSQLBench project will use +this version across the board, including JVM and language features.

+

No Shading

+

Keeping the project modular and easy to build is essential. In the past, there were some driver +modules which would not play well together in the same runtime due to JNI or JNA level artifact +conflicts. Guava, for example was used variously across many drivers and was an unending source +of dependency conflicts.

+

Going forward, any module or dependency which requires shading in order to work with the other +modules that do not will not be included in the project. This is a necessary minimum standard +to protect the sanity of the code base as well as the developers who work on it.

+

JPMS Modular jars

+

Ideally, any dependencies which are added have the necessary minimum module information to +function as a JPMS modular jar. This is not requiring the full adoption of JPMS. It is a +fairly minor task to make your artifacts work this way.

+

Logging Subsystems

+

The standard logging implementation in NoSQLBench is Log4J2. This was used because of its +extensive runtime configuration support. Further, API stub implementations for SLF4J and others +are included, but only using the later (JPMS-friendly) versions. Included modules should not +implement their own logging subsystem, but instead should either use Log4J2 directly, or SLF4J +using a modern version.

+

Dependency Management

+

If you are building a new module, be sure you understand the project layout. Leverage the +existing module structure to minimize new library dependencies. If you are using a common +library, there is a good chance it is already available and under version management in the +mvn-defaults/pom.xml file. If it is not, then scan for the dependency and hoist it up to the +mvn-defaults level if that makes sense for multiple modules depending on it.

+

Abandoned Code

+

If code is contributed which needs to be maintained by a vendor or other party, there will be an +expectation that the contributor is at least willing to do bug fixes or resolve other +user-affecting issues. If a module is considered abandoned for a significant period of time, it +may be removed from the project.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/project-standards/index.html b/dev-guide/project-standards/index.html new file mode 100644 index 000000000..15626a238 --- /dev/null +++ b/dev-guide/project-standards/index.html @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + Project Structure | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

NoSQLBench is a large project. It has a few basic layers of functionality which nest together +like a system of modules and interfaces:

+
    +
  • Core APIs +
      +
    • Annotations and Processors
    • +
    +
  • +
  • Core Runtime
  • +
  • Virtual Data Subsystem
  • +
  • Extensions and Plugins
  • +
  • Driver Adapters
  • +
+

SPI and Modules

+

Nearly all of the functionality in NoSQLBench is wired together at runtime through a service +discovery mechanism. This allows modules to be bundled within the project and packaged together +as needed. At runtime, when a particular set of components is called up to be used together, the +runtime uses Java's SPI mechanism to discover and map them by a name, called a selector.

+

You will see this throughout the project in the form of a @Service(...) annotation. Any +component withing the code base which needs to be realized at runtime must have this. The +built-in annotation processors do the packing work to put these into the standard service manifest +format.

+

Driver Adapters

+

If you are building a driver adapter, you don't need to understand the whole project structure. +You simply need to implement the DriverAdapter interface. You only need the adapters-api +module as an upstream dependency.

+

Insert Module Graph Here

+

This will be a visual of all the core modules.

+

(Java) Package Naming

+

All of the modules in the project follow a minimum structural standard. The internal package +names must have the prefix io.nosqlbench.[module-name] where the module name has its +non-words replaced with package boundaries.

+

This means that module named adapter-diag lives in a directory under the main project of the +same name. It has a package named io.nosqlbench.adapter.diag in which all of its driver code +resides.

+

This makes it easy to know what module any package is part of simply from the name.

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/dev-guide/project-standards/project-structure/index.html b/dev-guide/project-standards/project-structure/index.html new file mode 100644 index 000000000..e9e3b6132 --- /dev/null +++ b/dev-guide/project-standards/project-structure/index.html @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + Project Structure | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

NoSQLBench is a large project. It has a few basic layers of functionality which nest together +like a system of modules and interfaces:

+
    +
  • Core APIs +
      +
    • Annotations and Processors
    • +
    +
  • +
  • Core Runtime
  • +
  • Virtual Data Subsystem
  • +
  • Extensions and Plugins
  • +
  • Driver Adapters
  • +
+

SPI and Modules

+

Nearly all of the functionality in NoSQLBench is wired together at runtime through a service +discovery mechanism. This allows modules to be bundled within the project and packaged together +as needed. At runtime, when a particular set of components is called up to be used together, the +runtime uses Java's SPI mechanism to discover and map them by a name, called a selector.

+

You will see this throughout the project in the form of a @Service(...) annotation. Any +component withing the code base which needs to be realized at runtime must have this. The +built-in annotation processors do the packing work to put these into the standard service manifest +format.

+

Driver Adapters

+

If you are building a driver adapter, you don't need to understand the whole project structure. +You simply need to implement the DriverAdapter interface. You only need the adapters-api +module as an upstream dependency.

+

Insert Module Graph Here

+

This will be a visual of all the core modules.

+

(Java) Package Naming

+

All of the modules in the project follow a minimum structural standard. The internal package +names must have the prefix io.nosqlbench.[module-name] where the module name has its +non-words replaced with package boundaries.

+

This means that module named adapter-diag lives in a directory under the main project of the +same name. It has a package named io.nosqlbench.adapter.diag in which all of its driver code +resides.

+

This makes it easy to know what module any package is part of simply from the name.

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/elasticlunr.min.js b/elasticlunr.min.js new file mode 100644 index 000000000..79dad65f5 --- /dev/null +++ b/elasticlunr.min.js @@ -0,0 +1,10 @@ +/** + * elasticlunr - http://weixsong.github.io + * Lightweight full-text search engine in Javascript for browser search and offline search. - 0.9.6 + * + * Copyright (C) 2017 Oliver Nightingale + * Copyright (C) 2017 Wei Song + * MIT Licensed + * @license + */ +!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/favicon-16x16.png b/favicon-16x16.png new file mode 100644 index 000000000..90bb7629e Binary files /dev/null and b/favicon-16x16.png differ diff --git a/favicon-32x32.png b/favicon-32x32.png new file mode 100644 index 000000000..f8b4cadc8 Binary files /dev/null and b/favicon-32x32.png differ diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 000000000..ec7a66234 Binary files /dev/null and b/favicon.ico differ diff --git a/font.css b/font.css new file mode 100644 index 000000000..498e49ba9 --- /dev/null +++ b/font.css @@ -0,0 +1 @@ +@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-ExtraLight.woff2");font-weight:200;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-Light.woff2");font-weight:300;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-Regular.woff2");font-weight:400;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-Medium.woff2");font-weight:500;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-SemiBold.woff2");font-weight:600;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-Bold.woff2");font-weight:700;font-display:swap}@font-face{font-family:"BerkelyMono";src:url("font/BerkeleyMono-Regular.woff2");font-weight:400;font-display:swap}@font-face{font-family:"BerkelyMono";src:url("font/BerkeleyMono-Bold.woff2");font-weight:600;font-display:swap}@font-face{font-family:"BerkelyMono";src:url("font/BerkeleyMono-Regular.woff2");font-weight:600;font-style:italic;font-display:swap}@font-face{font-family:"BerkelyMono";src:url("font/BerkeleyMono-Regular.woff2");font-weight:400;font-display:swap}@font-face{font-family:"BerkelyMonoVariable";src:url("font/BerkeleyMonoVariable-Regular.woff2");font-weight:400;font-display:swap}@font-face{font-family:"BerkelyMonoVariable";src:url("font/BerkeleyMonoVariable-Italic.woff2");font-weight:400;font-style:italic;font-display:swap} \ No newline at end of file diff --git a/font/Abridge.woff2 b/font/Abridge.woff2 new file mode 100644 index 000000000..2ce019300 Binary files /dev/null and b/font/Abridge.woff2 differ diff --git a/font/Arimo-Bold.woff2 b/font/Arimo-Bold.woff2 new file mode 100644 index 000000000..cff36d976 Binary files /dev/null and b/font/Arimo-Bold.woff2 differ diff --git a/font/Arimo-Italic.woff2 b/font/Arimo-Italic.woff2 new file mode 100644 index 000000000..2adf45963 Binary files /dev/null and b/font/Arimo-Italic.woff2 differ diff --git a/font/Arimo.woff2 b/font/Arimo.woff2 new file mode 100644 index 000000000..f10b6c5a8 Binary files /dev/null and b/font/Arimo.woff2 differ diff --git a/font/BerkeleyMono-Bold.woff b/font/BerkeleyMono-Bold.woff new file mode 100644 index 000000000..c24e9f105 Binary files /dev/null and b/font/BerkeleyMono-Bold.woff differ diff --git a/font/BerkeleyMono-Bold.woff2 b/font/BerkeleyMono-Bold.woff2 new file mode 100644 index 000000000..27dc96c06 Binary files /dev/null and b/font/BerkeleyMono-Bold.woff2 differ diff --git a/font/BerkeleyMono-BoldItalic.woff b/font/BerkeleyMono-BoldItalic.woff new file mode 100644 index 000000000..42b2b2a36 Binary files /dev/null and b/font/BerkeleyMono-BoldItalic.woff differ diff --git a/font/BerkeleyMono-BoldItalic.woff2 b/font/BerkeleyMono-BoldItalic.woff2 new file mode 100644 index 000000000..a67bd7536 Binary files /dev/null and b/font/BerkeleyMono-BoldItalic.woff2 differ diff --git a/font/BerkeleyMono-Italic.woff b/font/BerkeleyMono-Italic.woff new file mode 100644 index 000000000..2e9eee868 Binary files /dev/null and b/font/BerkeleyMono-Italic.woff differ diff --git a/font/BerkeleyMono-Italic.woff2 b/font/BerkeleyMono-Italic.woff2 new file mode 100644 index 000000000..15f39cd0a Binary files /dev/null and b/font/BerkeleyMono-Italic.woff2 differ diff --git a/font/BerkeleyMono-Regular.woff b/font/BerkeleyMono-Regular.woff new file mode 100644 index 000000000..9ca3682d1 Binary files /dev/null and b/font/BerkeleyMono-Regular.woff differ diff --git a/font/BerkeleyMono-Regular.woff2 b/font/BerkeleyMono-Regular.woff2 new file mode 100644 index 000000000..9b34b7f5a Binary files /dev/null and b/font/BerkeleyMono-Regular.woff2 differ diff --git a/font/BerkeleyMonoVariable-Italic.woff b/font/BerkeleyMonoVariable-Italic.woff new file mode 100644 index 000000000..4656d222a Binary files /dev/null and b/font/BerkeleyMonoVariable-Italic.woff differ diff --git a/font/BerkeleyMonoVariable-Italic.woff2 b/font/BerkeleyMonoVariable-Italic.woff2 new file mode 100644 index 000000000..039512b97 Binary files /dev/null and b/font/BerkeleyMonoVariable-Italic.woff2 differ diff --git a/font/BerkeleyMonoVariable-Regular.woff b/font/BerkeleyMonoVariable-Regular.woff new file mode 100644 index 000000000..50ca829df Binary files /dev/null and b/font/BerkeleyMonoVariable-Regular.woff differ diff --git a/font/BerkeleyMonoVariable-Regular.woff2 b/font/BerkeleyMonoVariable-Regular.woff2 new file mode 100644 index 000000000..5f580d519 Binary files /dev/null and b/font/BerkeleyMonoVariable-Regular.woff2 differ diff --git a/font/FiraCode.woff2 b/font/FiraCode.woff2 new file mode 100644 index 000000000..41a8ef195 Binary files /dev/null and b/font/FiraCode.woff2 differ diff --git a/font/Lato-Bold.woff2 b/font/Lato-Bold.woff2 new file mode 100644 index 000000000..11de83fea Binary files /dev/null and b/font/Lato-Bold.woff2 differ diff --git a/font/Lato-Italic.woff2 b/font/Lato-Italic.woff2 new file mode 100644 index 000000000..851630ff8 Binary files /dev/null and b/font/Lato-Italic.woff2 differ diff --git a/font/Lato.woff2 b/font/Lato.woff2 new file mode 100644 index 000000000..ff60934dd Binary files /dev/null and b/font/Lato.woff2 differ diff --git a/font/README.md b/font/README.md new file mode 100644 index 000000000..862fb2616 --- /dev/null +++ b/font/README.md @@ -0,0 +1,2 @@ +Some of the fonts in this theme are licensed to a project maintainer. +If you do not have licenses to these files, do not use them. diff --git a/font/ReadexPro-ExtraLight.woff2 b/font/ReadexPro-ExtraLight.woff2 new file mode 100644 index 000000000..18e044d96 Binary files /dev/null and b/font/ReadexPro-ExtraLight.woff2 differ diff --git a/font/ReadexPro-Light.woff2 b/font/ReadexPro-Light.woff2 new file mode 100644 index 000000000..4eb6efbb0 Binary files /dev/null and b/font/ReadexPro-Light.woff2 differ diff --git a/font/ReadexPro-Medium.woff2 b/font/ReadexPro-Medium.woff2 new file mode 100644 index 000000000..4f0ec3cbd Binary files /dev/null and b/font/ReadexPro-Medium.woff2 differ diff --git a/font/ReadexPro-Regular.woff2 b/font/ReadexPro-Regular.woff2 new file mode 100644 index 000000000..d6efca53b Binary files /dev/null and b/font/ReadexPro-Regular.woff2 differ diff --git a/font/ReadexPro-SemiBold.woff2 b/font/ReadexPro-SemiBold.woff2 new file mode 100644 index 000000000..828a0374f Binary files /dev/null and b/font/ReadexPro-SemiBold.woff2 differ diff --git a/font/ReadexPro-bold.woff2 b/font/ReadexPro-bold.woff2 new file mode 100644 index 000000000..4d9f1eb48 Binary files /dev/null and b/font/ReadexPro-bold.woff2 differ diff --git a/font/Roboto-Bold.woff2 b/font/Roboto-Bold.woff2 new file mode 100644 index 000000000..771fbeccc Binary files /dev/null and b/font/Roboto-Bold.woff2 differ diff --git a/font/Roboto-Italic.woff2 b/font/Roboto-Italic.woff2 new file mode 100644 index 000000000..e1b7a79f9 Binary files /dev/null and b/font/Roboto-Italic.woff2 differ diff --git a/font/Roboto.woff2 b/font/Roboto.woff2 new file mode 100644 index 000000000..020729ef8 Binary files /dev/null and b/font/Roboto.woff2 differ diff --git a/fonts/BerkelyMono.css b/fonts/BerkelyMono.css new file mode 100644 index 000000000..c79ac9d81 --- /dev/null +++ b/fonts/BerkelyMono.css @@ -0,0 +1 @@ +@font-face{font-family:"BerkelyMono";src:url("font/BerkeleyMono-Regular.woff2");font-weight:400;font-display:swap}@font-face{font-family:"BerkelyMono";src:url("font/BerkeleyMono-Bold.woff2");font-weight:600;font-display:swap}@font-face{font-family:"BerkelyMono";src:url("font/BerkeleyMono-Regular.woff2");font-weight:600;font-style:italic;font-display:swap}@font-face{font-family:"BerkelyMono";src:url("font/BerkeleyMono-Regular.woff2");font-weight:400;font-display:swap}@font-face{font-family:"BerkelyMonoVariable";src:url("font/BerkeleyMonoVariable-Regular.woff2");font-weight:400;font-display:swap}@font-face{font-family:"BerkelyMonoVariable";src:url("font/BerkeleyMonoVariable-Italic.woff2");font-weight:400;font-style:italic;font-display:swap} \ No newline at end of file diff --git a/fonts/KaTeX_AMS-Regular.woff2 b/fonts/KaTeX_AMS-Regular.woff2 new file mode 100644 index 000000000..0acaaff03 Binary files /dev/null and b/fonts/KaTeX_AMS-Regular.woff2 differ diff --git a/fonts/KaTeX_Caligraphic-Bold.woff2 b/fonts/KaTeX_Caligraphic-Bold.woff2 new file mode 100644 index 000000000..f390922ec Binary files /dev/null and b/fonts/KaTeX_Caligraphic-Bold.woff2 differ diff --git a/fonts/KaTeX_Caligraphic-Regular.woff2 b/fonts/KaTeX_Caligraphic-Regular.woff2 new file mode 100644 index 000000000..75344a1f9 Binary files /dev/null and b/fonts/KaTeX_Caligraphic-Regular.woff2 differ diff --git a/fonts/KaTeX_Fraktur-Bold.woff2 b/fonts/KaTeX_Fraktur-Bold.woff2 new file mode 100644 index 000000000..395f28bea Binary files /dev/null and b/fonts/KaTeX_Fraktur-Bold.woff2 differ diff --git a/fonts/KaTeX_Fraktur-Regular.woff2 b/fonts/KaTeX_Fraktur-Regular.woff2 new file mode 100644 index 000000000..735f6948d Binary files /dev/null and b/fonts/KaTeX_Fraktur-Regular.woff2 differ diff --git a/fonts/KaTeX_Main-Bold.woff2 b/fonts/KaTeX_Main-Bold.woff2 new file mode 100644 index 000000000..ab2ad21da Binary files /dev/null and b/fonts/KaTeX_Main-Bold.woff2 differ diff --git a/fonts/KaTeX_Main-BoldItalic.woff2 b/fonts/KaTeX_Main-BoldItalic.woff2 new file mode 100644 index 000000000..5931794de Binary files /dev/null and b/fonts/KaTeX_Main-BoldItalic.woff2 differ diff --git a/fonts/KaTeX_Main-Italic.woff2 b/fonts/KaTeX_Main-Italic.woff2 new file mode 100644 index 000000000..b50920e13 Binary files /dev/null and b/fonts/KaTeX_Main-Italic.woff2 differ diff --git a/fonts/KaTeX_Main-Regular.woff2 b/fonts/KaTeX_Main-Regular.woff2 new file mode 100644 index 000000000..eb24a7ba2 Binary files /dev/null and b/fonts/KaTeX_Main-Regular.woff2 differ diff --git a/fonts/KaTeX_Math-BoldItalic.woff2 b/fonts/KaTeX_Math-BoldItalic.woff2 new file mode 100644 index 000000000..29657023a Binary files /dev/null and b/fonts/KaTeX_Math-BoldItalic.woff2 differ diff --git a/fonts/KaTeX_Math-Italic.woff2 b/fonts/KaTeX_Math-Italic.woff2 new file mode 100644 index 000000000..215c143fd Binary files /dev/null and b/fonts/KaTeX_Math-Italic.woff2 differ diff --git a/fonts/KaTeX_SansSerif-Bold.woff2 b/fonts/KaTeX_SansSerif-Bold.woff2 new file mode 100644 index 000000000..cfaa3bda5 Binary files /dev/null and b/fonts/KaTeX_SansSerif-Bold.woff2 differ diff --git a/fonts/KaTeX_SansSerif-Italic.woff2 b/fonts/KaTeX_SansSerif-Italic.woff2 new file mode 100644 index 000000000..349c06dc6 Binary files /dev/null and b/fonts/KaTeX_SansSerif-Italic.woff2 differ diff --git a/fonts/KaTeX_SansSerif-Regular.woff2 b/fonts/KaTeX_SansSerif-Regular.woff2 new file mode 100644 index 000000000..a90eea85f Binary files /dev/null and b/fonts/KaTeX_SansSerif-Regular.woff2 differ diff --git a/fonts/KaTeX_Script-Regular.woff2 b/fonts/KaTeX_Script-Regular.woff2 new file mode 100644 index 000000000..b3048fc11 Binary files /dev/null and b/fonts/KaTeX_Script-Regular.woff2 differ diff --git a/fonts/KaTeX_Size1-Regular.woff2 b/fonts/KaTeX_Size1-Regular.woff2 new file mode 100644 index 000000000..c5a8462fb Binary files /dev/null and b/fonts/KaTeX_Size1-Regular.woff2 differ diff --git a/fonts/KaTeX_Size2-Regular.woff2 b/fonts/KaTeX_Size2-Regular.woff2 new file mode 100644 index 000000000..e1bccfe24 Binary files /dev/null and b/fonts/KaTeX_Size2-Regular.woff2 differ diff --git a/fonts/KaTeX_Size3-Regular.woff2 b/fonts/KaTeX_Size3-Regular.woff2 new file mode 100644 index 000000000..249a28662 Binary files /dev/null and b/fonts/KaTeX_Size3-Regular.woff2 differ diff --git a/fonts/KaTeX_Size4-Regular.woff2 b/fonts/KaTeX_Size4-Regular.woff2 new file mode 100644 index 000000000..680c13085 Binary files /dev/null and b/fonts/KaTeX_Size4-Regular.woff2 differ diff --git a/fonts/KaTeX_Typewriter-Regular.woff2 b/fonts/KaTeX_Typewriter-Regular.woff2 new file mode 100644 index 000000000..771f1af70 Binary files /dev/null and b/fonts/KaTeX_Typewriter-Regular.woff2 differ diff --git a/fonts/ReadexPro.css b/fonts/ReadexPro.css new file mode 100644 index 000000000..ffab44a20 --- /dev/null +++ b/fonts/ReadexPro.css @@ -0,0 +1 @@ +@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-ExtraLight.woff2");font-weight:200;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-Light.woff2");font-weight:300;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-Regular.woff2");font-weight:400;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-Medium.woff2");font-weight:500;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-SemiBold.woff2");font-weight:600;font-display:swap}@font-face{font-family:"ReadexPro";src:url("font/ReadexPro-Bold.woff2");font-weight:700;font-display:swap} \ No newline at end of file diff --git a/getting-started/00-get-nosqlbench/index.html b/getting-started/00-get-nosqlbench/index.html new file mode 100644 index 000000000..1d974cad5 --- /dev/null +++ b/getting-started/00-get-nosqlbench/index.html @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + 00 Download | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

NoSQLBench version 5 is packaged directly as a Linux binary named +nb5 +and as an executable Java 17 jar named +nb5.jar +. All releases are available at +[NoSQLBench Releases]. The Linux binary is +recommended, since it comes with its own JVM and eliminates the need to manage +Java downloads.

+

Requirements

+

The nb5 binary requires Linux and a system with a working +FUSE library. Most modern distributions +have this out of the box.

+

nb5.jar is not particular about what system you run it on, as long as you have java 17 or newer.1

+

Download Scripts

+

Get the latest nb5 binary

+
# download the latest nb5 binary and make it executable
+curl -L -O https://github.com/nosqlbench/nosqlbench/releases/latest/download/nb5
+chmod +x nb5
+./nb5 --version
+
+

👉 If after downloading and executing nb, you get an error, please consult the +AppImage troubleshooting page.

+

Get the latest nb5 jar

+
# download the latest nb5 jar
+curl -L -O https://github.com/nosqlbench/nosqlbench/releases/latest/download/nb5.jar
+java -jar nb5.jar --version
+
+

This documentation assumes you are using the Linux binary initiating NoSqlBench commands with +./nb. If you are using the jar, just replace ./nb with java -jar nb.jar when running +commands. If you are using the jar version, Java 17 is recommended, and will be required soon.

+

Running nb5

+

To run a simple built-in workload run:

+
./nb5 examples/bindings-basics
+
+

This runs a built-in scenario located in the workload template named 'bindings-basics'. The +file that the scenario is defined in is called the workload template. The scenario is named +default, so you don't even have to specify it here. But you could, as

+
./nb5 examples/bindings-basics default
+
+

This will be explained further in Scenarios.

+

Options

+

Here is a more detailed command which demonstrates how customizable nb5 is:

+
1./nb5 examples/bindings-basics default \ +
2 filename=exampledata.out \ +
3 format=csv \ +
4 cycles=10000 \ +
5 rate=100 \ +
6 --progress console:1s +
+

Each line does something specific:

+
    +
  1. Starts the scenario named default from the workload template examples/binding-basics.
  2. +
  3. Sets the filename parameter (part of the stdout driver) to exampledata.out.
  4. +
  5. Sets the output format (part of the stdout driver) to CSV.
  6. +
  7. Sets the number of cycles to run to 10000, short for 0..10000, which represents 0 through 9999.
  8. +
  9. Sets the cycle rate to 100 per second.
  10. +
  11. Tells nb5 to report activity progress to the console every second.
  12. +
+

Dashboards

+

You can use --docker-metrics to stand up a live metrics dashboard at port 3000.

+

👉In order to use the --docker-metrics option, you need to have docker installed on your +local system, and your user must have permissions to use it. Typically, this means that your user +has been added to the docker group with a command like sudo usermod $USER -g docker.

+

Here is the above command, with built-in dashboarding enabled:

+
./nb5 examples/bindings-basics default \
+ filename=exampledata.out \
+ format=csv \
+ cycles=10000 \
+ rate=100 \
+ --progress console:1s \
+ --docker-metrics
+
+
1 +

The version scheme for NoSQLBench is [major]-[java-lts]-[minor], so nb5 version 5.17.1 +requires java version 17, which is the latest LTS Java release.

+
+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/getting-started/01-test-target/index.html b/getting-started/01-test-target/index.html new file mode 100644 index 000000000..69225d148 --- /dev/null +++ b/getting-started/01-test-target/index.html @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + 01 Test Target | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

You need a target system to run your test against. If you already have one, you can skip this +section. This tutorial assumes you are testing against a CQL based system. If you need to start +something up, you have some options:

+ +

Run DSE in docker

+

You can start an instance of DSE with this one-liner:

+
docker run -e DS_LICENSE=accept --name my-dse -p 9042:9042 -d datastax/dse-server:6.8.17-ubi7
+
+

👉 If you want to see system-level metrics from your cluster, it is possible to get these as +well as Apache Cassandra level metrics by using the DSE Metrics Collector (if using DSE), or +by setting up a metrics feed to the Prometheus instance in your local docker stack. You can +read the +DSE Metrics Collector docs.

+

Run an Astra Cluster

+

You can choose to run a serverless cluster through DataStax AstraDB for functional +testing. For tips on how to set up an Astra DB instance, you can check out this +[Astra Tutorial].

+

If you plan to follow along this tutorial using AstraDB, you will need to follow these steps:

+
    +
  • +

    Add a keyspace named 'baselines' to your Astra Database (this is because Astra does not +support adding keyspaces through CQLSH), see the following for details:

    +

    Keyspace

    +
  • +
  • +

    In the connect menu of your Astra DB Instance, download your secure connect bundle and make note of its path.

    +
  • +
  • +

    In your organization settings, you need to generate a Read/Write token and make note of the Client ID and Client Secret. +see below for details:

    +

    Token

    +
  • +
+

Configuring for AstraDB

+

The following config pattern is often helpful for configuring NB5 for Astra:

+
... driver=cqld4 scb=<secureconnectbundle> userfile=<userfile> passfile=<passfile> ...
+
+

This allows you to keep the credentials in files so that they aren't exposed on the console or +in log files. It is also convenient to put these into a subdirectory together when you are +testing multiple systems, for example:

+
... driver=cqld4 scb=creds1/scb-somename.zip userfile=creds1/userfile passfile=creds1/passfile ...
+
+

This makes it easy to manage credentials for multiple endpoints when all you have to do is +reference a different directory.

+

👉 It might be helpful to refer back to this section later when you learn about activity parameters.

+

Run Apache Cassandra in Docker

+

https://hub.docker.com/_/cassandra

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/getting-started/02-scenarios/index.html b/getting-started/02-scenarios/index.html new file mode 100644 index 000000000..22931d8d0 --- /dev/null +++ b/getting-started/02-scenarios/index.html @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + 02 Scenarios | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Scenarios

+

👉 The commands in this section are examples to show you how the command line works with nb5.

+

Run a scenario

+

To run a simple built-in scenario, run one of these:

+
./nb5 cql-keyvalue host=<addr> localdc=<localdcname>
+
+

To run the same scenario against Astra, add the credentials and secure connect bundle:

+
./nb5 cql-keyvalue scb=<scb.zip> userfile=<file-with-client-id> passfile=<file-with-client-secret> ...
+
+

👉 Regardless of what form you are using for the tutorial, you'll want to keep these options +handy. You may want to drop them in anywhere you see a ... below.

+

This example shows how you can call on a completely pre-built workload template by simply using it +as the first argument. cql-keyvalue is actually a workload description hosted within the binary +(or jar), at activities/cql-keyvalue.yaml. You do have to provide some endpoint and authentication +details, but these should not be added to the workload template anyway.

+

This also captures some workflow for us. It takes care of:

+
    +
  1. Initializing your schema.
  2. +
  3. Loading background data to provide a realistic scenario.
  4. +
  5. Running a main activity against the background data.
  6. +
+

How this works is explained in more depth throughout this guide. For now, just know that all of +these details are completely open for you to change simply by modifying the workload template.

+

Discover Scenarios

+

To get a list of built-in scenarios run:

+
./nb5 --list-scenarios
+
+

If you want a simple list of workload templates which contain named scenarios, run:

+
./nb5 --list-workloads
+
+

These are distinct commands, because you can have multiple named scenarios in a given workload +template. The commands above scan for all known sources (bundled within or locally on your +filesystem) and provide a list of available scenarios or their containing workload templates. +The example works above when we specify the workload, because it has a default scenario built in.

+

👉 These commands will include workloads that were shipped with nb5 and workloads in your local +directory. To learn more about how to design custom workloads see +[Workloads 101].

+

You can also include the example path prefix which will show many more:

+
./nb5 --list-workloads --include examples
+
+

When learning about bindings, it is recommended for first time users to use the above command to +find lots of examples for inspiration.

+

Compose scenarios

+

We could easily ask nb5 to run a different named scenario of our choosing by running this:

+
# Run a specific named scenario
+./nb5 cql-keyvalue astra ...
+
+# Run a specific step of a specific named scenario
+./nb5 cql-keyvalue astra.schema ...
+
+# Run a series of specific steps from specific named scenarios
+./nb5 cql-keyvalue astra.schema astra.rampup ...
+
+

If you don't specify which steps to run, they are all run serially, in the order they are defined. +If you don't specify which named scenario to run, default is used.

+

Example Activities

+

The first examples above show you how to call whole scenarios, which contain multiple steps and +pre-configured defaults. You can also skip using named scenarios and invoke the activities that +they invoke directly.

+
+

You can skip the next part of this page if you want to just use built-in scenarios. If you +want to know how to drill down to the steps and test them individually, continue on.

+
+

Create a schema

+

We will start by creating a simple schema in the database:

+
# ( We'll use SQL highlighting for our CQL )
+    
+CREATE KEYSPACE baselines
+ WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}
+ AND durable_writes = true;
+
+CREATE TABLE baselines.keyvalue (
+    key text PRIMARY KEY,
+    value text
+)
+
+

From your command line, go ahead and execute the following command, replacing +the ... with that of one of your database nodes. Alternately, if using Astra, +use the options described in the test target section.

+
./nb5 run driver=cqld4 workload=cql-keyvalue tags=block:schema ...
+
+

This follows the basic command pattern of all nb5 commands. The first bare word is a command, +and all assignments after it are parameters to that command. The run command is short for "run +an activity".

+

Let's break down each of those command line options.

+

run tells NoSQLBench to run an activity.

+

driver=... is used to specify the activity type (driver). In this case +we are using cqld4, which tells NoSQLBench to use the DataStax Java Driver +and execute CQL statements against a database.

+

workload=... is used to specify the workload definition file that defines the activity. In +this example, we use cql-keyvalue which is a pre-built workload that is packaged with +NoSQLBench.

+

tags=block:schema tells NoSQLBench to run the op templates from a block that is +tagged with block:schema. In this example, that is the DDL portion of the cql-keyvalue +workload.

+

... should be the endpoint and authentication details that you used from the first example.

+

If you like, you can verify the result of this command by describing your +keyspace in cqlsh or DataStax Studio with +DESCRIBE KEYSPACE baselines.

+

Load some data

+

Before running a test of typical access patterns where you want to capture the results, you +need to make the test more interesting than loading an empty table. For this, we use the +rampup activity.

+

Before sending our test writes to the database, we will use the stdout driver, so we can see +what NoSQLBench is generating for CQL statements.

+

Go ahead and execute the following command:

+
./nb5 run driver=stdout workload=cql-keyvalue
+
+

You should see 10 of the following statements in your console

+
insert into baselines.keyvalue (key, value) values (0,382062539);
+insert into baselines.keyvalue (key, value) values (1,774912474);
+insert into baselines.keyvalue (key, value) values (2,949364593);
+insert into baselines.keyvalue (key, value) values (3,352527683);
+insert into baselines.keyvalue (key, value) values (4,351686621);
+insert into baselines.keyvalue (key, value) values (5,114304900);
+insert into baselines.keyvalue (key, value) values (6,439790106);
+insert into baselines.keyvalue (key, value) values (7,564330072);
+insert into baselines.keyvalue (key, value) values (8,296173906);
+insert into baselines.keyvalue (key, value) values (9,97405552);
+
+

NoSQLBench deterministically generates data, so the generated values will be the same from run to run.

+

Now we are ready to write some data to our database. Go ahead and execute the following from your command line:

+
./nb5 run driver=cql workload=cql-keyvalue tags=block:rampup cycles=100k ... --progress console:1s
+
+

Note the differences between this and the command that we used to generate the schema.

+

tags=block:rampup is running the yaml block in cql-keyvalue that has only INSERT statements.

+

cycles=100k will run a total of 100,000 operations, in this case, +100,000 writes. You will want to pick an appropriately large number of +cycles in actual testing to make your main test meaningful.

+

👉 The cycles parameter is not just a quantity. It is a range of values. +The cycles=n format is short for +cycles=0..n, which makes cycles a zero-based range. For example, +cycles=5 means that the activity will use cycles 0,1,2,3,4, but not 5. The +reason for this is explained in detail in the Activity Parameters section.

+

These parameters are explained in detail in the section on Activity +Parameters.

+

--progress console:1s will print the progression of the run to the +console every 1 second.

+

You should see output that looks like this

+
cql-keyvalue-astra (remaining,active,completed)=(99377,50,623) 001%
+cql-keyvalue-astra (remaining,active,completed)=(98219,50,1782) 002%
+cql-keyvalue-astra (remaining,active,completed)=(97009,50,2991) 003%
+cql-keyvalue-astra (remaining,active,completed)=(95856,50,4153) 004%
+cql-keyvalue-astra (remaining,active,completed)=(94653,50,5347) 005%
+cql-keyvalue-astra (remaining,active,completed)=(93494,50,6506) 007%
+cql-keyvalue-astra (remaining,active,completed)=(92254,50,7746) 008%
+cql-keyvalue-astra (remaining,active,completed)=(91024,50,8976) 009%
+cql-keyvalue-astra (remaining,active,completed)=(89800,50,10200) 010%
+cql-keyvalue-astra (remaining,active,completed)=(88588,50,11416) 011%
+cql-keyvalue-astra (remaining,active,completed)=(87378,50,12622) 013%
+...
+cql-keyvalue-astra (remaining,active,completed)=(0,0,100000) 100% (last report)
+
+

Run the main activity

+

Now that we have a base dataset of 100K rows in the database, we will now +run a mixed read / write workload, by default this runs a 50% read / 50% +write workload. This time we will add a -v option for more context.

+
 ./nb5 run driver=cql workload=cql-keyvalue tags='block:main.*' \
+ cycles=50k cyclerate=5000 threads=50 --progress console:1s ...
+
+

You can go ahead and paste your activity parameters on the end. nb5 will always parse out the +global options (those with a dash) and leave your commands intact.

+

You should see output that looks like this:

+
Configured scenario log at ...
+cql-keyvalue (remaining,active,completed)=(47168,1,2832) 006%
+cql-keyvalue (remaining,active,completed)=(42059,2,7941) 016%
+cql-keyvalue (remaining,active,completed)=(37107,2,12895) 026%
+cql-keyvalue (remaining,active,completed)=(32060,1,17941) 036%
+cql-keyvalue (remaining,active,completed)=(27060,2,22940) 046%
+cql-keyvalue (remaining,active,completed)=(22058,2,27943) 056%
+cql-keyvalue (remaining,active,completed)=(17058,1,32942) 066%
+cql-keyvalue (remaining,active,completed)=(12059,2,37942) 076%
+cql-keyvalue (remaining,active,completed)=(7059,1,42942) 086%
+cql-keyvalue (remaining,active,completed)=(2060,1,47941) 096%
+cql-keyvalue (remaining,active,completed)=(0,0,50000) 100% (last report)
+
+

We have a few new command line options here:

+

tags=block:main is using a new block in our workload template that contains both read and +write queries.

+

threads=50 is an important one. The default for NoSQLBench is to run with a single thread. +This is not adequate for workloads that will be running many operations, so threads is used as +a way to increase concurrency on the client side.

+

cyclerate=5000 is used to control the operations per second that are initiated by NoSQLBench. +This command line option is the primary means to rate limit the workload and here we are +running at 5000 ops/sec.

+

Now What?

+

Note in the above output, we +see Configured scenario log at logs/scenario_20230113_135200_029.log.

+

By default, NoSQLBench records the metrics from the run in this file, we will go into detail +about these metrics in the next section example results.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/getting-started/03-example-results/index.html b/getting-started/03-example-results/index.html new file mode 100644 index 000000000..51049be63 --- /dev/null +++ b/getting-started/03-example-results/index.html @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + 03 Results | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

We just ran a very simple workload against our database. In that example, we saw that nb5 +writes to a log file, and it is in that log file where the most basic form of metrics are displayed.

+

Log File Metrics

+

For our previous run, we saw that NoSQLBench was writing to a +file like logs/scenario_20190812_154431_028.log

+

Even when you don't configure NoSQLBench to write its metrics to another location, it will +periodically report all the metrics to the log file. At the end of a scenario, before NoSQLBench +shuts down, it will flush the partial reporting interval again to the logs. This means you can +always look in the logs for metrics information.

+

WARNING: +If you look in the logs for metrics, be aware that the last report will only contain a partial +interval of results. When looking at the last partial window, only metrics which average over time +or which compute the mean for the whole test will be meaningful.

+

Below is a sample of the log that gives us our basic metrics. There is a lot to digest here, for now +we will only focus a subset of the most important metrics.

+
2019-08-12 15:46:00,274 INFO [main] i.e.c.ScenarioResult [ScenarioResult.java:48] -- BEGIN METRICS DETAIL --
+2019-08-12 15:46:00,294 INFO [main] i.e.c.ScenarioResult [Slf4jReporter.java:373] type=GAUGE, name=cql-keyvalue.cycles.config.burstrate, value=5500.0
+2019-08-12 15:46:00,295 INFO [main] i.e.c.ScenarioResult [Slf4jReporter.java:373] type=GAUGE, name=cql-keyvalue.cycles.config.cyclerate, value=5000.0
+2019-08-12 15:46:00,295 INFO [main] i.e.c.ScenarioResult [Slf4jReporter.java:373] type=GAUGE, name=cql-keyvalue.cycles.waittime, value=3898782735
+2019-08-12 15:46:00,298 INFO [main] i.e.c.ScenarioResult [Slf4jReporter.java:373] type=HISTOGRAM, name=cql-keyvalue.resultset-size, count=100000, min=0, max=1, mean=8.0E-5, stddev=0.008943914131967056, median=0.0, p75=0.0, p95=0.0, p98=0.0, p99=0.0, p999=0.0
+2019-08-12 15:46:01,703 INFO [main] i.e.c.ScenarioResult [ScenarioResult.java:56] -- END METRICS DETAIL --
+
+

The log contains lots of information on metrics, but this is obviously not the most desirable way +to consume metrics from NoSQLBench.

+

We recommend that you use one of these methods, according to your environment or tooling available:

+
    +
  1. --docker-metrics with a local docker-based grafana dashboard (See the section on Docker Based +Metrics)
  2. +
  3. --docker-metrics-at <addr> with a remote docker-based grafana dashboard that you have +previously +set up.
  4. +
  5. Send your metrics to a dedicated graphite server with --report-graphite-to graphitehost
  6. +
  7. Record your metrics to local CSV files with --report-csv-to my_metrics_dir
  8. +
  9. Record your metrics to HDR logs with --log-histograms my_hdr_metrics.log
  10. +
  11. Record your metrics to a running docker metrics system with --docker-metrics-at <host>
  12. +
+

See the command line reference for details on how to route your metrics to a metrics collector or +format of your preference.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/getting-started/04-reading-metrics/index.html b/getting-started/04-reading-metrics/index.html new file mode 100644 index 000000000..d63b092e8 --- /dev/null +++ b/getting-started/04-reading-metrics/index.html @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + 04 Metrics | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

A set of core metrics are provided for every workload that runs with NoSQLBench, regardless of the activity type and +protocol used. This section explains each of these metrics and shows an example of them from the log file.

+

metric: result

+

This is the primary metric that should be used to get a quick idea of the throughput and latency for a given run. It +encapsulates the entire operation life cycle ( ie. bind, execute, get result back ).

+

For this example we see that we averaged 3732 operations / second with 3.6ms 75th percentile latency and 23.9ms 99th +percentile latency. Note the raw metrics are in microseconds. This duration_unit may change depending on how a user +configures NoSQLBench, so always double-check it.

+
2019-08-12 15:46:01,310 INFO [main] i.e.c.ScenarioResult [Slf4jReporter.java:373] type=TIMER,
+ name=cql-keyvalue.result, count=100000, min=233.48, max=358596.607, mean=3732.00338612, stddev=10254.850416061185,
+ median=1874.815, p75=3648.767, p95=10115.071, p98=15855.615, p99=23916.543, p999=111292.415,
+ mean_rate=4024.0234405430424, m1=3514.053841156124, m5=3307.431472596865, m15=3268.6786509004132,
+ rate_unit=events/second, duration_unit=microseconds
+
+

metric: result-success

+

This metric shows whether there were any errors during the run. You can confirm that the count is equal to the number of +cycles for the run if you are expecting or requiring zero failed operations.

+

Here we see that all 100k of our cycles succeeded. Note that the metrics for throughput and latency here are slightly +different than the results metric simply because this is a separate timer that only includes operations which +completed with no exceptions.

+
2019-08-12 15:46:01,452 INFO [main] i.e.c.ScenarioResult [Slf4jReporter.java:373] type=TIMER,
+ name=cql-keyvalue.result-success, count=100000, min=435.168, max=358645.759, mean=3752.40990808,
+ stddev=10251.524945886964, median=1889.791, p75=3668.479, p95=10154.495, p98=15884.287, p99=24280.063,
+ p999=111443.967, mean_rate=4003.3090048756894, m1=3523.40328629036, m5=3318.8463896065778, m15=3280.480326762243,
+ rate_unit=events/second, duration_unit=microseconds
+
+

metric: resultset-size

+

For read workloads, this metric shows the size of result sent back to NoSQLBench from the server. This is useful to +confirm that you are reading rows that already exist in the database.

+
2019-08-12 15:46:00,298 INFO [main] i.e.c.ScenarioResult [Slf4jReporter.java:373] type=HISTOGRAM,
+ name=cql-keyvalue.resultset-size, count=100000, min=0, max=1, mean=8.0E-5, stddev=0.008943914131967056,
+ median=0.0, p75=0.0, p95=0.0, p98=0.0, p99=0.0, p999=0.0
+
+

metric: tries

+

NoSQLBench will retry failures 10 times by default, this is configurable via the maxtries command line option for the +cql activity type. This metric shows a histogram of the number of tries that each operation required, in this example, +there were no retries as the count is 100k.

+
2019-08-12 15:46:00,341 INFO [main] i.e.c.ScenarioResult [Slf4jReporter.java:373] type=HISTOGRAM,
+ name=cql-keyvalue.tries, count=100000, min=1, max=1, mean=1.0, stddev=0.0, median=1.0,
+ p75=1.0, p95=1.0, p98=1.0, p99=1.0, p999=1.0
+
+

More Metrics

+

NoSQLBench extends many ways to report the metrics from a run, including:

+
    +
  • Built-in Docker Dashboard
  • +
  • Reporting to CSV
  • +
  • Reporting to Graphite
  • +
  • Reporting to HDR
  • +
+

To get more information on these options, see the output of

+
./nb5 --help
+
+

Congratulations

+

You have completed your first run with NoSQLBench!

+

In the 'Next Steps' section, you'll find options for how to continue, whether you are looking for basic testing or +something more advanced.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/getting-started/05-next-steps/index.html b/getting-started/05-next-steps/index.html new file mode 100644 index 000000000..5503e467f --- /dev/null +++ b/getting-started/05-next-steps/index.html @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + 05 Next Steps | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Now that you've run NoSQLBench for the first time and seen what it does, you can choose what level +of customization you want for further testing.

+

The sections below describe key areas that users typically customize when working with NoSQLBench.

+

Everyone who uses NoSQLBench will want to get familiar with the +Core Concepts +section. This is essential reading for new and experienced testers alike.

+

High-Level Users

+

Several canonical workloads are already baked-in to NoSQLBench for immediate use. If you are simply +wanting to drive workloads without building a custom workload, then you'll want to learn about +the available workloads and their options.

+

Workload Builders

+

If you want to use NoSQLBench to build a tailored workload that closely emulates what a specific +application would do, then you can build a self-contained and portable YAML file that specifies all +the details. You can specify the access patterns, data distributions, and more. This is +explained further in Workloads 101

+

Built-In Sources

+

You can use the --list-workloads option to see all the built-in workloads, and then use the +--copy <name> option to copy them out of the runtime into your local directory. +These sources provide a wealth of examples to consider as you build your own workloads or customize +existing ones.

+

Scenario Developers

+

For advanced scenario designs, iterative testing models, or analysis methods, you can use ECMAScript +to control the scenario from start to finish. This is an advanced feature that is not recommended +for first-time users. If you need this feature and run into any issues, join us on the discord +server and strike up a conversation!

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/getting-started/index.html b/getting-started/index.html new file mode 100644 index 000000000..0f123fd76 --- /dev/null +++ b/getting-started/index.html @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + 00 Download | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

NoSQLBench version 5 is packaged directly as a Linux binary named +nb5 +and as an executable Java 17 jar named +nb5.jar +. All releases are available at +[NoSQLBench Releases]. The Linux binary is +recommended, since it comes with its own JVM and eliminates the need to manage +Java downloads.

+

Requirements

+

The nb5 binary requires Linux and a system with a working +FUSE library. Most modern distributions +have this out of the box.

+

nb5.jar is not particular about what system you run it on, as long as you have java 17 or newer.1

+

Download Scripts

+

Get the latest nb5 binary

+
# download the latest nb5 binary and make it executable
+curl -L -O https://github.com/nosqlbench/nosqlbench/releases/latest/download/nb5
+chmod +x nb5
+./nb5 --version
+
+

👉 If after downloading and executing nb, you get an error, please consult the +AppImage troubleshooting page.

+

Get the latest nb5 jar

+
# download the latest nb5 jar
+curl -L -O https://github.com/nosqlbench/nosqlbench/releases/latest/download/nb5.jar
+java -jar nb5.jar --version
+
+

This documentation assumes you are using the Linux binary initiating NoSqlBench commands with +./nb. If you are using the jar, just replace ./nb with java -jar nb.jar when running +commands. If you are using the jar version, Java 17 is recommended, and will be required soon.

+

Running nb5

+

To run a simple built-in workload run:

+
./nb5 examples/bindings-basics
+
+

This runs a built-in scenario located in the workload template named 'bindings-basics'. The +file that the scenario is defined in is called the workload template. The scenario is named +default, so you don't even have to specify it here. But you could, as

+
./nb5 examples/bindings-basics default
+
+

This will be explained further in Scenarios.

+

Options

+

Here is a more detailed command which demonstrates how customizable nb5 is:

+
1./nb5 examples/bindings-basics default \ +
2 filename=exampledata.out \ +
3 format=csv \ +
4 cycles=10000 \ +
5 rate=100 \ +
6 --progress console:1s +
+

Each line does something specific:

+
    +
  1. Starts the scenario named default from the workload template examples/binding-basics.
  2. +
  3. Sets the filename parameter (part of the stdout driver) to exampledata.out.
  4. +
  5. Sets the output format (part of the stdout driver) to CSV.
  6. +
  7. Sets the number of cycles to run to 10000, short for 0..10000, which represents 0 through 9999.
  8. +
  9. Sets the cycle rate to 100 per second.
  10. +
  11. Tells nb5 to report activity progress to the console every second.
  12. +
+

Dashboards

+

You can use --docker-metrics to stand up a live metrics dashboard at port 3000.

+

👉In order to use the --docker-metrics option, you need to have docker installed on your +local system, and your user must have permissions to use it. Typically, this means that your user +has been added to the docker group with a command like sudo usermod $USER -g docker.

+

Here is the above command, with built-in dashboarding enabled:

+
./nb5 examples/bindings-basics default \
+ filename=exampledata.out \
+ format=csv \
+ cycles=10000 \
+ rate=100 \
+ --progress console:1s \
+ --docker-metrics
+
+
1 +

The version scheme for NoSQLBench is [major]-[java-lts]-[minor], so nb5 version 5.17.1 +requires java version 17, which is the latest LTS Java release.

+
+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/getting-started/keyspace.png b/getting-started/keyspace.png new file mode 100644 index 000000000..c6075cd8e Binary files /dev/null and b/getting-started/keyspace.png differ diff --git a/getting-started/token.png b/getting-started/token.png new file mode 100644 index 000000000..6678d134a Binary files /dev/null and b/getting-started/token.png differ diff --git a/gh-link-light.svg b/gh-link-light.svg new file mode 100644 index 000000000..2a5c03975 --- /dev/null +++ b/gh-link-light.svg @@ -0,0 +1,7 @@ + + + + diff --git a/gh-link-strong.svg b/gh-link-strong.svg new file mode 100644 index 000000000..6ba70428b --- /dev/null +++ b/gh-link-strong.svg @@ -0,0 +1,6 @@ + + + diff --git a/index.html b/index.html new file mode 100644 index 000000000..8c15383f2 --- /dev/null +++ b/index.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + What's New - NB5 | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Updates in Progress

+

👉 The docs are presently updated to support NoSQLBench v5.17. 👈

+

Welcome to NB5! This release represents a massive leap forward. There are so many improvements +that should have gone into smaller releases along the way, but here we are. We've had our heads +down, focusing on new APIs, porting drivers, and fixing bugs, but it's time to talk about the +new stuff!

+

For those who are experienced NB5 users, this will have few (but some!) surprises. For +those of you who are NB (4 or earlier) users, NB5 is a whole different kind of testing tool. The +changes allow for a much more streamlined user and developer experience, while also offering +additional capabilities never seen together in a systems testing tool.

+

Everything mentioned here will find its way into the main docs site before were done.

+

We've taken some care to make sure that there is support for earlier workloads where at all +possible. If we've missed something critical, please let us know, and we'll patch it up ASAP.

+

This is a narrative overview of changes for NB5 in general. Individual +releases will have itemized code changes +listed individually.

+

Artifacts

+

nb5

+

The main bundled artifact is now named nb5. This version of NoSQLBench is a +significant departure from the previous limitations and conventions, so a new name was fitting. +It also allows you to easily have both on your system if you are maintaining test harnesses. +This is a combination of the NoSQLBench core runtime module nbr and all the bundled driver +adapters which have been contributed to the project.

+

Packaging

+

The code base for nb5 is more modular and adaptable. The core runtime module nbr is now +separate, including only the core diagnostic driver which is used in integration tests. This allows +for leaner and meaner integration tests.

+

drivers

+

We've ported many drivers to the nb5 APIs. All CQL support is now being provided by +Datastax Java Driver for Apache Cassandra. +In addition, multiple contributors are stepping up to provide new drivers for many systems +across the NoSQL ecosystem.

+

Project

+

Significant changes were made for the benefit of both users and developers.

+

Team

+

We've expanded the developer team which maintains tools like NoSQLBench. This should allow us to +make improvements faster, focus on users more, and bring more strategic capabilities to the project +which can redefine how advanced testing is done.

+

WYSiWYG Docs

+

We've connected the integration and specification tests to the documentation in a way that +ties examples everything together. If the examples and integration tests that are used on this +site fail, the build fails. Otherwise, the most recent examples are auto exported from the main +code base to the docs site. This means that test coverage will improve examples in the docs, +which will stay constantly up to date. Expect coverage of this method to improve with each +release. Until we can say What You See Is What You Get across all nb5 functions and examples, +we're not done yet.

+

Releases

+

Going forward we'll enforce stricter release criteria. Interim releases will be flagged as +prerelease unless due diligence checks have been done and a peer review finds a prerelease +suitable for promotion to a main release. Once flagged as a normal release, CI/CD tools can pick +up the release from the github releases area automatically.

+

We have a set of release criteria which will be published to this site and used as a blueprint for +releases going forward. More information on how releases are managed can be found in our +Contributing section. This will include testing coverage, +static +analysis, and further integrated testing support.

+

Documentation

+

This doc site is a significant step up from the previous version. It is now more accessible, +more standards compliant, and generally more user-friendly. The dark theme is highly usable. +Syntax highlighting is much easier on the eyes, and page navigation works better! The starting +point for this site was provided by the abridge theme by +Jieiku.

+

Architecture

+

The impetus for a major new version of NoSQLBench came from user and developer needs. In +order to provide a consistent user experience across a variety of testing needs, the core +machinery needed an upgrade. The APIs for building drivers and features have been redesigned to +this end, resulting in a vast improvement for all who use or maintain nb5 core or drivers.

+

These benefits include:

+
    +
  • Vastly simplified driver contributor experience
  • +
  • Common features across all implemented DriverAdapters
  • +
  • Interoperability between drivers in the same scenario or activity
  • +
  • Standard core activity params across all drivers, like op=...
  • +
  • Standard metrics semantics across all drivers
  • +
  • Standard highly configurable error handler support
  • +
  • Standard op template features, like named start and stop timers
  • +
  • Standard diagnostic tools across all drivers, like dryrun=...
  • +
+

The amount of Standard you see in this list is directly related to the burden removed from +both nb5 users and project contributors.

+

Some highlights of these will be described below, with more details in the user guide.

+
    +
  • The error handlers mechanism is now fully generalized across all +drivers. +It is also chainable, with specific support for handling each error type with a specific chain of +handlers, or +simply assigning a default to all of them as before.
  • +
  • The rate limiter is more efficient. This should allow it to work better in some scenarios +where inter-core contention was a limiting factor.
  • +
  • It is now possible to dry-run an activity with dryrun=op or similar. Each dryrun option goes +a little further into a normal run so that incremental verification of workloads can be done. +For example, the dryrun=op option uses all the logic of a normal execution, but it wraps +the op implementation in a no-op. The results of this will tell you how fast the client can +synthesize and dispatch operations when there is no op execution involved. The measurement +will be conservative due to the extra wrapping layer.
  • +
  • Thread management within activities is now more efficient, more consistent, and more real-time. +Polling calls were replaced with evented calls where possible.
  • +
  • Only op templates which are active (selected and have a positive ratio) are resolved at +activity initialization. This improves startup times for large workload with subsets of +operations enabled.
  • +
  • Native drivers (like the CQL Java Driver) now have their driver instance and object graph +cached, indexed by a named op field called space. By default, this is wired to return +default, thus each unique adapter will use the same internal object graph for execution. +This is how things worked for most drivers before. However, if the user specifies that the +space should vary, then they simply assign it a binding. This allows for advanced driver +testing across a number of client instances, either pseudo-randomly or in lock-step with +specific access patterns. If you don't want to use this, then ignore it and everything works +as it did before. But if you do, this is built-in to every driver by design.
  • +
  • The activity parameter driver simply sets the default adapter for an activity. You can set +this per op template, and run a different driver for every cycle. This field must be static on +each op template, however. This allows for mixed-mode workloads in the same op sequence.
  • +
  • Adapters can be loaded from external jars. This can help users who are building adapters and want +to avoid building the full runtime just for iterative testing.
  • +
  • The phase loop has been removed.
  • +
  • Operations can now generate more operations associated with a cycle. This opens the door to
  • +
  • There is a distinct API for implementing dynamic activity params distinctly from +initialization params.
  • +
+

Ergonomics

+

Console

+
    +
  • ANSI color support in some places, such as in console logging patterns. The --ansi and +--console-pattern and --logging-pattern options work together. If a non-terminal is +detected on stdout, ANSI is automatically disabled.
  • +
  • The progress meter has been modified to show real-time, accurate, detailed numbers +including operations in flight.
  • +
+

Discovery

+
    +
  • Discovery of bundled assets is now more consistent, supported with a family of --list-... +options.
  • +
+

Configuration

+
    +
  • Drivers know what parameters they can be configured with. This allows for more +intelligent and useful feedback to users around appropriate parameter usage. If you get a +param name wrong, nb5 will likely suggest the next closest option.
  • +
  • S3 Urls should work in most places, including for loading workload templates. You only need to +configure your local authentication first.
  • +
+

Templating

+

Much of the power of NB5 is illustrated in the new ways you can template workloads. This +includes structured data, dynamic op configuration, and driver instancing, to name a few.

+
    +
  • The structure of op templates (the YAML you write to simulate access patterns) has been +standardized around a strict set of specification tests and examples. These are documented +in-depth and tested against a specification with round-trip validation.
  • +
  • Now, JSON and Jsonnet are supported directly as workload template formats. Jsonnet allows you to +see the activity params as external variables.
  • +
  • All workload template structure is now supported as maps, in addition to the other structural +forms (previously called workload YAMLs). All of these forms automatically de-sugar into the +canonical forms for the runtime to use. This follows the previous pattern of "If it does what +it looks like, it is valid", but further allows simplification of workloads with inline +naming of elements.
  • +
  • In addition to workload template structure, op templates also support arbitrary structure +instead of just scalar or String values. This is especially useful for JSON payload modeling. +This means that op templates now have a generalized templating mechanism that works for all +data structures. You can reference bindings as before, but you can also create collections and +string templates by writing fields as they naturally occur, then adding {bindings} where you +need.
  • +
  • All op template fields can be made dynamic if an adapter supports it. It is up to the adapter +implementor to decide which op fields must be static.
  • +
  • Op template values auto-defer to configured values as static, then dynamic, and then +configured from activity parameters as defaults. If an adapter supports a parameter at the +activity level, and an op form supports the same field, then this occurs automatically.
  • +
  • Tags for basic workload template elements are provided gratis. You no longer need to specify the +conventional tags. All op templates now have block: <blockname> and name: <blockname>--<name> tags added. This works with regexes in tag filtering.
  • +
  • Named scenarios now allow for nb5 <workload-file> <scenario-name>.<scenario-step> .... You can +prototype and validate complex scenarios by sub-selecting the steps to execute.
  • +
  • You can use the op="..." activity parameter to specific a single-op workload on the +command line, as if you had read it from a workload YAML. This allows +for one-liner tests streamlined integration, and other simple utility usage.
  • +
  • Binding recipes can now occur inline, as {{Identity()}}. This works with the op +parameter above.
  • +
  • You can now set a minimum version of NoSQLBench to use for a workload. The min_version: "4.17. 15" property is checked starting from the most-significant number down. If there are new core +features that your workload depends on, you can use this to avoid ambiguous errors.
  • +
  • Template vars like <<name:value>> or TEMPLATE(name,value) can set defaults the first time they +are seen. This means you don't have to update them everywhere. A nice way to handle this is to +include them in the description once, since you should be documenting them anyway!
  • +
  • You can load JSON files directly. You can also load JSONNET files directly! If you need to +sanity check your jsonnet rendering, you can use dryrun=jsonnet.
  • +
  • All workload template elements can have a description.
  • +
+

Misc Improvements

+

(some carry over from pre-nb5 features)

+
    +
  • Argsfile support for allowing sticky parameters on a system.
  • +
  • Tag filters are more expressive, with regexes and conjunctions.
  • +
  • Some scenario commands now allow for regex-style globbing on activity alias names.
  • +
  • Startup logging now includes details on version, hardware config, and scenario commands for +better diagnostics and bug reports.
  • +
  • The logging subsystem config is improved and standardized across the project.
  • +
  • Test output is now vectored exclusively through logging config.
  • +
  • Analysis methods are improved and more widely used.
  • +
+

Deprecations and Standards

+
    +
  • NB5 depends on Java 17. Going forward, major versions will adopt the latest LTS java release.
  • +
  • Dependencies which require shading in order to play well with others are not supported. If you +have a native driver or need to depend on a library which is not a good citizen, you can only +use it with NB5 by using the external jar feature (explained elsewhere). This includes the +previous CQL drivers which were the 1.9.* and 3.*.* version. Only CQL driver 4.* is +provided in nb5.
  • +
  • Dependencies should behave as modular jars, according to JPMS specification. This does not +mean they need to be JPMS modules, only that the get halfway there.
  • +
  • Log4J2 is the standard logging provider in the runtime for NoSQLBench. An SLF4J stub +implementation is provided to allow clients which implement against the SLF4J API to work.
  • +
  • All new drivers added to the project are based on the Adapter API.
  • +
+

Works In Progress

+
    +
  • These docs!
  • +
  • Bulk Loading efficiency for large tests
  • +
  • Linearized Op Modeling +
      +
    • We now have a syntax for designating fields to extract from op results. This is part of the +support needed to make client-side joins and other patterns easy to emulate.
    • +
    +
  • +
  • Rate Limiter v3
  • +
  • VictoriaMetrics Integration +
      +
    • Labeled metrics need to be fed to a victoria metrics docker via push. This approach will +remove much of the pain involved in using prometheus as an ephemeral testing apparatus.
    • +
    +
  • +
+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/introduction/community/index.html b/introduction/community/index.html new file mode 100644 index 000000000..6b28ec72c --- /dev/null +++ b/introduction/community/index.html @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + Community | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

In general, our goals with NoSQLBench are to make the help systems and examples wrap around the +users like a suit of armor, so that they feel capable of doing most things without having to ask for +help. Please keep this in mind when looking for personal support from our community, and help us +find those places where the docs are lacking. Maybe you can help us by adding some missing docs!

+

Doc Site

+

This site is intended to be the first and most useful form of documentation for NoSQLBench. It is +hosted on a separate project repo on GitHub so that it can be owned and maintained by the NoSQLBench +user and developer community. +(Click the GitHub link [here] to go directly there.) If you +see something here that should be updated or expanded, please submit an issue, reach out on discord, +or even better, submit a pull request!

+

Discord Server

+

Our discord server is where users and developers can discuss anything about NoSQLBench and support +each other. Please +[join us] there if you are a new user of NoSQLBench!

+

Contributing

+

We welcome all builders to NoSQLBench to help us improve it. Whether you are focused on improving +docs, building a new subsystem or developing a new scripting extension, there is room for everyone, and all are +appreciated. We have a new contributing section +if you are interested.

+

Documentation

+

The primary documentation for NoSQLBench has been moved to this site. While there are still some +comment line help facilities, like nb5 help <driver>, this is the best place to read it. +When nb5 is built, it automatically exports all the rendered docs content to this site.

+

This site contains much more documentation than you will want to browse on the command line. +It is recommended that you look here first with the search function when possible.

+

Bug Fixes

+

If you think you have found a bug, please +[file a bug report] +. NoSQLBench is actively used within DataStax, and verified bugs will get attention as resources +permit. We appreciate all feedback, no matter how detailed. However, bug reports which are more +detailed, or which include steps to reproduce any issues will get attention first.

+

Feature Requests

+

If you would like to see something in NoSQLBench that is not there yet, please +[submit a feature request] +.

+

Documentation Requests

+

If you would like to see a specific NoSQLBench or testing topic added to the guidebook, please +[request docs content] +.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/introduction/core-concepts/index.html b/introduction/core-concepts/index.html new file mode 100644 index 000000000..af3faf97a --- /dev/null +++ b/introduction/core-concepts/index.html @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + Core Concepts | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

NoSQLBench is built on top of core concepts that have been scrutinized, replaced, refined, and +hardened through several years of use by a diverse set of users.

+

This level of refinement is important when trying to find a way to express common patterns in what +is often a highly fragmented practice. Testing is hard. Scale testing is hard. Distributed testing +is hard. Combined, the challenge of executing realistic tests is often quite daunting to all but +seasoned test engineers. To make this worse, existing tools have only skirmished with this problem +enough to make dents, but none has tackled full-on the lack of conceptual building blocks.

+

This has to change. We need a set of testing concepts that can span across workloads and system +types, and machinery to put these concepts to use. This is why it is important to focus on finding a +useful and robust set of concepts to use as the foundation for the rest of the toolkit to be built +on. Finding these building blocks is often one of the most difficult challenges in systems design. +Once you find and validate a useful set of concepts, everything else gets easier.

+

We believe that the success that we've already had using NoSQLBench has been strongly tied to the core +concepts. Some concepts used in NoSQLBench are shared below for illustration, but this is by no +means an exhaustive list.

+

The Cycle

+

Cycles in NoSQLBench are whole numbers on a number line. Each operation in a NoSQLBench scenario is +derived from a single cycle. It's a long value, representing a seed. The cycle determines not only which +operation is selected for execution, but also what data will be attached and fed to it.

+

Cycles are specified as a closed-open [min,max) interval, known as slices in some languages. That +is to say, the min value is included in the range, but the max value is not. This means that you can stack +slices using common numeric reference points without overlaps or gaps, and that you can have exact +awareness of what data is in your dataset, even incrementally.

+

You can think of a cycle as a single-valued coordinate system for data that lives adjacent to that +number on the number line. In this way, virtual dataset functions are ways of converting coordinates +into data.

+

In NoSQLBench, the cycle range determines both the total size of a workload and the specific set of +operations which will be performed. Using the same cycle range is the same as specifying the same +exact operations. This means that your tests can be completely deterministic (pseudo-random) and +repeatable, even when they appear random or are shaped by density curves.

+

The Activity

+

An activity is a multithreaded flywheel of statements in some sequence and ratio. Each activity +runs over the numbers in a cycle range. An activity is specified as a series of op templates in some +ratio and order. When an activity runs, it executes an efficient loop over specific operations with +its own thread pool.

+

The Op Template

+

Each possible operation in an activity is provided by the user in a YAML or data structure driven +template. The op templates are used to create efficient op dispensers in the runtime according to +the mapping rules for a given driver.

+

The Driver Adapter

+

A driver adapter is a high level driver for a protocol which interfaces a native driver to the +runtime machinery of NoSQLBench. It's like a statement-aware cartridge that knows how to take a +basic op template and turn it into an operation for an activity to execute for a given cycle.

+

The Scenario

+

The scenario is a runtime session that holds activities while they run. A NoSQLBench scenario is +responsible for aggregating global runtime settings, metrics reporting channels, log files, and so +on. All activities run within a scenario, under the control of the scenario script.

+

The Scenario Script

+

Each scenario is governed by a central script. This script runs in a single-threaded manner, asynchronous from +the activities, maintaining control over them. If necessary, the scenario script is automatically created for the user, +and the user never knows it is there. If the user has advanced testing requirements, then they may take +advantage of the scripting capability at such time. The scenario completes when the script exits, AND all +activities are also complete. Shortcut forms of scripting are provided on the command line to address +common variations.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/introduction/download/index.html b/introduction/download/index.html new file mode 100644 index 000000000..b3f74d6dc --- /dev/null +++ b/introduction/download/index.html @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + Download | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

In general, our goals with NoSQLBench are to make the help systems and examples wrap around the +users like a suit of armor, so that they feel capable of doing most things without having to ask for +help. Please keep this in mind when looking for personal support from our community, and help us +find those places where the docs are lacking. Maybe you can help us by adding some missing docs!

+

Doc Site

+

This site is intended to be the first and most useful form of documentation for NoSQLBench. It is +hosted on a separate project repo on GitHub so that it can be owned and maintained by the NoSQLBench +user and developer community. (Click the GitHub link [here] to go directly there.) If you +see something here that should be updated or expanded, please submit an issue, reach out on discord, +or best of all, submit a pull request!

+

Discord Server

+

Our discord server is where users and developers can discuss anything about NoSQLBench and support +each other. Please +[join us] there if you are a new user of NoSQLBench!

+

Contributing

+

We welcome all builders to NoSQLBench to help us improve it. Whether you are focused on improving +docs or building a new subsystem or scripting extension, there is room for everyone, and all are +appreciated. Please read about +[CONTRIBUTING] +if you are interested.

+

Built-In Docs

+

NoSQLBench has some built-in docs which are available on the command line. You can see a list of +built-in docs with the command:

+
nb5 help topics
+
+

or, to read any topic, simply use the command:

+
nb5 help <topic>
+
+

This doc site contains much more documentation than you will want to browse on the command line. +It is recommended that you look here first with the search function when possible.

+

Bug Fixes

+

If you think you have found a bug, please +[file a bug report] +. NoSQLBench is actively used within DataStax, and verified bugs will get attention as resources +permit. We appreciate all feedback, no matter how detailed. However, bug reports which are more +detailed, or which include steps to reproduce any issues will get attention first.

+

Feature Requests

+

If you would like to see something in NoSQLBench that is not there yet, please +[submit a feature request] +.

+

Documentation Requests

+

If you would like to see a specific NoSQLBench or testing topic added to the guidebook, please +[request docs content] +.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/introduction/index.html b/introduction/index.html new file mode 100644 index 000000000..c3545a44a --- /dev/null +++ b/introduction/index.html @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + NoSQLBench | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Welcome to the documentation for NoSQLBench. This is a power tool that emulates real application +workloads. This means that you can fast-track performance, sizing and data model testing without +writing your own testing harness.

+

To get started right away, jump to the +Getting Started section of the docs.

+

What is NoSQLBench?

+

NoSQLBench is a serious performance testing tool for the NoSQL ecosystem.

+

NoSQLBench brings advanced testing capabilities into one tool that are not found in other testing +tools.

+
    +
  • You can run common testing workloads directly from the command line within 5 minutes of reading this.
  • +
  • You can generate virtual data sets of arbitrary size, with deterministic data and statistically +shaped values.
  • +
  • You can design custom workloads that emulate your application, contained in a single file, based +on statement templates—no IDE or coding required.
  • +
  • You can immediately plot your results in a docker and grafana stack on Linux with a single command +line option.
  • +
  • You can open the access panels when necessary and rewire the runtime behavior of NoSQLBench for advanced +testing. This includes access to a full scripting environment with Javascript.
  • +
+

The core machinery of NoSQLBench has been built with attention to detail. It has been battle tested +within DataStax as a way to help users validate their data models, baseline system performance, and +qualify system designs for scale.

+

In short, NoSQLBench wishes to be a programmable power tool for performance testing. However, it is +somewhat generic. It doesn't know directly about a particular type of system, or protocol. It simply +provides a suitable machine harness in which to put your drivers and testing logic. If you know how +to build a client for a particular kind of system, NoSQLBench will let you load it like a plugin and control +it dynamically.

+

Initially, NoSQLBench was used for CQL testing, but we have seen this expanded over time by +other users and vendors with drivers for a variety of systems. We would like to see this +expanded further with contributions from others.

+

Origins

+

The code in this project comes from multiple sources. The procedural data generation capability was +known before as Virtual Data Set. The core runtime and scripting harness was from the +EngineBlock project. The CQL support was previously used within DataStax. In March 2020, DataStax +and the project maintainers decided to put everything into one OSS project in order to make +contributions and sharing easier for everyone. Thus, the new project name and structure was launched +as NoSQLBench.io. NoSQLBench is an independent project that is primarily sponsored by DataStax.

+

We offer NoSQLBench as a new way of thinking about testing systems. It is not limited to testing +only one type of system. It is our wish to build a community of users and practice around this +project so that everyone in the NoSQL ecosystem can benefit from common concepts and understanding +and reliable patterns of use.

+

Scalable User Experience

+

NoSQLBench endeavors to be valuable to all users. We do this by making it easy for you, our user, to +do just what you need without worrying about the rest. If you need to do something simple, it should +be simple to find the right settings and just do it. If you need something more sophisticated, then +you should be able to find what you need with a reasonable amount of effort and no surprises.

+

That is the core design principle behind NoSQLBench. We hope you like it.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/introduction/introduction/index.html b/introduction/introduction/index.html new file mode 100644 index 000000000..6b5ac1c3a --- /dev/null +++ b/introduction/introduction/index.html @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + NoSQLBench | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Welcome to the documentation for NoSQLBench. This is a power tool that emulates real application +workloads. This means that you can fast-track performance, sizing and data model testing without +writing your own testing harness.

+

To get started right away, jump to the +Getting Started section of the docs.

+

What is NoSQLBench?

+

NoSQLBench is a serious performance testing tool for the NoSQL ecosystem.

+

NoSQLBench brings advanced testing capabilities into one tool that are not found in other testing +tools.

+
    +
  • You can run common testing workloads directly from the command line within 5 minutes of reading this.
  • +
  • You can generate virtual data sets of arbitrary size, with deterministic data and statistically +shaped values.
  • +
  • You can design custom workloads that emulate your application, contained in a single file, based +on statement templates—no IDE or coding required.
  • +
  • You can immediately plot your results in a docker and grafana stack on Linux with a single command +line option.
  • +
  • You can open the access panels when necessary and rewire the runtime behavior of NoSQLBench for advanced +testing. This includes access to a full scripting environment with Javascript.
  • +
+

The core machinery of NoSQLBench has been built with attention to detail. It has been battle tested +within DataStax as a way to help users validate their data models, baseline system performance, and +qualify system designs for scale.

+

In short, NoSQLBench wishes to be a programmable power tool for performance testing. However, it is +somewhat generic. It doesn't know directly about a particular type of system, or protocol. It simply +provides a suitable machine harness in which to put your drivers and testing logic. If you know how +to build a client for a particular kind of system, NoSQLBench will let you load it like a plugin and control +it dynamically.

+

Initially, NoSQLBench was used for CQL testing, but we have seen this expanded over time by +other users and vendors with drivers for a variety of systems. We would like to see this +expanded further with contributions from others.

+

Origins

+

The code in this project comes from multiple sources. The procedural data generation capability was +known before as Virtual Data Set. The core runtime and scripting harness was from the +EngineBlock project. The CQL support was previously used within DataStax. In March 2020, DataStax +and the project maintainers decided to put everything into one OSS project in order to make +contributions and sharing easier for everyone. Thus, the new project name and structure was launched +as NoSQLBench.io. NoSQLBench is an independent project that is primarily sponsored by DataStax.

+

We offer NoSQLBench as a new way of thinking about testing systems. It is not limited to testing +only one type of system. It is our wish to build a community of users and practice around this +project so that everyone in the NoSQL ecosystem can benefit from common concepts and understanding +and reliable patterns of use.

+

Scalable User Experience

+

NoSQLBench endeavors to be valuable to all users. We do this by making it easy for you, our user, to +do just what you need without worrying about the rest. If you need to do something simple, it should +be simple to find the right settings and just do it. If you need something more sophisticated, then +you should be able to find what you need with a reasonable amount of effort and no surprises.

+

That is the core design principle behind NoSQLBench. We hope you like it.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/introduction/principles/index.html b/introduction/principles/index.html new file mode 100644 index 000000000..a4134dc99 --- /dev/null +++ b/introduction/principles/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + Design Principles | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

There are a few core design principles that steer the technical design of NoSQLBench. They are +shared here in the hopes that they will help others understand what NoSQLBench is all about.

+

Respect for Users

+

While this sounds like a conduct level aspect, the focus here is on what this means in terms of +design. Respect is absolutely part of the code of conduct governing this project as well.

+

What this means is that we try to build systems which respect users in general and in specific +ways which can only be tackled through thoughtful design.

+

Durable Concepts

+

We focus on core concepts that stand the test of time, and as such give time back to users. We +look for concepts which give back more in terms of clarity and reuse than they take away by +indirection. We build patterns of use around these concepts which bring users together in +common practice and understanding and move the testing ecosystem together as a whole.

+

Composable Systems

+

We build composable systems such that they can quickly be used in a pre-built form at a high +level. We make them reconfigurable by those who need so that they can be repurposed into +something more contextual. In this way, we provide a sliding scale of user experience, where +users' time is exchanged for incremental value in results.

+

High Fidelity

+

We build high-fidelity measurement tools and instruments into NoSQLBench, so that the results +are not only useful, but repeatable and reproducible. We build efficiency into the NoSQLBench +machinery, so that testing tools maintain headroom enough to make accurate measurements at speed.

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/introduction/showcase/index.html b/introduction/showcase/index.html new file mode 100644 index 000000000..662a3ffa6 --- /dev/null +++ b/introduction/showcase/index.html @@ -0,0 +1,496 @@ + + + + + + + + + + + + + + + + Showcase | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

NoSQLBench has enjoyed a history of unique innovation: driven by the vision of its users and +builders, forged by the need for practical methods to test modern systems. This section covers a +sampling of what makes NoSQLBench unique. Many of these features simply could not be found in other +testing systems when they were needed. Thus, NoSQLBench took form as we solved them one after +another in the same tool space. The result is a powerful runtime and system of components and +concepts which can be adapted to a variety of testing needs.

+

Virtual Data Set

+

The Virtual Dataset capabilities within NoSQLBench allow you to generate data on the fly. There +are many reasons for using this technique in testing, but it is often a topic that is overlooked or +taken for granted.

+

This has multiple positive effects on the fidelity of a test:

+
    +
  • It is very much more efficient than interacting with storage systems and piping data around. In most +cases, even loading data from lightweight storage like NVMe will be more time intensive than simply +generating it.
  • +
  • As such, it leaves significant headroom on the table for introducing other valuable capabilities +into the test system, like advanced rate metering, coordinated omission awareness, and more.
  • +
  • Changing the generated data is as easy as changing the recipe.
  • +
  • The efficiency of the client is often high enough to support single-client test setups without +appreciable loss of capacity.
  • +
  • Because of modern procedural generation techniques, the variety and shape of data available is +significant. Increasing the space of possibilities is a matter of adding new algorithms. There is +no data bulk to manage.
  • +
  • Sophisticated test setups that are highly data dependent are portable. All you need is the test +client. The building blocks for data generation are included, and many pre-built testing scenarios +are already wired to use them.
  • +
  • It is straight-forward to design incremental data generation schemes which produce monotonic +identifiers, pseudo-random traversal over the values, or even statistically-shaped versions of +incremental or pseudo-random values.
  • +
+

Additional details of this approach are explained below.

+
Industrial Strength
+

The algorithms used to generate data are based on advanced techniques in the realm of variate +sampling. The authors have gone to great lengths to ensure that data generation is efficient and as +much O(1) in processing time as possible.

+

For example, one technique that is used to achieve this is to initialize and cache data in high +resolution look-up tables for distributions which may otherwise perform differently depending on +their respective density functions. The existing Apache Commons Math libraries have been adapted +into a set of interpolated Inverse Cumulative Distribution sampling functions. This means that you +can use them all in the same place as you would a Uniform distribution, and once initialized, they +sample with identical overhead. This means that by changing your test definition, you don't +accidentally change the behavior of your test client; only the data, as intended.

+
A Purpose-Built Tool
+

Many other testing systems avoid building a dataset generation component. It's a tough problem to +solve, so it's often just avoided. Instead, they use libraries like "faker" or other sources of data +which weren't designed for testing at scale. Faker is well named, no pun intended. It was meant as a +vignette and wire-framing library, not a source of test data for realistic results. If you are using +a testing tool for scale testing and relying on a faker variant, then you will almost certainly get +invalid results that do not represent how a system would perform in production.

+

The virtual dataset component of NoSQLBench is a library that was designed for high scale and +realistic data streams. It uses the limits of the data types in the JVM to simulate high cardinality +datasets which approximate production data distributions for realistic and reproducible results.

+
Deterministic
+

The data that is generated by the virtual dataset libraries is deterministic. This means that for a +given cycle in a test, the operation that is synthesized for that cycle will be the same from one +session to the next. This is intentional. If you want to perturb the test data from one session to +the next, then you can most easily do it by simply selecting a different set of cycles as your +basis.

+

This means that if you find something interesting in a test run, you can go back to it just by +specifying the cycles in question. It also means that you aren't losing comparative value between +tests with additional randomness thrown in. The data you generate will still look random to the +human eye, but that doesn't mean that it won't be reproducible.

+
Statistically Shaped
+

If you want a normal distribution, you can have it simply by specifying Normal(50,10). The values +drawn from this sampling function are deterministic AND normal. If you want another distribution, +you can have it. All the distributions provided by the Apache Commons math libraries are supported. +You can ask for a stream of floating point values 1 trillion values long, in any order. You can use +discrete or continuous distributions, with whatever distribution parameters you need.

+
Best of Both Worlds
+

Some might worry that fully synthetic testing data is not realistic enough. The devil is in the +details on these arguments, but suffice it to say that you can pick the level of real data you use +as seed data with NoSQLBench. You don't have to choose between realism and agility. The procedural +data generation approach allows you to have all the benefits of testing agility of low-entropy +testing tools while retaining nearly all the benefits of real testing data.

+

For example, using the alias sampling method and a published US census (public domain) list of names +and surnames tha occurred more than 100x, we can provide extremely accurate samples of names +according to the published labels and weights. The alias method allows us to sample accurately +in O(1) time from the entire dataset by turning a large number of weights into two uniform +samples. You will simply not find a better way to sample realistic (US) names than this. (If you do, +please file an issue!) Actually, any data set that you have in CSV form with a weight column can +also be used this way, so you're not strictly limited to US census data.

+
Java Idiomatic Extension
+

The way that the virtual dataset component works allows Java developers to write any extension to +the data generation functions simply in the form of Java functional interfaces. As long +as they include the annotation processor and annotate their classes, they will show up in the +runtime and be available to any workload by their class name.

+

Additionally, annotation based examples and annotation processing is used to hoist function docs +directly into the published docs that go along with any version of NoSQLBench.

+
Binding Recipes
+

It is possible to stitch data generation functions together directly in a workload YAML. These are +data-flow sketches of functions that can be copied and pasted between workload descriptions to share +or remix data streams. This allows for the adventurous to build sophisticated virtual datasets that +emulate nuances of real datasets, but in a form that takes up less space on the screen than this +paragraph!

+

Portable Workloads

+

All the workloads that you can build with NoSQLBench are self-contained in a workload file. This +is a statement-oriented configuration file that contains templates for the operations you want to +run in a workload.

+

This defines part of an activity—the iterative flywheel part that is run directly within an +activity type. This file contains everything needed to run a basic activity: a set of statements +in some ratio. It can be used to start an activity, or as part of several activities within a +scenario.

+

Standard YAML Format

+

The format for describing statements in NoSQLBench is generic, but in a particular way that is +specialized around describing statements for a workload. That means that you can use the same YAML +format to describe a workload for kafka as you can for Apache Cassandra or DSE.

+

The YAML structure has been tailored to describing statements, their data generation bindings, how +they are grouped and selected, and the parameters needed by drivers, such as whether they should be +prepared statements or not.

+

Furthermore, the YAML format allows for defaults and overrides with a very simple mechanism that reduces +editing fatigue for frequent users.

+

You can also templatize document-wide macro parameters which are taken from the command line just +like any other parameter. This is a way of templating a workload and making it multipurpose or +adjustable on the fly.

+

Experimentation Friendly

+

Because the workload YAML format is generic across driver types, it is possible to ask one driver +type to interpret the statements that are meant for another. This isn't generally a good idea, but +it becomes extremely handy when you want to have a high level driver type like stdout +interpret the syntax of another driver like cql. When you do this, the stdout activity type _ +plays_ the statements to your console as they would be executed in CQL, data bindings and all.

+

This means you can empirically and directly demonstrate and verify access patterns, data skew, and +other dataset details before you change back to cql mode and turn up the settings for a higher scale +test. It takes away the guess work about what your test is actually doing, and it works for all +drivers.

+

Scripting Environment

+

The ability to write open-ended testing simulations is provided in NoSQLBench by means of a scripted +runtime, where each scenario is driven from a control script that can do anything the user wants.

+
Dynamic Parameters
+

Some configuration parameters of activities are designed to be assignable while a workload is +running. This makes things like threads, rates, and other workload dynamics in real-time. The +internal APIs work with the scripting environment to expose these parameters directly to scenario +scripts. Drivers that are provided to NoSQLBench can also expose dynamic parameters in the same way +so that anything can be scripted dynamically when needed.

+
Scripting Automatons
+

When a NoSQLBench scenario is running, it is under the control of a single-threaded script. Each +activity that is started by this script is run within its own thread pool, simultaneously and +asynchronously.

+

The control script has executive control of the activities, as well as full visibility into the +metrics that are provided by each activity. The way these two parts of the runtime meet is through +the service objects which are installed into the scripting runtime. These service objects provide a +named access point for each running activity and its metrics.

+

This means that the scenario script can do something simple, like start activities and wait for them +to complete, OR, it can do something more sophisticated like dynamically and iteratively scrutinize +the metrics and make real-time adjustments to the workload while it runs.

+
Analysis Methods
+

Scripting automatons that do feedback-oriented analysis of a target system are called analysis +methods in NoSQLBench. These are used for advanced testing scenarios. Advanced testers or +researchers can build their own in a way that interacts with a live system with feedback and +sampling times measured in seconds.

+
Command Line Scripting
+

The command line has the form of basic test commands and parameters. These command get converted +directly into scenario control script in the order they appear. The user can choose whether to stay +in high level executive mode, with simple commands like nb5 test-scenario ..., or to drop +directly into script design. They can look at the equivalent script for any command line by running +--show-script. If you take the script that is dumped to console and run it, it will do exactly the +same thing as if you hadn't even looked at it and just ran basic commands on the command line.

+

There are even ways to combine script fragments, full commands, and calls to scripts on the command +line. Since each variant is merely a way of constructing scenario script, they all get composited +together before the scenario script is run.

+

New introductions to NoSQLBench should focus on the command line. Once a user is familiar with this, +it is up to them whether to tap into the deeper functionality. If they don't need to know about +scenario scripting, then they shouldn't have to learn about it to be effective. This is what we are +calling a scalable user experience.

+
Compared to DSLs
+

Other tools may claim that their DSL makes scenario "simulation" easier. In practice, any DSL is +generally dependent on a development tool to lay the language out in front of a user in a fluent +way. This means that DSLs are almost always developer-targeted tools, and mostly useless for casual +users who don't want to break out an IDE.

+

One of the things a DSL proponent may tell you is that it tells you "all the things you can do!". +This is de-facto the same thing as it telling you +"all the things you can't do" because it's not part of the DSL. This is not a win-win for the user. +For DSL-based systems, the user is required to use the DSL, even when it interferes with the +user's creative control. Most DSLs aren't rich enough to do much that is interesting from a +simulation perspective.

+

In NoSQLBench, we don't force the user to use the programming abstractions except at a very surface +level: the CLI. It is up to the user whether to open the secret access panel for the more +advanced functionality. If they decide to do this, we give them a commodity language (ECMAScript), +and we wire it into all the things they were already using. We don't take away their creative +freedom by telling them what they can't do. This way, users can pick their level of investment and +reward as best fits their individual needs, as it should be.

+
Scripting Extensions
+

Also mentioned under the section on modularity, it is relatively easy for a developer to add their +own scripting extensions into NoSQLBench in the form of named service objects.

+

Modular Architecture

+

The internal architecture of NoSQLBench is modular throughout. Everything from the scripting +extensions to data generation is enumerated at compile time into a service descriptor, and then +discovered at runtime by the SPI mechanism in Java.

+

This means that extending and customizing bundles and features is quite manageable.

+

It also means that it is relatively easy to provide a suitable API for multi-protocol support. In +fact, there are several drivers available in the current NoSQLBench distribution. You can list them +out with nb5 --list-drivers, and you can get help on how to use each of them +with nb5 help <driver name>.

+

This also is a way for us to encourage and empower other contributors to help develop the +capabilities and reach of NoSQLBench. By encouraging others to help us build NoSQLBench modules and +extensions, we can help more users in the NoSQL community at large.

+

High Fidelity Metrics

+

Since NoSQLBench has been built as a serious testing tool for all users, some attention was +necessary on the way metric are used. More details follow...

+
Discrete Reservoirs
+

In NoSQLBench, we avoid the use of time-decaying metrics reservoirs. Internally, we use HDR +reservoirs with discrete time boundaries. This is so that you can look at the min and max values and +know that they apply accurately to the whole sampling window.

+
Metric Naming
+

All running activities have a symbolic alias that identifies them for the purposes of automation and +metrics. If you have multiple activities running concurrently, they will have different names and +will be represented distinctly in the metrics flow.

+
Precision and Units
+

By default, the internal HDR histogram reservoirs are kept at 4 digits of precision. All timers are +kept at nanosecond resolution.

+
Metrics Reporting
+

Metrics can be reported via graphite as well as CSV, logs, HDR logs, and HDR stats summary CSV +files.

+
Coordinated Omission
+

The metrics naming and semantics in NoSQLBench are set up so that you can have coordinated omission +metrics when they are appropriate, but there are no there changes when they are not. This means that +the metric names and meanings remain stable in any case.

+

Particularly, NoSQLBench tries to avoid the term "latency" altogether as it is often overused and +thus prone to confusing people.

+

Instead, the terms service time, wait time, and response time are used. These are abbreviated +in metrics as servicetime, waittime, and responsetime.

+

The servicetime metric is the only one which is always present. When a rate limiter is used, then +additionally waittime and responsetime are reported.

+

Advanced Testing Features

+

👉 Some features discussed here are only for advanced testing scenarios. First-time users should +become familiar with the basic options first.

+
Hybrid Rate Limiting
+

Rate limiting is a complicated endeavor, if you want to do it well. The basic rub is that going fast +means you have to be less accurate, and vice-versa. As such, rate limiting is a parasitic drain on +any system. The act of rate limiting itself poses a limit to the maximum rate, regardless of the +settings you pick. This occurs as a side effect of forcing your system to interact with some +hardware notion of time passing, which takes CPU cycles that could be going to the thing you are +limiting.

+

This means that in practice, rate limiters are often very featureless. It's daunting enough to need +rate limiting, and asking for anything more than that is often wishful thinking. Not so in +NoSQLBench.

+

The rate limiter in NoSQLBench provides a comparable degree of performance and accuracy to others +found in the Java ecosystem, but it also has advanced features:

+
    +
  • It allows a sliding scale between average rate limiting and strict rate limiting, called _ +bursting_.
  • +
  • It internally accumulates delay time, for C.O. friendly metrics which are separately tracked for +each and every operation.
  • +
  • It is resettable and reconfigurable on the fly, including the bursting rate.
  • +
  • It provides its configured values in addition to performance data in metrics, capturing your rate +limiter settings as a simple matter of metrics collection.
  • +
  • It comes with advanced scripting helpers which allow you to read data directly from histogram +reservoirs, or control the reservoir window programmatically.
  • +
+
Flexible Error Handling
+

An emergent facility in NoSQLBench is the way that error are handled within an activity. For +example, with the CQL activity type, you are able to route error handling for any of the known +exception types. You can count errors, you can log them. You can cause errored operations to +auto-retry if possible, up to a configurable number of tries.

+

This means, that as a user, you get to decide what your test is about. Is it about measuring some +nominal but anticipated level of errors due to intentional over-saturation? If so, then count the +errors, and look at their histogram data for timing details within the available timeout.

+

Are you doing a basic stability test, where you want the test to error out for even the slightest +error? You can configure for that if you need.

+
Cycle Logging
+

It is possible to record the result status of each and every cycle in a NoSQLBench test run. If the +results are mostly homogeneous, the RLE encoding of the results will reduce the output file down to +a small fraction of the number of cycles. The errors are mapped to ordinals by error type, and these +ordinals are stored into a direct RLE-encoded log file. For most testing where most of the results +are simply success, this file will be tiny. You can also convert the cycle log into textual form for +other testing and post-processing and vice-versa.

+
Op Sequencing
+

The way that operations are planned for execution in NoSQLBench is based on a stable ordering that +is configurable. The statement forms are mixed together based on their relative ratios. The three +schemes currently supported are round-robin with exhaustion (bucket), duplicate in order +(concat), and a way to spread each statement out over the unit interval +(interval). These account for most configuration scenarios without users having to micromanage +their statement templates.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/jsonpath-picker.min.css b/jsonpath-picker.min.css new file mode 100644 index 000000000..bb9e90370 --- /dev/null +++ b/jsonpath-picker.min.css @@ -0,0 +1,58 @@ +ul.json-dict, ol.json-array { + list-style-type: none; + margin: 0 0 0 1px; + border-left: 1px dotted #ccc; + padding-left: 2em +} + +.json-string { + color: #0b7500 +} + +.json-literal { + color: #1a01cc; + font-weight: bold +} + +a.json-toggle { + position: relative; + color: inherit; + text-decoration: none +} + +a.json-toggle:focus { + outline: 0 +} + +a.json-toggle:before { + color: #aaa; + content: "\25BC"; + position: absolute; + display: inline-block; + width: 1em; + left: -1em +} + +a.json-toggle.collapsed:before { + content: "\25B6" +} + +a.json-placeholder { + color: #aaa; + padding: 0 1em; + text-decoration: none +} + +a.json-placeholder:hover { + text-decoration: underline +} + +.pick-path { + color: lightgray; + cursor: pointer; + margin-left: 3px +} + +.pick-path:hover { + color: darkgray +} diff --git a/jsonpath-picker.min.js b/jsonpath-picker.min.js new file mode 100644 index 000000000..7d37b9234 --- /dev/null +++ b/jsonpath-picker.min.js @@ -0,0 +1 @@ +!function a(c,i,s){function l(t,e){if(!i[t]){if(!c[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(f)return f(t,!0);var o=new Error("Cannot find module '"+t+"'");throw o.code="MODULE_NOT_FOUND",o}var r=i[t]={exports:{}};c[t][0].call(r.exports,function(e){return l(c[t][1][e]||e)},r,r.exports,a,c,i,s)}return i[t].exports}for(var f="function"==typeof require&&require,e=0;e'.concat(f,""))}else p(a[c],".json-placeholder",function(e){return e.parentNode.removeChild(e)});t.stopPropagation(),t.preventDefault()}function y(e){for(var t=e.target;t&&t!==this;)t.matches("a.json-toggle")&&(o.call(null,t,e),e.stopPropagation(),e.preventDefault()),t=t.parentNode}function r(e,t){p(e,"a.json-toggle",function(e){return u(e)}),t.stopPropagation(),t.preventDefault()}function d(e){for(var t=e.target;t&&t!==this;)t.matches("a.json-placeholder")&&r.call(null,t,e),t=t.parentNode}function a(e){if(0!==v.length){for(var t=function(e,t){for(var n=[],o=e&&e.parentElement;o;o=o.parentElement)"string"==typeof t&&o.matches(t)&&n.push(o);return n}(e,"li").reverse(),n=[],o=0;o/g,">");!function(e){return/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#:.?+=&%@!\-/]))?/.test(e)}(r)?o+='"'.concat(r,'"'):o+='').concat(r,"")}else if("number"==typeof t)o+=''.concat(t,"");else if("boolean"==typeof t)o+=''.concat(t,"");else if(null===t)o+='null';else if(t instanceof Array)if(0';for(var a=0;a'),f(t[a])&&(o+=''),o+=e(t[a],n),a";o+="]"}else o+="[]";else if("object"===l(t)){var c=Object.keys(t).length;if(0');var s=n.outputWithQuotes?'"'.concat(i,'"'):i;f(t[i])?o+=''.concat(s,""):o+=s,o+='&'+n.pickerIcon+";",o+=": ".concat(e(t[i],n)),0<(c-=1)&&(o+=","),o+=""}o+="}"}else o+="{}"}return o}(t,g);if(f(t)&&(a=''.concat(a)),e.innerHTML=a,function(e,t,n,o){var r=o,a=n,c=t;"function"==typeof t&&(r=n,a=t,c=window),r=!!r,(c="string"==typeof c?document.querySelector(c):c)&&c.removeEventListener(e,a,r)}("click",e),e.addEventListener("click",y),e.addEventListener("click",d),g.WithoutPicker){var c=e.getAttribute("data-jsonpath-uniq-id");document.querySelectorAll("[id*='".concat(c,"'] .pick-path")).forEach(function(e){return e.parentNode.removeChild(e)})}else e.addEventListener("click",h);if(!0===g.outputCollapsed)for(var i=document.querySelectorAll("a.json-toggle"),s=0;s.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo} diff --git a/katex.min.js b/katex.min.js new file mode 100644 index 000000000..a9b96ca64 --- /dev/null +++ b/katex.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.katex=t():e.katex=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,r){for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t={};e.d(t,{default:function(){return Qn}});var r=function e(t,r){this.position=void 0;var n,a="KaTeX parse error: "+t,i=r&&r.loc;if(i&&i.start<=i.end){var o=i.lexer.input;n=i.start;var s=i.end;n===o.length?a+=" at end of input: ":a+=" at position "+(n+1)+": ";var l=o.slice(n,s).replace(/[^]/g,"$&\u0332");a+=(n>15?"\u2026"+o.slice(n-15,n):o.slice(0,n))+l+(s+15":">","<":"<",'"':""","'":"'"},o=/[&><"']/g;var s=function e(t){return"ordgroup"===t.type||"color"===t.type?1===t.body.length?e(t.body[0]):t:"font"===t.type?e(t.body):t},l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(o,(function(e){return i[e]}))},hyphenate:function(e){return e.replace(a,"-$1").toLowerCase()},getBaseElem:s,isCharacterBox:function(e){var t=s(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){var t=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=t?t[1]:"_relative"}},h={displayMode:{type:"boolean",description:"Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.",cli:"-d, --display-mode"},output:{type:{enum:["htmlAndMathml","html","mathml"]},description:"Determines the markup language of the output.",cli:"-F, --format "},leqno:{type:"boolean",description:"Render display math in leqno style (left-justified tags)."},fleqn:{type:"boolean",description:"Render display math flush left."},throwOnError:{type:"boolean",default:!0,cli:"-t, --no-throw-on-error",cliDescription:"Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error."},errorColor:{type:"string",default:"#cc0000",cli:"-c, --error-color ",cliDescription:"A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.",cliProcessor:function(e){return"#"+e}},macros:{type:"object",cli:"-m, --macro ",cliDescription:"Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).",cliDefault:[],cliProcessor:function(e,t){return t.push(e),t}},minRuleThickness:{type:"number",description:"Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.",processor:function(e){return Math.max(0,e)},cli:"--min-rule-thickness ",cliProcessor:parseFloat},colorIsTextColor:{type:"boolean",description:"Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.",cli:"-b, --color-is-text-color"},strict:{type:[{enum:["warn","ignore","error"]},"boolean","function"],description:"Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.",cli:"-S, --strict",cliDefault:!1},trust:{type:["boolean","function"],description:"Trust the input, enabling all HTML features such as \\url.",cli:"-T, --trust"},maxSize:{type:"number",default:1/0,description:"If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large",processor:function(e){return Math.max(0,e)},cli:"-s, --max-size ",cliProcessor:parseInt},maxExpand:{type:"number",default:1e3,description:"Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.",processor:function(e){return Math.max(0,e)},cli:"-e, --max-expand ",cliProcessor:function(e){return"Infinity"===e?1/0:parseInt(e)}},globalGroup:{type:"boolean",cli:!1}};function m(e){if(e.default)return e.default;var t=e.type,r=Array.isArray(t)?t[0]:t;if("string"!=typeof r)return r.enum[0];switch(r){case"boolean":return!1;case"string":return"";case"number":return 0;case"object":return{}}}var c=function(){function e(e){for(var t in this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0,this.errorColor=void 0,this.macros=void 0,this.minRuleThickness=void 0,this.colorIsTextColor=void 0,this.strict=void 0,this.trust=void 0,this.maxSize=void 0,this.maxExpand=void 0,this.globalGroup=void 0,e=e||{},h)if(h.hasOwnProperty(t)){var r=h[t];this[t]=void 0!==e[t]?r.processor?r.processor(e[t]):e[t]:m(r)}}var t=e.prototype;return t.reportNonstrict=function(e,t,r){var a=this.strict;if("function"==typeof a&&(a=a(e,t,r)),a&&"ignore"!==a){if(!0===a||"error"===a)throw new n("LaTeX-incompatible input and strict mode is set to 'error': "+t+" ["+e+"]",r);"warn"===a?"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"):"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+a+"': "+t+" ["+e+"]")}},t.useStrictBehavior=function(e,t,r){var n=this.strict;if("function"==typeof n)try{n=n(e,t,r)}catch(e){n="error"}return!(!n||"ignore"===n)&&(!0===n||"error"===n||("warn"===n?("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"),!1):("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+n+"': "+t+" ["+e+"]"),!1)))},t.isTrusted=function(e){e.url&&!e.protocol&&(e.protocol=l.protocolFromUrl(e.url));var t="function"==typeof this.trust?this.trust(e):this.trust;return Boolean(t)},e}(),u=function(){function e(e,t,r){this.id=void 0,this.size=void 0,this.cramped=void 0,this.id=e,this.size=t,this.cramped=r}var t=e.prototype;return t.sup=function(){return p[d[this.id]]},t.sub=function(){return p[f[this.id]]},t.fracNum=function(){return p[g[this.id]]},t.fracDen=function(){return p[v[this.id]]},t.cramp=function(){return p[b[this.id]]},t.text=function(){return p[y[this.id]]},t.isTight=function(){return this.size>=2},e}(),p=[new u(0,0,!1),new u(1,0,!0),new u(2,1,!1),new u(3,1,!0),new u(4,2,!1),new u(5,2,!0),new u(6,3,!1),new u(7,3,!0)],d=[4,5,4,5,6,7,6,7],f=[5,5,5,5,7,7,7,7],g=[2,3,4,5,6,7,6,7],v=[3,3,5,5,7,7,7,7],b=[1,1,3,3,5,5,7,7],y=[0,1,2,3,2,3,2,3],x={DISPLAY:p[0],TEXT:p[2],SCRIPT:p[4],SCRIPTSCRIPT:p[6]},w=[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}];var k=[];function S(e){for(var t=0;t=k[t]&&e<=k[t+1])return!0;return!1}w.forEach((function(e){return e.blocks.forEach((function(e){return k.push.apply(k,e)}))}));var M=80,z={doubleleftarrow:"M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",doublerightarrow:"M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",leftarrow:"M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",leftbrace:"M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",leftbraceunder:"M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",leftgroup:"M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",leftgroupunder:"M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",leftharpoon:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",leftharpoonplus:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",leftharpoondown:"M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",leftharpoondownplus:"M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",lefthook:"M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",leftlinesegment:"M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",leftmapsto:"M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",leftToFrom:"M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",longequal:"M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",midbrace:"M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",midbraceunder:"M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",oiintSize1:"M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",oiintSize2:"M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",oiiintSize1:"M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",oiiintSize2:"M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",rightarrow:"M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",rightbrace:"M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",rightbraceunder:"M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",rightgroup:"M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",rightgroupunder:"M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",rightharpoon:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",rightharpoonplus:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",rightharpoondown:"M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",rightharpoondownplus:"M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",righthook:"M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",rightlinesegment:"M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",rightToFrom:"M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",twoheadleftarrow:"M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",twoheadrightarrow:"M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",tilde1:"M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",tilde2:"M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",tilde3:"M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",tilde4:"M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",vec:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",widehat1:"M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",widehat2:"M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat3:"M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat4:"M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widecheck1:"M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",widecheck2:"M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck3:"M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck4:"M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",baraboveleftarrow:"M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",rightarrowabovebar:"M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",baraboveshortleftharpoon:"M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",rightharpoonaboveshortbar:"M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",shortbaraboveleftharpoon:"M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",shortrightharpoonabovebar:"M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"},A=function(){function e(e){this.children=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.children=e,this.classes=[],this.height=0,this.depth=0,this.maxFontSize=0,this.style={}}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){for(var e=document.createDocumentFragment(),t=0;t=5?0:e>=3?1:2]){var r=N[t]={cssEmPerMu:B.quad[t]/18};for(var n in B)B.hasOwnProperty(n)&&(r[n]=B[n][t])}return N[t]}(this.size)),this._fontMetrics},t.getColor=function(){return this.phantom?"transparent":this.color},e}();H.BASESIZE=6;var E=H,L={pt:1,mm:7227/2540,cm:7227/254,in:72.27,bp:1.00375,pc:12,dd:1238/1157,cc:14856/1157,nd:685/642,nc:1370/107,sp:1/65536,px:1.00375},D={ex:!0,em:!0,mu:!0},P=function(e){return"string"!=typeof e&&(e=e.unit),e in L||e in D||"ex"===e},F=function(e,t){var r;if(e.unit in L)r=L[e.unit]/t.fontMetrics().ptPerEm/t.sizeMultiplier;else if("mu"===e.unit)r=t.fontMetrics().cssEmPerMu;else{var a;if(a=t.style.isTight()?t.havingStyle(t.style.text()):t,"ex"===e.unit)r=a.fontMetrics().xHeight;else{if("em"!==e.unit)throw new n("Invalid unit: '"+e.unit+"'");r=a.fontMetrics().quad}a!==t&&(r*=a.sizeMultiplier/t.sizeMultiplier)}return Math.min(e.number*r,t.maxSize)},V=function(e){return+e.toFixed(4)+"em"},G=function(e){return e.filter((function(e){return e})).join(" ")},U=function(e,t,r){if(this.classes=e||[],this.attributes={},this.height=0,this.depth=0,this.maxFontSize=0,this.style=r||{},t){t.style.isTight()&&this.classes.push("mtight");var n=t.getColor();n&&(this.style.color=n)}},Y=function(e){var t=document.createElement(e);for(var r in t.className=G(this.classes),this.style)this.style.hasOwnProperty(r)&&(t.style[r]=this.style[r]);for(var n in this.attributes)this.attributes.hasOwnProperty(n)&&t.setAttribute(n,this.attributes[n]);for(var a=0;a"},W=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.width=void 0,this.maxFontSize=void 0,this.style=void 0,U.call(this,e,r,n),this.children=t||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return Y.call(this,"span")},t.toMarkup=function(){return X.call(this,"span")},e}(),_=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,U.call(this,t,n),this.children=r||[],this.setAttribute("href",e)}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return Y.call(this,"a")},t.toMarkup=function(){return X.call(this,"a")},e}(),j=function(){function e(e,t,r){this.src=void 0,this.alt=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.alt=t,this.src=e,this.classes=["mord"],this.style=r}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createElement("img");for(var t in e.src=this.src,e.alt=this.alt,e.className="mord",this.style)this.style.hasOwnProperty(t)&&(e.style[t]=this.style[t]);return e},t.toMarkup=function(){var e=""+this.alt+"=a[0]&&e<=a[1])return r.name}return null}(this.text.charCodeAt(0));l&&this.classes.push(l+"_fallback"),/[\xee\xef\xed\xec]/.test(this.text)&&(this.text=$[this.text])}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createTextNode(this.text),t=null;for(var r in this.italic>0&&((t=document.createElement("span")).style.marginRight=V(this.italic)),this.classes.length>0&&((t=t||document.createElement("span")).className=G(this.classes)),this.style)this.style.hasOwnProperty(r)&&((t=t||document.createElement("span")).style[r]=this.style[r]);return t?(t.appendChild(e),t):e},t.toMarkup=function(){var e=!1,t="0&&(r+="margin-right:"+this.italic+"em;"),this.style)this.style.hasOwnProperty(n)&&(r+=l.hyphenate(n)+":"+this.style[n]+";");r&&(e=!0,t+=' style="'+l.escape(r)+'"');var a=l.escape(this.text);return e?(t+=">",t+=a,t+=""):a},e}(),K=function(){function e(e,t){this.children=void 0,this.attributes=void 0,this.children=e||[],this.attributes=t||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","svg");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);for(var r=0;r":""},e}(),Q=function(){function e(e){this.attributes=void 0,this.attributes=e||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","line");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);return e},t.toMarkup=function(){var e="","\\gt",!0),ie(oe,le,be,"\u2208","\\in",!0),ie(oe,le,be,"\ue020","\\@not"),ie(oe,le,be,"\u2282","\\subset",!0),ie(oe,le,be,"\u2283","\\supset",!0),ie(oe,le,be,"\u2286","\\subseteq",!0),ie(oe,le,be,"\u2287","\\supseteq",!0),ie(oe,he,be,"\u2288","\\nsubseteq",!0),ie(oe,he,be,"\u2289","\\nsupseteq",!0),ie(oe,le,be,"\u22a8","\\models"),ie(oe,le,be,"\u2190","\\leftarrow",!0),ie(oe,le,be,"\u2264","\\le"),ie(oe,le,be,"\u2264","\\leq",!0),ie(oe,le,be,"<","\\lt",!0),ie(oe,le,be,"\u2192","\\rightarrow",!0),ie(oe,le,be,"\u2192","\\to"),ie(oe,he,be,"\u2271","\\ngeq",!0),ie(oe,he,be,"\u2270","\\nleq",!0),ie(oe,le,ye,"\xa0","\\ "),ie(oe,le,ye,"\xa0","\\space"),ie(oe,le,ye,"\xa0","\\nobreakspace"),ie(se,le,ye,"\xa0","\\ "),ie(se,le,ye,"\xa0"," "),ie(se,le,ye,"\xa0","\\space"),ie(se,le,ye,"\xa0","\\nobreakspace"),ie(oe,le,ye,null,"\\nobreak"),ie(oe,le,ye,null,"\\allowbreak"),ie(oe,le,ve,",",","),ie(oe,le,ve,";",";"),ie(oe,he,ce,"\u22bc","\\barwedge",!0),ie(oe,he,ce,"\u22bb","\\veebar",!0),ie(oe,le,ce,"\u2299","\\odot",!0),ie(oe,le,ce,"\u2295","\\oplus",!0),ie(oe,le,ce,"\u2297","\\otimes",!0),ie(oe,le,xe,"\u2202","\\partial",!0),ie(oe,le,ce,"\u2298","\\oslash",!0),ie(oe,he,ce,"\u229a","\\circledcirc",!0),ie(oe,he,ce,"\u22a1","\\boxdot",!0),ie(oe,le,ce,"\u25b3","\\bigtriangleup"),ie(oe,le,ce,"\u25bd","\\bigtriangledown"),ie(oe,le,ce,"\u2020","\\dagger"),ie(oe,le,ce,"\u22c4","\\diamond"),ie(oe,le,ce,"\u22c6","\\star"),ie(oe,le,ce,"\u25c3","\\triangleleft"),ie(oe,le,ce,"\u25b9","\\triangleright"),ie(oe,le,ge,"{","\\{"),ie(se,le,xe,"{","\\{"),ie(se,le,xe,"{","\\textbraceleft"),ie(oe,le,ue,"}","\\}"),ie(se,le,xe,"}","\\}"),ie(se,le,xe,"}","\\textbraceright"),ie(oe,le,ge,"{","\\lbrace"),ie(oe,le,ue,"}","\\rbrace"),ie(oe,le,ge,"[","\\lbrack",!0),ie(se,le,xe,"[","\\lbrack",!0),ie(oe,le,ue,"]","\\rbrack",!0),ie(se,le,xe,"]","\\rbrack",!0),ie(oe,le,ge,"(","\\lparen",!0),ie(oe,le,ue,")","\\rparen",!0),ie(se,le,xe,"<","\\textless",!0),ie(se,le,xe,">","\\textgreater",!0),ie(oe,le,ge,"\u230a","\\lfloor",!0),ie(oe,le,ue,"\u230b","\\rfloor",!0),ie(oe,le,ge,"\u2308","\\lceil",!0),ie(oe,le,ue,"\u2309","\\rceil",!0),ie(oe,le,xe,"\\","\\backslash"),ie(oe,le,xe,"\u2223","|"),ie(oe,le,xe,"\u2223","\\vert"),ie(se,le,xe,"|","\\textbar",!0),ie(oe,le,xe,"\u2225","\\|"),ie(oe,le,xe,"\u2225","\\Vert"),ie(se,le,xe,"\u2225","\\textbardbl"),ie(se,le,xe,"~","\\textasciitilde"),ie(se,le,xe,"\\","\\textbackslash"),ie(se,le,xe,"^","\\textasciicircum"),ie(oe,le,be,"\u2191","\\uparrow",!0),ie(oe,le,be,"\u21d1","\\Uparrow",!0),ie(oe,le,be,"\u2193","\\downarrow",!0),ie(oe,le,be,"\u21d3","\\Downarrow",!0),ie(oe,le,be,"\u2195","\\updownarrow",!0),ie(oe,le,be,"\u21d5","\\Updownarrow",!0),ie(oe,le,fe,"\u2210","\\coprod"),ie(oe,le,fe,"\u22c1","\\bigvee"),ie(oe,le,fe,"\u22c0","\\bigwedge"),ie(oe,le,fe,"\u2a04","\\biguplus"),ie(oe,le,fe,"\u22c2","\\bigcap"),ie(oe,le,fe,"\u22c3","\\bigcup"),ie(oe,le,fe,"\u222b","\\int"),ie(oe,le,fe,"\u222b","\\intop"),ie(oe,le,fe,"\u222c","\\iint"),ie(oe,le,fe,"\u222d","\\iiint"),ie(oe,le,fe,"\u220f","\\prod"),ie(oe,le,fe,"\u2211","\\sum"),ie(oe,le,fe,"\u2a02","\\bigotimes"),ie(oe,le,fe,"\u2a01","\\bigoplus"),ie(oe,le,fe,"\u2a00","\\bigodot"),ie(oe,le,fe,"\u222e","\\oint"),ie(oe,le,fe,"\u222f","\\oiint"),ie(oe,le,fe,"\u2230","\\oiiint"),ie(oe,le,fe,"\u2a06","\\bigsqcup"),ie(oe,le,fe,"\u222b","\\smallint"),ie(se,le,pe,"\u2026","\\textellipsis"),ie(oe,le,pe,"\u2026","\\mathellipsis"),ie(se,le,pe,"\u2026","\\ldots",!0),ie(oe,le,pe,"\u2026","\\ldots",!0),ie(oe,le,pe,"\u22ef","\\@cdots",!0),ie(oe,le,pe,"\u22f1","\\ddots",!0),ie(oe,le,xe,"\u22ee","\\varvdots"),ie(oe,le,me,"\u02ca","\\acute"),ie(oe,le,me,"\u02cb","\\grave"),ie(oe,le,me,"\xa8","\\ddot"),ie(oe,le,me,"~","\\tilde"),ie(oe,le,me,"\u02c9","\\bar"),ie(oe,le,me,"\u02d8","\\breve"),ie(oe,le,me,"\u02c7","\\check"),ie(oe,le,me,"^","\\hat"),ie(oe,le,me,"\u20d7","\\vec"),ie(oe,le,me,"\u02d9","\\dot"),ie(oe,le,me,"\u02da","\\mathring"),ie(oe,le,de,"\ue131","\\@imath"),ie(oe,le,de,"\ue237","\\@jmath"),ie(oe,le,xe,"\u0131","\u0131"),ie(oe,le,xe,"\u0237","\u0237"),ie(se,le,xe,"\u0131","\\i",!0),ie(se,le,xe,"\u0237","\\j",!0),ie(se,le,xe,"\xdf","\\ss",!0),ie(se,le,xe,"\xe6","\\ae",!0),ie(se,le,xe,"\u0153","\\oe",!0),ie(se,le,xe,"\xf8","\\o",!0),ie(se,le,xe,"\xc6","\\AE",!0),ie(se,le,xe,"\u0152","\\OE",!0),ie(se,le,xe,"\xd8","\\O",!0),ie(se,le,me,"\u02ca","\\'"),ie(se,le,me,"\u02cb","\\`"),ie(se,le,me,"\u02c6","\\^"),ie(se,le,me,"\u02dc","\\~"),ie(se,le,me,"\u02c9","\\="),ie(se,le,me,"\u02d8","\\u"),ie(se,le,me,"\u02d9","\\."),ie(se,le,me,"\xb8","\\c"),ie(se,le,me,"\u02da","\\r"),ie(se,le,me,"\u02c7","\\v"),ie(se,le,me,"\xa8",'\\"'),ie(se,le,me,"\u02dd","\\H"),ie(se,le,me,"\u25ef","\\textcircled");var we={"--":!0,"---":!0,"``":!0,"''":!0};ie(se,le,xe,"\u2013","--",!0),ie(se,le,xe,"\u2013","\\textendash"),ie(se,le,xe,"\u2014","---",!0),ie(se,le,xe,"\u2014","\\textemdash"),ie(se,le,xe,"\u2018","`",!0),ie(se,le,xe,"\u2018","\\textquoteleft"),ie(se,le,xe,"\u2019","'",!0),ie(se,le,xe,"\u2019","\\textquoteright"),ie(se,le,xe,"\u201c","``",!0),ie(se,le,xe,"\u201c","\\textquotedblleft"),ie(se,le,xe,"\u201d","''",!0),ie(se,le,xe,"\u201d","\\textquotedblright"),ie(oe,le,xe,"\xb0","\\degree",!0),ie(se,le,xe,"\xb0","\\degree"),ie(se,le,xe,"\xb0","\\textdegree",!0),ie(oe,le,xe,"\xa3","\\pounds"),ie(oe,le,xe,"\xa3","\\mathsterling",!0),ie(se,le,xe,"\xa3","\\pounds"),ie(se,le,xe,"\xa3","\\textsterling",!0),ie(oe,he,xe,"\u2720","\\maltese"),ie(se,he,xe,"\u2720","\\maltese");for(var ke='0123456789/@."',Se=0;Set&&(t=i.height),i.depth>r&&(r=i.depth),i.maxFontSize>n&&(n=i.maxFontSize)}e.height=t,e.depth=r,e.maxFontSize=n},Xe=function(e,t,r,n){var a=new W(e,t,r,n);return Ye(a),a},We=function(e,t,r,n){return new W(e,t,r,n)},_e=function(e){var t=new A(e);return Ye(t),t},je=function(e,t,r){var n="";switch(e){case"amsrm":n="AMS";break;case"textrm":n="Main";break;case"textsf":n="SansSerif";break;case"texttt":n="Typewriter";break;default:n=e}return n+"-"+("textbf"===t&&"textit"===r?"BoldItalic":"textbf"===t?"Bold":"textit"===t?"Italic":"Regular")},$e={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathit:{variant:"italic",fontName:"Main-Italic"},mathnormal:{variant:"italic",fontName:"Math-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}},Ze={vec:["vec",.471,.714],oiintSize1:["oiintSize1",.957,.499],oiintSize2:["oiintSize2",1.472,.659],oiiintSize1:["oiiintSize1",1.304,.499],oiiintSize2:["oiiintSize2",1.98,.659]},Ke={fontMap:$e,makeSymbol:Ge,mathsym:function(e,t,r,n){return void 0===n&&(n=[]),"boldsymbol"===r.font&&Ve(e,"Main-Bold",t).metrics?Ge(e,"Main-Bold",t,r,n.concat(["mathbf"])):"\\"===e||"main"===ae[t][e].font?Ge(e,"Main-Regular",t,r,n):Ge(e,"AMS-Regular",t,r,n.concat(["amsrm"]))},makeSpan:Xe,makeSvgSpan:We,makeLineSpan:function(e,t,r){var n=Xe([e],[],t);return n.height=Math.max(r||t.fontMetrics().defaultRuleThickness,t.minRuleThickness),n.style.borderBottomWidth=V(n.height),n.maxFontSize=1,n},makeAnchor:function(e,t,r,n){var a=new _(e,t,r,n);return Ye(a),a},makeFragment:_e,wrapFragment:function(e,t){return e instanceof A?Xe([],[e],t):e},makeVList:function(e,t){for(var r=function(e){if("individualShift"===e.positionType){for(var t=e.children,r=[t[0]],n=-t[0].shift-t[0].elem.depth,a=n,i=1;i0&&(o.push(kt(s,t)),s=[]),o.push(a[l]));s.length>0&&o.push(kt(s,t)),r?((i=kt(ft(r,t,!0))).classes=["tag"],o.push(i)):n&&o.push(n);var m=mt(["katex-html"],o);if(m.setAttribute("aria-hidden","true"),i){var c=i.children[0];c.style.height=V(m.height+m.depth),m.depth&&(c.style.verticalAlign=V(-m.depth))}return m}function Mt(e){return new A(e)}var zt=function(){function e(e,t,r){this.type=void 0,this.attributes=void 0,this.children=void 0,this.classes=void 0,this.type=e,this.attributes={},this.children=t||[],this.classes=r||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.getAttribute=function(e){return this.attributes[e]},t.toNode=function(){var e=document.createElementNS("http://www.w3.org/1998/Math/MathML",this.type);for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);this.classes.length>0&&(e.className=G(this.classes));for(var r=0;r0&&(e+=' class ="'+l.escape(G(this.classes))+'"'),e+=">";for(var r=0;r"},t.toText=function(){return this.children.map((function(e){return e.toText()})).join("")},e}(),At=function(){function e(e){this.text=void 0,this.text=e}var t=e.prototype;return t.toNode=function(){return document.createTextNode(this.text)},t.toMarkup=function(){return l.escape(this.toText())},t.toText=function(){return this.text},e}(),Tt={MathNode:zt,TextNode:At,SpaceNode:function(){function e(e){this.width=void 0,this.character=void 0,this.width=e,this.character=e>=.05555&&e<=.05556?"\u200a":e>=.1666&&e<=.1667?"\u2009":e>=.2222&&e<=.2223?"\u2005":e>=.2777&&e<=.2778?"\u2005\u200a":e>=-.05556&&e<=-.05555?"\u200a\u2063":e>=-.1667&&e<=-.1666?"\u2009\u2063":e>=-.2223&&e<=-.2222?"\u205f\u2063":e>=-.2778&&e<=-.2777?"\u2005\u2063":null}var t=e.prototype;return t.toNode=function(){if(this.character)return document.createTextNode(this.character);var e=document.createElementNS("http://www.w3.org/1998/Math/MathML","mspace");return e.setAttribute("width",V(this.width)),e},t.toMarkup=function(){return this.character?""+this.character+"":''},t.toText=function(){return this.character?this.character:" "},e}(),newDocumentFragment:Mt},Bt=function(e,t,r){return!ae[t][e]||!ae[t][e].replace||55349===e.charCodeAt(0)||we.hasOwnProperty(e)&&r&&(r.fontFamily&&"tt"===r.fontFamily.substr(4,2)||r.font&&"tt"===r.font.substr(4,2))||(e=ae[t][e].replace),new Tt.TextNode(e)},Ct=function(e){return 1===e.length?e[0]:new Tt.MathNode("mrow",e)},qt=function(e,t){if("texttt"===t.fontFamily)return"monospace";if("textsf"===t.fontFamily)return"textit"===t.fontShape&&"textbf"===t.fontWeight?"sans-serif-bold-italic":"textit"===t.fontShape?"sans-serif-italic":"textbf"===t.fontWeight?"bold-sans-serif":"sans-serif";if("textit"===t.fontShape&&"textbf"===t.fontWeight)return"bold-italic";if("textit"===t.fontShape)return"italic";if("textbf"===t.fontWeight)return"bold";var r=t.font;if(!r||"mathnormal"===r)return null;var n=e.mode;if("mathit"===r)return"italic";if("boldsymbol"===r)return"textord"===e.type?"bold":"bold-italic";if("mathbf"===r)return"bold";if("mathbb"===r)return"double-struck";if("mathfrak"===r)return"fraktur";if("mathscr"===r||"mathcal"===r)return"script";if("mathsf"===r)return"sans-serif";if("mathtt"===r)return"monospace";var a=e.text;return l.contains(["\\imath","\\jmath"],a)?null:(ae[n][a]&&ae[n][a].replace&&(a=ae[n][a].replace),q(a,Ke.fontMap[r].fontName,n)?Ke.fontMap[r].variant:null)},Nt=function(e,t,r){if(1===e.length){var n=Rt(e[0],t);return r&&n instanceof zt&&"mo"===n.type&&(n.setAttribute("lspace","0em"),n.setAttribute("rspace","0em")),[n]}for(var a,i=[],o=0;o0&&(p.text=p.text.slice(0,1)+"\u0338"+p.text.slice(1),i.pop())}}}i.push(s),a=s}return i},It=function(e,t,r){return Ct(Nt(e,t,r))},Rt=function(e,t){if(!e)return new Tt.MathNode("mrow");if(it[e.type])return it[e.type](e,t);throw new n("Got group of unknown type: '"+e.type+"'")};function Ot(e,t,r,n,a){var i,o=Nt(e,r);i=1===o.length&&o[0]instanceof zt&&l.contains(["mrow","mtable"],o[0].type)?o[0]:new Tt.MathNode("mrow",o);var s=new Tt.MathNode("annotation",[new Tt.TextNode(t)]);s.setAttribute("encoding","application/x-tex");var h=new Tt.MathNode("semantics",[i,s]),m=new Tt.MathNode("math",[h]);m.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),n&&m.setAttribute("display","block");var c=a?"katex":"katex-mathml";return Ke.makeSpan([c],[m])}var Ht=function(e){return new E({style:e.displayMode?x.DISPLAY:x.TEXT,maxSize:e.maxSize,minRuleThickness:e.minRuleThickness})},Et=function(e,t){if(t.displayMode){var r=["katex-display"];t.leqno&&r.push("leqno"),t.fleqn&&r.push("fleqn"),e=Ke.makeSpan(r,[e])}return e},Lt=function(e,t,r){var n,a=Ht(r);if("mathml"===r.output)return Ot(e,t,a,r.displayMode,!0);if("html"===r.output){var i=St(e,a);n=Ke.makeSpan(["katex"],[i])}else{var o=Ot(e,t,a,r.displayMode,!1),s=St(e,a);n=Ke.makeSpan(["katex"],[o,s])}return Et(n,r)},Dt={widehat:"^",widecheck:"\u02c7",widetilde:"~",utilde:"~",overleftarrow:"\u2190",underleftarrow:"\u2190",xleftarrow:"\u2190",overrightarrow:"\u2192",underrightarrow:"\u2192",xrightarrow:"\u2192",underbrace:"\u23df",overbrace:"\u23de",overgroup:"\u23e0",undergroup:"\u23e1",overleftrightarrow:"\u2194",underleftrightarrow:"\u2194",xleftrightarrow:"\u2194",Overrightarrow:"\u21d2",xRightarrow:"\u21d2",overleftharpoon:"\u21bc",xleftharpoonup:"\u21bc",overrightharpoon:"\u21c0",xrightharpoonup:"\u21c0",xLeftarrow:"\u21d0",xLeftrightarrow:"\u21d4",xhookleftarrow:"\u21a9",xhookrightarrow:"\u21aa",xmapsto:"\u21a6",xrightharpoondown:"\u21c1",xleftharpoondown:"\u21bd",xrightleftharpoons:"\u21cc",xleftrightharpoons:"\u21cb",xtwoheadleftarrow:"\u219e",xtwoheadrightarrow:"\u21a0",xlongequal:"=",xtofrom:"\u21c4",xrightleftarrows:"\u21c4",xrightequilibrium:"\u21cc",xleftequilibrium:"\u21cb","\\cdrightarrow":"\u2192","\\cdleftarrow":"\u2190","\\cdlongequal":"="},Pt={overrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],overleftarrow:[["leftarrow"],.888,522,"xMinYMin"],underrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],underleftarrow:[["leftarrow"],.888,522,"xMinYMin"],xrightarrow:[["rightarrow"],1.469,522,"xMaxYMin"],"\\cdrightarrow":[["rightarrow"],3,522,"xMaxYMin"],xleftarrow:[["leftarrow"],1.469,522,"xMinYMin"],"\\cdleftarrow":[["leftarrow"],3,522,"xMinYMin"],Overrightarrow:[["doublerightarrow"],.888,560,"xMaxYMin"],xRightarrow:[["doublerightarrow"],1.526,560,"xMaxYMin"],xLeftarrow:[["doubleleftarrow"],1.526,560,"xMinYMin"],overleftharpoon:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoonup:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoondown:[["leftharpoondown"],.888,522,"xMinYMin"],overrightharpoon:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoonup:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoondown:[["rightharpoondown"],.888,522,"xMaxYMin"],xlongequal:[["longequal"],.888,334,"xMinYMin"],"\\cdlongequal":[["longequal"],3,334,"xMinYMin"],xtwoheadleftarrow:[["twoheadleftarrow"],.888,334,"xMinYMin"],xtwoheadrightarrow:[["twoheadrightarrow"],.888,334,"xMaxYMin"],overleftrightarrow:[["leftarrow","rightarrow"],.888,522],overbrace:[["leftbrace","midbrace","rightbrace"],1.6,548],underbrace:[["leftbraceunder","midbraceunder","rightbraceunder"],1.6,548],underleftrightarrow:[["leftarrow","rightarrow"],.888,522],xleftrightarrow:[["leftarrow","rightarrow"],1.75,522],xLeftrightarrow:[["doubleleftarrow","doublerightarrow"],1.75,560],xrightleftharpoons:[["leftharpoondownplus","rightharpoonplus"],1.75,716],xleftrightharpoons:[["leftharpoonplus","rightharpoondownplus"],1.75,716],xhookleftarrow:[["leftarrow","righthook"],1.08,522],xhookrightarrow:[["lefthook","rightarrow"],1.08,522],overlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],underlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],overgroup:[["leftgroup","rightgroup"],.888,342],undergroup:[["leftgroupunder","rightgroupunder"],.888,342],xmapsto:[["leftmapsto","rightarrow"],1.5,522],xtofrom:[["leftToFrom","rightToFrom"],1.75,528],xrightleftarrows:[["baraboveleftarrow","rightarrowabovebar"],1.75,901],xrightequilibrium:[["baraboveshortleftharpoon","rightharpoonaboveshortbar"],1.75,716],xleftequilibrium:[["shortbaraboveleftharpoon","shortrightharpoonabovebar"],1.75,716]},Ft=function(e,t,r,n,a){var i,o=e.height+e.depth+r+n;if(/fbox|color|angl/.test(t)){if(i=Ke.makeSpan(["stretchy",t],[],a),"fbox"===t){var s=a.color&&a.getColor();s&&(i.style.borderColor=s)}}else{var l=[];/^[bx]cancel$/.test(t)&&l.push(new Q({x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})),/^x?cancel$/.test(t)&&l.push(new Q({x1:"0",y1:"100%",x2:"100%",y2:"0","stroke-width":"0.046em"}));var h=new K(l,{width:"100%",height:V(o)});i=Ke.makeSvgSpan([],[h],a)}return i.height=o,i.style.height=V(o),i},Vt=function(e){var t=new Tt.MathNode("mo",[new Tt.TextNode(Dt[e.replace(/^\\/,"")])]);return t.setAttribute("stretchy","true"),t},Gt=function(e,t){var r=function(){var r=4e5,n=e.label.substr(1);if(l.contains(["widehat","widecheck","widetilde","utilde"],n)){var a,i,o,s="ordgroup"===(d=e.base).type?d.body.length:1;if(s>5)"widehat"===n||"widecheck"===n?(a=420,r=2364,o=.42,i=n+"4"):(a=312,r=2340,o=.34,i="tilde4");else{var h=[1,1,2,2,3,3][s];"widehat"===n||"widecheck"===n?(r=[0,1062,2364,2364,2364][h],a=[0,239,300,360,420][h],o=[0,.24,.3,.3,.36,.42][h],i=n+h):(r=[0,600,1033,2339,2340][h],a=[0,260,286,306,312][h],o=[0,.26,.286,.3,.306,.34][h],i="tilde"+h)}var m=new J(i),c=new K([m],{width:"100%",height:V(o),viewBox:"0 0 "+r+" "+a,preserveAspectRatio:"none"});return{span:Ke.makeSvgSpan([],[c],t),minWidth:0,height:o}}var u,p,d,f=[],g=Pt[n],v=g[0],b=g[1],y=g[2],x=y/1e3,w=v.length;if(1===w)u=["hide-tail"],p=[g[3]];else if(2===w)u=["halfarrow-left","halfarrow-right"],p=["xMinYMin","xMaxYMin"];else{if(3!==w)throw new Error("Correct katexImagesData or update code here to support\n "+w+" children.");u=["brace-left","brace-center","brace-right"],p=["xMinYMin","xMidYMin","xMaxYMin"]}for(var k=0;k0&&(n.style.minWidth=V(a)),n};function Ut(e,t){if(!e||e.type!==t)throw new Error("Expected node of type "+t+", but got "+(e?"node of type "+e.type:String(e)));return e}function Yt(e){var t=Xt(e);if(!t)throw new Error("Expected node of symbol group type, but got "+(e?"node of type "+e.type:String(e)));return t}function Xt(e){return e&&("atom"===e.type||re.hasOwnProperty(e.type))?e:null}var Wt=function(e,t){var r,n,a;e&&"supsub"===e.type?(r=(n=Ut(e.base,"accent")).base,e.base=r,a=function(e){if(e instanceof W)return e;throw new Error("Expected span but got "+String(e)+".")}(wt(e,t)),e.base=n):r=(n=Ut(e,"accent")).base;var i=wt(r,t.havingCrampedStyle()),o=0;if(n.isShifty&&l.isCharacterBox(r)){var s=l.getBaseElem(r);o=ee(wt(s,t.havingCrampedStyle())).skew}var h,m="\\c"===n.label,c=m?i.height+i.depth:Math.min(i.height,t.fontMetrics().xHeight);if(n.isStretchy)h=Gt(n,t),h=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"elem",elem:h,wrapperClasses:["svg-align"],wrapperStyle:o>0?{width:"calc(100% - "+V(2*o)+")",marginLeft:V(2*o)}:void 0}]},t);else{var u,p;"\\vec"===n.label?(u=Ke.staticSvg("vec",t),p=Ke.svgData.vec[1]):((u=ee(u=Ke.makeOrd({mode:n.mode,text:n.label},t,"textord"))).italic=0,p=u.width,m&&(c+=u.depth)),h=Ke.makeSpan(["accent-body"],[u]);var d="\\textcircled"===n.label;d&&(h.classes.push("accent-full"),c=i.height);var f=o;d||(f-=p/2),h.style.left=V(f),"\\textcircled"===n.label&&(h.style.top=".2em"),h=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"kern",size:-c},{type:"elem",elem:h}]},t)}var g=Ke.makeSpan(["mord","accent"],[h],t);return a?(a.children[0]=g,a.height=Math.max(g.height,a.height),a.classes[0]="mord",a):g},_t=function(e,t){var r=e.isStretchy?Vt(e.label):new Tt.MathNode("mo",[Bt(e.label,e.mode)]),n=new Tt.MathNode("mover",[Rt(e.base,t),r]);return n.setAttribute("accent","true"),n},jt=new RegExp(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring"].map((function(e){return"\\"+e})).join("|"));ot({type:"accent",names:["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring","\\widecheck","\\widehat","\\widetilde","\\overrightarrow","\\overleftarrow","\\Overrightarrow","\\overleftrightarrow","\\overgroup","\\overlinesegment","\\overleftharpoon","\\overrightharpoon"],props:{numArgs:1},handler:function(e,t){var r=lt(t[0]),n=!jt.test(e.funcName),a=!n||"\\widehat"===e.funcName||"\\widetilde"===e.funcName||"\\widecheck"===e.funcName;return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:n,isShifty:a,base:r}},htmlBuilder:Wt,mathmlBuilder:_t}),ot({type:"accent",names:["\\'","\\`","\\^","\\~","\\=","\\u","\\.",'\\"',"\\c","\\r","\\H","\\v","\\textcircled"],props:{numArgs:1,allowedInText:!0,allowedInMath:!0,argTypes:["primitive"]},handler:function(e,t){var r=t[0],n=e.parser.mode;return"math"===n&&(e.parser.settings.reportNonstrict("mathVsTextAccents","LaTeX's accent "+e.funcName+" works only in text mode"),n="text"),{type:"accent",mode:n,label:e.funcName,isStretchy:!1,isShifty:!0,base:r}},htmlBuilder:Wt,mathmlBuilder:_t}),ot({type:"accentUnder",names:["\\underleftarrow","\\underrightarrow","\\underleftrightarrow","\\undergroup","\\underlinesegment","\\utilde"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"accentUnder",mode:r.mode,label:n,base:a}},htmlBuilder:function(e,t){var r=wt(e.base,t),n=Gt(e,t),a="\\utilde"===e.label?.12:0,i=Ke.makeVList({positionType:"top",positionData:r.height,children:[{type:"elem",elem:n,wrapperClasses:["svg-align"]},{type:"kern",size:a},{type:"elem",elem:r}]},t);return Ke.makeSpan(["mord","accentunder"],[i],t)},mathmlBuilder:function(e,t){var r=Vt(e.label),n=new Tt.MathNode("munder",[Rt(e.base,t),r]);return n.setAttribute("accentunder","true"),n}});var $t=function(e){var t=new Tt.MathNode("mpadded",e?[e]:[]);return t.setAttribute("width","+0.6em"),t.setAttribute("lspace","0.3em"),t};ot({type:"xArrow",names:["\\xleftarrow","\\xrightarrow","\\xLeftarrow","\\xRightarrow","\\xleftrightarrow","\\xLeftrightarrow","\\xhookleftarrow","\\xhookrightarrow","\\xmapsto","\\xrightharpoondown","\\xrightharpoonup","\\xleftharpoondown","\\xleftharpoonup","\\xrightleftharpoons","\\xleftrightharpoons","\\xlongequal","\\xtwoheadrightarrow","\\xtwoheadleftarrow","\\xtofrom","\\xrightleftarrows","\\xrightequilibrium","\\xleftequilibrium","\\\\cdrightarrow","\\\\cdleftarrow","\\\\cdlongequal"],props:{numArgs:1,numOptionalArgs:1},handler:function(e,t,r){var n=e.parser,a=e.funcName;return{type:"xArrow",mode:n.mode,label:a,body:t[0],below:r[0]}},htmlBuilder:function(e,t){var r,n=t.style,a=t.havingStyle(n.sup()),i=Ke.wrapFragment(wt(e.body,a,t),t),o="\\x"===e.label.slice(0,2)?"x":"cd";i.classes.push(o+"-arrow-pad"),e.below&&(a=t.havingStyle(n.sub()),(r=Ke.wrapFragment(wt(e.below,a,t),t)).classes.push(o+"-arrow-pad"));var s,l=Gt(e,t),h=-t.fontMetrics().axisHeight+.5*l.height,m=-t.fontMetrics().axisHeight-.5*l.height-.111;if((i.depth>.25||"\\xleftequilibrium"===e.label)&&(m-=i.depth),r){var c=-t.fontMetrics().axisHeight+r.height+.5*l.height+.111;s=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h},{type:"elem",elem:r,shift:c}]},t)}else s=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h}]},t);return s.children[0].children[0].children[1].classes.push("svg-align"),Ke.makeSpan(["mrel","x-arrow"],[s],t)},mathmlBuilder:function(e,t){var r,n=Vt(e.label);if(n.setAttribute("minsize","x"===e.label.charAt(0)?"1.75em":"3.0em"),e.body){var a=$t(Rt(e.body,t));if(e.below){var i=$t(Rt(e.below,t));r=new Tt.MathNode("munderover",[n,i,a])}else r=new Tt.MathNode("mover",[n,a])}else if(e.below){var o=$t(Rt(e.below,t));r=new Tt.MathNode("munder",[n,o])}else r=$t(),r=new Tt.MathNode("mover",[n,r]);return r}});var Zt={">":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"},Kt=function(e){return"textord"===e.type&&"@"===e.text};function Jt(e,t,r){var n=Zt[e];switch(n){case"\\\\cdrightarrow":case"\\\\cdleftarrow":return r.callFunction(n,[t[0]],[t[1]]);case"\\uparrow":case"\\downarrow":var a={type:"atom",text:n,mode:"math",family:"rel"},i={type:"ordgroup",mode:"math",body:[r.callFunction("\\\\cdleft",[t[0]],[]),r.callFunction("\\Big",[a],[]),r.callFunction("\\\\cdright",[t[1]],[])]};return r.callFunction("\\\\cdparent",[i],[]);case"\\\\cdlongequal":return r.callFunction("\\\\cdlongequal",[],[]);case"\\Vert":return r.callFunction("\\Big",[{type:"textord",text:"\\Vert",mode:"math"}],[]);default:return{type:"textord",text:" ",mode:"math"}}}ot({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"cdlabel",mode:r.mode,side:n.slice(4),label:t[0]}},htmlBuilder:function(e,t){var r=t.havingStyle(t.style.sup()),n=Ke.wrapFragment(wt(e.label,r,t),t);return n.classes.push("cd-label-"+e.side),n.style.bottom=V(.8-n.depth),n.height=0,n.depth=0,n},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mrow",[Rt(e.label,t)]);return(r=new Tt.MathNode("mpadded",[r])).setAttribute("width","0"),"left"===e.side&&r.setAttribute("lspace","-1width"),r.setAttribute("voffset","0.7em"),(r=new Tt.MathNode("mstyle",[r])).setAttribute("displaystyle","false"),r.setAttribute("scriptlevel","1"),r}}),ot({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler:function(e,t){return{type:"cdlabelparent",mode:e.parser.mode,fragment:t[0]}},htmlBuilder:function(e,t){var r=Ke.wrapFragment(wt(e.fragment,t),t);return r.classes.push("cd-vert-arrow"),r},mathmlBuilder:function(e,t){return new Tt.MathNode("mrow",[Rt(e.fragment,t)])}}),ot({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){for(var r=e.parser,a=Ut(t[0],"ordgroup").body,i="",o=0;o=1114111)throw new n("\\@char with invalid code point "+i);return l<=65535?s=String.fromCharCode(l):(l-=65536,s=String.fromCharCode(55296+(l>>10),56320+(1023&l))),{type:"textord",mode:r.mode,text:s}}});var Qt=function(e,t){var r=ft(e.body,t.withColor(e.color),!1);return Ke.makeFragment(r)},er=function(e,t){var r=Nt(e.body,t.withColor(e.color)),n=new Tt.MathNode("mstyle",r);return n.setAttribute("mathcolor",e.color),n};ot({type:"color",names:["\\textcolor"],props:{numArgs:2,allowedInText:!0,argTypes:["color","original"]},handler:function(e,t){var r=e.parser,n=Ut(t[0],"color-token").color,a=t[1];return{type:"color",mode:r.mode,color:n,body:ht(a)}},htmlBuilder:Qt,mathmlBuilder:er}),ot({type:"color",names:["\\color"],props:{numArgs:1,allowedInText:!0,argTypes:["color"]},handler:function(e,t){var r=e.parser,n=e.breakOnTokenText,a=Ut(t[0],"color-token").color;r.gullet.macros.set("\\current@color",a);var i=r.parseExpression(!0,n);return{type:"color",mode:r.mode,color:a,body:i}},htmlBuilder:Qt,mathmlBuilder:er}),ot({type:"cr",names:["\\\\"],props:{numArgs:0,numOptionalArgs:1,argTypes:["size"],allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=r[0],i=!n.settings.displayMode||!n.settings.useStrictBehavior("newLineInDisplayMode","In LaTeX, \\\\ or \\newline does nothing in display mode");return{type:"cr",mode:n.mode,newLine:i,size:a&&Ut(a,"size").value}},htmlBuilder:function(e,t){var r=Ke.makeSpan(["mspace"],[],t);return e.newLine&&(r.classes.push("newline"),e.size&&(r.style.marginTop=V(F(e.size,t)))),r},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mspace");return e.newLine&&(r.setAttribute("linebreak","newline"),e.size&&r.setAttribute("height",V(F(e.size,t)))),r}});var tr={"\\global":"\\global","\\long":"\\\\globallong","\\\\globallong":"\\\\globallong","\\def":"\\gdef","\\gdef":"\\gdef","\\edef":"\\xdef","\\xdef":"\\xdef","\\let":"\\\\globallet","\\futurelet":"\\\\globalfuture"},rr=function(e){var t=e.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(t))throw new n("Expected a control sequence",e);return t},nr=function(e,t,r,n){var a=e.gullet.macros.get(r.text);null==a&&(r.noexpand=!0,a={tokens:[r],numArgs:0,unexpandable:!e.gullet.isExpandable(r.text)}),e.gullet.macros.set(t,a,n)};ot({type:"internal",names:["\\global","\\long","\\\\globallong"],props:{numArgs:0,allowedInText:!0},handler:function(e){var t=e.parser,r=e.funcName;t.consumeSpaces();var a=t.fetch();if(tr[a.text])return"\\global"!==r&&"\\\\globallong"!==r||(a.text=tr[a.text]),Ut(t.parseFunction(),"internal");throw new n("Invalid token after macro prefix",a)}}),ot({type:"internal",names:["\\def","\\gdef","\\edef","\\xdef"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,a=t.gullet.popToken(),i=a.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(i))throw new n("Expected a control sequence",a);for(var o,s=0,l=[[]];"{"!==t.gullet.future().text;)if("#"===(a=t.gullet.popToken()).text){if("{"===t.gullet.future().text){o=t.gullet.future(),l[s].push("{");break}if(a=t.gullet.popToken(),!/^[1-9]$/.test(a.text))throw new n('Invalid argument number "'+a.text+'"');if(parseInt(a.text)!==s+1)throw new n('Argument number "'+a.text+'" out of order');s++,l.push([])}else{if("EOF"===a.text)throw new n("Expected a macro definition");l[s].push(a.text)}var h=t.gullet.consumeArg().tokens;return o&&h.unshift(o),"\\edef"!==r&&"\\xdef"!==r||(h=t.gullet.expandTokens(h)).reverse(),t.gullet.macros.set(i,{tokens:h,numArgs:s,delimiters:l},r===tr[r]),{type:"internal",mode:t.mode}}}),ot({type:"internal",names:["\\let","\\\\globallet"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=rr(t.gullet.popToken());t.gullet.consumeSpaces();var a=function(e){var t=e.gullet.popToken();return"="===t.text&&" "===(t=e.gullet.popToken()).text&&(t=e.gullet.popToken()),t}(t);return nr(t,n,a,"\\\\globallet"===r),{type:"internal",mode:t.mode}}}),ot({type:"internal",names:["\\futurelet","\\\\globalfuture"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,r=e.funcName,n=rr(t.gullet.popToken()),a=t.gullet.popToken(),i=t.gullet.popToken();return nr(t,n,i,"\\\\globalfuture"===r),t.gullet.pushToken(i),t.gullet.pushToken(a),{type:"internal",mode:t.mode}}});var ar=function(e,t,r){var n=q(ae.math[e]&&ae.math[e].replace||e,t,r);if(!n)throw new Error("Unsupported symbol "+e+" and font size "+t+".");return n},ir=function(e,t,r,n){var a=r.havingBaseStyle(t),i=Ke.makeSpan(n.concat(a.sizingClasses(r)),[e],r),o=a.sizeMultiplier/r.sizeMultiplier;return i.height*=o,i.depth*=o,i.maxFontSize=a.sizeMultiplier,i},or=function(e,t,r){var n=t.havingBaseStyle(r),a=(1-t.sizeMultiplier/n.sizeMultiplier)*t.fontMetrics().axisHeight;e.classes.push("delimcenter"),e.style.top=V(a),e.height-=a,e.depth+=a},sr=function(e,t,r,n,a,i){var o=function(e,t,r,n){return Ke.makeSymbol(e,"Size"+t+"-Regular",r,n)}(e,t,a,n),s=ir(Ke.makeSpan(["delimsizing","size"+t],[o],n),x.TEXT,n,i);return r&&or(s,n,x.TEXT),s},lr=function(e,t,r){var n;return n="Size1-Regular"===t?"delim-size1":"delim-size4",{type:"elem",elem:Ke.makeSpan(["delimsizinginner",n],[Ke.makeSpan([],[Ke.makeSymbol(e,t,r)])])}},hr=function(e,t,r){var n=T["Size4-Regular"][e.charCodeAt(0)]?T["Size4-Regular"][e.charCodeAt(0)][4]:T["Size1-Regular"][e.charCodeAt(0)][4],a=new J("inner",function(e,t){switch(e){case"\u239c":return"M291 0 H417 V"+t+" H291z M291 0 H417 V"+t+" H291z";case"\u2223":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145z";case"\u2225":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145zM367 0 H410 V"+t+" H367z M367 0 H410 V"+t+" H367z";case"\u239f":return"M457 0 H583 V"+t+" H457z M457 0 H583 V"+t+" H457z";case"\u23a2":return"M319 0 H403 V"+t+" H319z M319 0 H403 V"+t+" H319z";case"\u23a5":return"M263 0 H347 V"+t+" H263z M263 0 H347 V"+t+" H263z";case"\u23aa":return"M384 0 H504 V"+t+" H384z M384 0 H504 V"+t+" H384z";case"\u23d0":return"M312 0 H355 V"+t+" H312z M312 0 H355 V"+t+" H312z";case"\u2016":return"M257 0 H300 V"+t+" H257z M257 0 H300 V"+t+" H257zM478 0 H521 V"+t+" H478z M478 0 H521 V"+t+" H478z";default:return""}}(e,Math.round(1e3*t))),i=new K([a],{width:V(n),height:V(t),style:"width:"+V(n),viewBox:"0 0 "+1e3*n+" "+Math.round(1e3*t),preserveAspectRatio:"xMinYMin"}),o=Ke.makeSvgSpan([],[i],r);return o.height=t,o.style.height=V(t),o.style.width=V(n),{type:"elem",elem:o}},mr={type:"kern",size:-.008},cr=["|","\\lvert","\\rvert","\\vert"],ur=["\\|","\\lVert","\\rVert","\\Vert"],pr=function(e,t,r,n,a,i){var o,s,h,m;o=h=m=e,s=null;var c="Size1-Regular";"\\uparrow"===e?h=m="\u23d0":"\\Uparrow"===e?h=m="\u2016":"\\downarrow"===e?o=h="\u23d0":"\\Downarrow"===e?o=h="\u2016":"\\updownarrow"===e?(o="\\uparrow",h="\u23d0",m="\\downarrow"):"\\Updownarrow"===e?(o="\\Uparrow",h="\u2016",m="\\Downarrow"):l.contains(cr,e)?h="\u2223":l.contains(ur,e)?h="\u2225":"["===e||"\\lbrack"===e?(o="\u23a1",h="\u23a2",m="\u23a3",c="Size4-Regular"):"]"===e||"\\rbrack"===e?(o="\u23a4",h="\u23a5",m="\u23a6",c="Size4-Regular"):"\\lfloor"===e||"\u230a"===e?(h=o="\u23a2",m="\u23a3",c="Size4-Regular"):"\\lceil"===e||"\u2308"===e?(o="\u23a1",h=m="\u23a2",c="Size4-Regular"):"\\rfloor"===e||"\u230b"===e?(h=o="\u23a5",m="\u23a6",c="Size4-Regular"):"\\rceil"===e||"\u2309"===e?(o="\u23a4",h=m="\u23a5",c="Size4-Regular"):"("===e||"\\lparen"===e?(o="\u239b",h="\u239c",m="\u239d",c="Size4-Regular"):")"===e||"\\rparen"===e?(o="\u239e",h="\u239f",m="\u23a0",c="Size4-Regular"):"\\{"===e||"\\lbrace"===e?(o="\u23a7",s="\u23a8",m="\u23a9",h="\u23aa",c="Size4-Regular"):"\\}"===e||"\\rbrace"===e?(o="\u23ab",s="\u23ac",m="\u23ad",h="\u23aa",c="Size4-Regular"):"\\lgroup"===e||"\u27ee"===e?(o="\u23a7",m="\u23a9",h="\u23aa",c="Size4-Regular"):"\\rgroup"===e||"\u27ef"===e?(o="\u23ab",m="\u23ad",h="\u23aa",c="Size4-Regular"):"\\lmoustache"===e||"\u23b0"===e?(o="\u23a7",m="\u23ad",h="\u23aa",c="Size4-Regular"):"\\rmoustache"!==e&&"\u23b1"!==e||(o="\u23ab",m="\u23a9",h="\u23aa",c="Size4-Regular");var u=ar(o,c,a),p=u.height+u.depth,d=ar(h,c,a),f=d.height+d.depth,g=ar(m,c,a),v=g.height+g.depth,b=0,y=1;if(null!==s){var w=ar(s,c,a);b=w.height+w.depth,y=2}var k=p+v+b,S=k+Math.max(0,Math.ceil((t-k)/(y*f)))*y*f,M=n.fontMetrics().axisHeight;r&&(M*=n.sizeMultiplier);var z=S/2-M,A=[];if(A.push(lr(m,c,a)),A.push(mr),null===s){var T=S-p-v+.016;A.push(hr(h,T,n))}else{var B=(S-p-v-b)/2+.016;A.push(hr(h,B,n)),A.push(mr),A.push(lr(s,c,a)),A.push(mr),A.push(hr(h,B,n))}A.push(mr),A.push(lr(o,c,a));var C=n.havingBaseStyle(x.TEXT),q=Ke.makeVList({positionType:"bottom",positionData:z,children:A},C);return ir(Ke.makeSpan(["delimsizing","mult"],[q],C),x.TEXT,n,i)},dr=.08,fr=function(e,t,r,n,a){var i=function(e,t,r){t*=1e3;var n="";switch(e){case"sqrtMain":n=function(e,t){return"M95,"+(622+e+t)+"\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl"+e/2.075+" -"+e+"\nc5.3,-9.3,12,-14,20,-14\nH400000v"+(40+e)+"H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM"+(834+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize1":n=function(e,t){return"M263,"+(601+e+t)+"c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl"+e/2.084+" -"+e+"\nc4.7,-7.3,11,-11,19,-11\nH40000v"+(40+e)+"H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize2":n=function(e,t){return"M983 "+(10+e+t)+"\nl"+e/3.13+" -"+e+"\nc4,-6.7,10,-10,18,-10 H400000v"+(40+e)+"\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM"+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize3":n=function(e,t){return"M424,"+(2398+e+t)+"\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl"+e/4.223+" -"+e+"c4,-6.7,10,-10,18,-10 H400000\nv"+(40+e)+"H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M"+(1001+e)+" "+t+"\nh400000v"+(40+e)+"h-400000z"}(t,M);break;case"sqrtSize4":n=function(e,t){return"M473,"+(2713+e+t)+"\nc339.3,-1799.3,509.3,-2700,510,-2702 l"+e/5.298+" -"+e+"\nc3.3,-7.3,9.3,-11,18,-11 H400000v"+(40+e)+"H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM"+(1001+e)+" "+t+"h400000v"+(40+e)+"H1017.7z"}(t,M);break;case"sqrtTall":n=function(e,t,r){return"M702 "+(e+t)+"H400000"+(40+e)+"\nH742v"+(r-54-t-e)+"l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 "+t+"H400000v"+(40+e)+"H742z"}(t,M,r)}return n}(e,n,r),o=new J(e,i),s=new K([o],{width:"400em",height:V(t),viewBox:"0 0 400000 "+r,preserveAspectRatio:"xMinYMin slice"});return Ke.makeSvgSpan(["hide-tail"],[s],a)},gr=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","\\surd"],vr=["\\uparrow","\\downarrow","\\updownarrow","\\Uparrow","\\Downarrow","\\Updownarrow","|","\\|","\\vert","\\Vert","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1"],br=["<",">","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"],yr=[0,1.2,1.8,2.4,3],xr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}],wr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"stack"}],kr=[{type:"small",style:x.SCRIPTSCRIPT},{type:"small",style:x.SCRIPT},{type:"small",style:x.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}],Sr=function(e){if("small"===e.type)return"Main-Regular";if("large"===e.type)return"Size"+e.size+"-Regular";if("stack"===e.type)return"Size4-Regular";throw new Error("Add support for delim type '"+e.type+"' here.")},Mr=function(e,t,r,n){for(var a=Math.min(2,3-n.style.size);at)return r[a]}return r[r.length-1]},zr=function(e,t,r,n,a,i){var o;"<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),o=l.contains(br,e)?xr:l.contains(gr,e)?kr:wr;var s=Mr(e,t,o,n);return"small"===s.type?function(e,t,r,n,a,i){var o=Ke.makeSymbol(e,"Main-Regular",a,n),s=ir(o,t,n,i);return r&&or(s,n,t),s}(e,s.style,r,n,a,i):"large"===s.type?sr(e,s.size,r,n,a,i):pr(e,t,r,n,a,i)},Ar={sqrtImage:function(e,t){var r,n,a=t.havingBaseSizing(),i=Mr("\\surd",e*a.sizeMultiplier,kr,a),o=a.sizeMultiplier,s=Math.max(0,t.minRuleThickness-t.fontMetrics().sqrtRuleThickness),l=0,h=0,m=0;return"small"===i.type?(e<1?o=1:e<1.4&&(o=.7),h=(1+s)/o,(r=fr("sqrtMain",l=(1+s+dr)/o,m=1e3+1e3*s+80,s,t)).style.minWidth="0.853em",n=.833/o):"large"===i.type?(m=1080*yr[i.size],h=(yr[i.size]+s)/o,l=(yr[i.size]+s+dr)/o,(r=fr("sqrtSize"+i.size,l,m,s,t)).style.minWidth="1.02em",n=1/o):(l=e+s+dr,h=e+s,m=Math.floor(1e3*e+s)+80,(r=fr("sqrtTall",l,m,s,t)).style.minWidth="0.742em",n=1.056),r.height=h,r.style.height=V(l),{span:r,advanceWidth:n,ruleWidth:(t.fontMetrics().sqrtRuleThickness+s)*o}},sizedDelim:function(e,t,r,a,i){if("<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),l.contains(gr,e)||l.contains(br,e))return sr(e,t,!1,r,a,i);if(l.contains(vr,e))return pr(e,yr[t],!1,r,a,i);throw new n("Illegal delimiter: '"+e+"'")},sizeToMaxHeight:yr,customSizedDelim:zr,leftRightDelim:function(e,t,r,n,a,i){var o=n.fontMetrics().axisHeight*n.sizeMultiplier,s=5/n.fontMetrics().ptPerEm,l=Math.max(t-o,r+o),h=Math.max(l/500*901,2*l-s);return zr(e,h,!0,n,a,i)}},Tr={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},Br=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","<",">","\\langle","\u27e8","\\rangle","\u27e9","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];function Cr(e,t){var r=Xt(e);if(r&&l.contains(Br,r.text))return r;throw new n(r?"Invalid delimiter '"+r.text+"' after '"+t.funcName+"'":"Invalid delimiter type '"+e.type+"'",e)}function qr(e){if(!e.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}ot({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:function(e,t){var r=Cr(t[0],e);return{type:"delimsizing",mode:e.parser.mode,size:Tr[e.funcName].size,mclass:Tr[e.funcName].mclass,delim:r.text}},htmlBuilder:function(e,t){return"."===e.delim?Ke.makeSpan([e.mclass]):Ar.sizedDelim(e.delim,e.size,t,e.mode,[e.mclass])},mathmlBuilder:function(e){var t=[];"."!==e.delim&&t.push(Bt(e.delim,e.mode));var r=new Tt.MathNode("mo",t);"mopen"===e.mclass||"mclose"===e.mclass?r.setAttribute("fence","true"):r.setAttribute("fence","false"),r.setAttribute("stretchy","true");var n=V(Ar.sizeToMaxHeight[e.size]);return r.setAttribute("minsize",n),r.setAttribute("maxsize",n),r}}),ot({type:"leftright-right",names:["\\right"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser.gullet.macros.get("\\current@color");if(r&&"string"!=typeof r)throw new n("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:e.parser.mode,delim:Cr(t[0],e).text,color:r}}}),ot({type:"leftright",names:["\\left"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=Cr(t[0],e),n=e.parser;++n.leftrightDepth;var a=n.parseExpression(!1);--n.leftrightDepth,n.expect("\\right",!1);var i=Ut(n.parseFunction(),"leftright-right");return{type:"leftright",mode:n.mode,body:a,left:r.text,right:i.delim,rightColor:i.color}},htmlBuilder:function(e,t){qr(e);for(var r,n,a=ft(e.body,t,!0,["mopen","mclose"]),i=0,o=0,s=!1,l=0;l-1?"mpadded":"menclose",[Rt(e.body,t)]);switch(e.label){case"\\cancel":n.setAttribute("notation","updiagonalstrike");break;case"\\bcancel":n.setAttribute("notation","downdiagonalstrike");break;case"\\phase":n.setAttribute("notation","phasorangle");break;case"\\sout":n.setAttribute("notation","horizontalstrike");break;case"\\fbox":n.setAttribute("notation","box");break;case"\\angl":n.setAttribute("notation","actuarial");break;case"\\fcolorbox":case"\\colorbox":if(r=t.fontMetrics().fboxsep*t.fontMetrics().ptPerEm,n.setAttribute("width","+"+2*r+"pt"),n.setAttribute("height","+"+2*r+"pt"),n.setAttribute("lspace",r+"pt"),n.setAttribute("voffset",r+"pt"),"\\fcolorbox"===e.label){var a=Math.max(t.fontMetrics().fboxrule,t.minRuleThickness);n.setAttribute("style","border: "+a+"em solid "+String(e.borderColor))}break;case"\\xcancel":n.setAttribute("notation","updiagonalstrike downdiagonalstrike")}return e.backgroundColor&&n.setAttribute("mathbackground",e.backgroundColor),n};ot({type:"enclose",names:["\\colorbox"],props:{numArgs:2,allowedInText:!0,argTypes:["color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ut(t[0],"color-token").color,o=t[1];return{type:"enclose",mode:n.mode,label:a,backgroundColor:i,body:o}},htmlBuilder:Nr,mathmlBuilder:Ir}),ot({type:"enclose",names:["\\fcolorbox"],props:{numArgs:3,allowedInText:!0,argTypes:["color","color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ut(t[0],"color-token").color,o=Ut(t[1],"color-token").color,s=t[2];return{type:"enclose",mode:n.mode,label:a,backgroundColor:o,borderColor:i,body:s}},htmlBuilder:Nr,mathmlBuilder:Ir}),ot({type:"enclose",names:["\\fbox"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!0},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\fbox",body:t[0]}}}),ot({type:"enclose",names:["\\cancel","\\bcancel","\\xcancel","\\sout","\\phase"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"enclose",mode:r.mode,label:n,body:a}},htmlBuilder:Nr,mathmlBuilder:Ir}),ot({type:"enclose",names:["\\angl"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!1},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\angl",body:t[0]}}});var Rr={};function Or(e){for(var t=e.type,r=e.names,n=e.props,a=e.handler,i=e.htmlBuilder,o=e.mathmlBuilder,s={type:t,numArgs:n.numArgs||0,allowedInText:!1,numOptionalArgs:0,handler:a},l=0;l1||!c)&&g.pop(),b.length0&&(y+=.25),m.push({pos:y,isDashed:e[t]})}for(w(o[0]),r=0;r0&&(M<(B+=b)&&(M=B),B=0),e.addJot&&(M+=f),z.height=S,z.depth=M,y+=S,z.pos=y,y+=M+B,h[r]=z,w(o[r+1])}var C,q,N=y/2+t.fontMetrics().axisHeight,I=e.cols||[],R=[],O=[];if(e.tags&&e.tags.some((function(e){return e})))for(r=0;r=s)){var W=void 0;(a>0||e.hskipBeforeAndAfter)&&0!==(W=l.deflt(P.pregap,p))&&((C=Ke.makeSpan(["arraycolsep"],[])).style.width=V(W),R.push(C));var _=[];for(r=0;r0){for(var K=Ke.makeLineSpan("hline",t,c),J=Ke.makeLineSpan("hdashline",t,c),Q=[{type:"elem",elem:h,shift:0}];m.length>0;){var ee=m.pop(),te=ee.pos-N;ee.isDashed?Q.push({type:"elem",elem:J,shift:te}):Q.push({type:"elem",elem:K,shift:te})}h=Ke.makeVList({positionType:"individualShift",children:Q},t)}if(0===O.length)return Ke.makeSpan(["mord"],[h],t);var re=Ke.makeVList({positionType:"individualShift",children:O},t);return re=Ke.makeSpan(["tag"],[re],t),Ke.makeFragment([h,re])},Xr={c:"center ",l:"left ",r:"right "},Wr=function(e,t){for(var r=[],n=new Tt.MathNode("mtd",[],["mtr-glue"]),a=new Tt.MathNode("mtd",[],["mml-eqn-num"]),i=0;i0){var p=e.cols,d="",f=!1,g=0,v=p.length;"separator"===p[0].type&&(c+="top ",g=1),"separator"===p[p.length-1].type&&(c+="bottom ",v-=1);for(var b=g;b0?"left ":"",c+=S[S.length-1].length>0?"right ":"";for(var M=1;M-1?"alignat":"align",o="split"===e.envName,s=Gr(e.parser,{cols:a,addJot:!0,autoTag:o?void 0:Vr(e.envName),emptySingleRow:!0,colSeparationType:i,maxNumCols:o?2:void 0,leqno:e.parser.settings.leqno},"display"),l=0,h={type:"ordgroup",mode:e.mode,body:[]};if(t[0]&&"ordgroup"===t[0].type){for(var m="",c=0;c0&&u&&(f=1),a[p]={type:"align",align:d,pregap:f,postgap:0}}return s.colSeparationType=u?"align":"alignat",s};Or({type:"array",names:["array","darray"],props:{numArgs:1},handler:function(e,t){var r=(Xt(t[0])?[t[0]]:Ut(t[0],"ordgroup").body).map((function(e){var t=Yt(e).text;if(-1!=="lcr".indexOf(t))return{type:"align",align:t};if("|"===t)return{type:"separator",separator:"|"};if(":"===t)return{type:"separator",separator:":"};throw new n("Unknown column alignment: "+t,e)})),a={cols:r,hskipBeforeAndAfter:!0,maxNumCols:r.length};return Gr(e.parser,a,Ur(e.envName))},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","matrix*","pmatrix*","bmatrix*","Bmatrix*","vmatrix*","Vmatrix*"],props:{numArgs:0},handler:function(e){var t={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[e.envName.replace("*","")],r="c",a={hskipBeforeAndAfter:!1,cols:[{type:"align",align:r}]};if("*"===e.envName.charAt(e.envName.length-1)){var i=e.parser;if(i.consumeSpaces(),"["===i.fetch().text){if(i.consume(),i.consumeSpaces(),r=i.fetch().text,-1==="lcr".indexOf(r))throw new n("Expected l or c or r",i.nextToken);i.consume(),i.consumeSpaces(),i.expect("]"),i.consume(),a.cols=[{type:"align",align:r}]}}var o=Gr(e.parser,a,Ur(e.envName)),s=Math.max.apply(Math,[0].concat(o.body.map((function(e){return e.length}))));return o.cols=new Array(s).fill({type:"align",align:r}),t?{type:"leftright",mode:e.mode,body:[o],left:t[0],right:t[1],rightColor:void 0}:o},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["smallmatrix"],props:{numArgs:0},handler:function(e){var t=Gr(e.parser,{arraystretch:.5},"script");return t.colSeparationType="small",t},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["subarray"],props:{numArgs:1},handler:function(e,t){var r=(Xt(t[0])?[t[0]]:Ut(t[0],"ordgroup").body).map((function(e){var t=Yt(e).text;if(-1!=="lc".indexOf(t))return{type:"align",align:t};throw new n("Unknown column alignment: "+t,e)}));if(r.length>1)throw new n("{subarray} can contain only one column");var a={cols:r,hskipBeforeAndAfter:!1,arraystretch:.5};if((a=Gr(e.parser,a,"script")).body.length>0&&a.body[0].length>1)throw new n("{subarray} can contain only one column");return a},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler:function(e){var t=Gr(e.parser,{arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:1},{type:"align",align:"l",pregap:0,postgap:0}]},Ur(e.envName));return{type:"leftright",mode:e.mode,body:[t],left:e.envName.indexOf("r")>-1?".":"\\{",right:e.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:_r,htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler:function(e){l.contains(["gather","gather*"],e.envName)&&Fr(e);var t={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",autoTag:Vr(e.envName),emptySingleRow:!0,leqno:e.parser.settings.leqno};return Gr(e.parser,t,"display")},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:_r,htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["equation","equation*"],props:{numArgs:0},handler:function(e){Fr(e);var t={autoTag:Vr(e.envName),emptySingleRow:!0,singleRow:!0,maxNumCols:1,leqno:e.parser.settings.leqno};return Gr(e.parser,t,"display")},htmlBuilder:Yr,mathmlBuilder:Wr}),Or({type:"array",names:["CD"],props:{numArgs:0},handler:function(e){return Fr(e),function(e){var t=[];for(e.gullet.beginGroup(),e.gullet.macros.set("\\cr","\\\\\\relax"),e.gullet.beginGroup();;){t.push(e.parseExpression(!1,"\\\\")),e.gullet.endGroup(),e.gullet.beginGroup();var r=e.fetch().text;if("&"!==r&&"\\\\"!==r){if("\\end"===r){0===t[t.length-1].length&&t.pop();break}throw new n("Expected \\\\ or \\cr or \\end",e.nextToken)}e.consume()}for(var a,i,o=[],s=[o],l=0;l-1);else{if(!("<>AV".indexOf(u)>-1))throw new n('Expected one of "<>AV=|." after @',h[c]);for(var d=0;d<2;d++){for(var f=!0,g=c+1;g=x.SCRIPT.id?r.text():x.DISPLAY:"text"===e&&r.size===x.DISPLAY.size?r=x.TEXT:"script"===e?r=x.SCRIPT:"scriptscript"===e&&(r=x.SCRIPTSCRIPT),r},nn=function(e,t){var r,n=rn(e.size,t.style),a=n.fracNum(),i=n.fracDen();r=t.havingStyle(a);var o=wt(e.numer,r,t);if(e.continued){var s=8.5/t.fontMetrics().ptPerEm,l=3.5/t.fontMetrics().ptPerEm;o.height=o.height0?3*c:7*c,d=t.fontMetrics().denom1):(m>0?(u=t.fontMetrics().num2,p=c):(u=t.fontMetrics().num3,p=3*c),d=t.fontMetrics().denom2),h){var w=t.fontMetrics().axisHeight;u-o.depth-(w+.5*m)0&&(t="."===(t=e)?null:t),t};ot({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler:function(e,t){var r,n=e.parser,a=t[4],i=t[5],o=lt(t[0]),s="atom"===o.type&&"open"===o.family?sn(o.text):null,l=lt(t[1]),h="atom"===l.type&&"close"===l.family?sn(l.text):null,m=Ut(t[2],"size"),c=null;r=!!m.isBlank||(c=m.value).number>0;var u="auto",p=t[3];if("ordgroup"===p.type){if(p.body.length>0){var d=Ut(p.body[0],"textord");u=on[Number(d.text)]}}else p=Ut(p,"textord"),u=on[Number(p.text)];return{type:"genfrac",mode:n.mode,numer:a,denom:i,continued:!1,hasBarLine:r,barSize:c,leftDelim:s,rightDelim:h,size:u}},htmlBuilder:nn,mathmlBuilder:an}),ot({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:function(e,t){var r=e.parser,n=(e.funcName,e.token);return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:Ut(t[0],"size").value,token:n}}}),ot({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:function(e,t){var r=e.parser,n=(e.funcName,t[0]),a=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e}(Ut(t[1],"infix").size),i=t[2],o=a.number>0;return{type:"genfrac",mode:r.mode,numer:n,denom:i,continued:!1,hasBarLine:o,barSize:a,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:nn,mathmlBuilder:an});var ln=function(e,t){var r,n,a=t.style;"supsub"===e.type?(r=e.sup?wt(e.sup,t.havingStyle(a.sup()),t):wt(e.sub,t.havingStyle(a.sub()),t),n=Ut(e.base,"horizBrace")):n=Ut(e,"horizBrace");var i,o=wt(n.base,t.havingBaseStyle(x.DISPLAY)),s=Gt(n,t);if(n.isOver?(i=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:o},{type:"kern",size:.1},{type:"elem",elem:s}]},t)).children[0].children[0].children[1].classes.push("svg-align"):(i=Ke.makeVList({positionType:"bottom",positionData:o.depth+.1+s.height,children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:o}]},t)).children[0].children[0].children[0].classes.push("svg-align"),r){var l=Ke.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t);i=n.isOver?Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:l},{type:"kern",size:.2},{type:"elem",elem:r}]},t):Ke.makeVList({positionType:"bottom",positionData:l.depth+.2+r.height+r.depth,children:[{type:"elem",elem:r},{type:"kern",size:.2},{type:"elem",elem:l}]},t)}return Ke.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t)};ot({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"horizBrace",mode:r.mode,label:n,isOver:/^\\over/.test(n),base:t[0]}},htmlBuilder:ln,mathmlBuilder:function(e,t){var r=Vt(e.label);return new Tt.MathNode(e.isOver?"mover":"munder",[Rt(e.base,t),r])}}),ot({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[1],a=Ut(t[0],"url").url;return r.settings.isTrusted({command:"\\href",url:a})?{type:"href",mode:r.mode,href:a,body:ht(n)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:function(e,t){var r=ft(e.body,t,!1);return Ke.makeAnchor(e.href,[],r,t)},mathmlBuilder:function(e,t){var r=It(e.body,t);return r instanceof zt||(r=new zt("mrow",[r])),r.setAttribute("href",e.href),r}}),ot({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=Ut(t[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:n}))return r.formatUnsupportedCmd("\\url");for(var a=[],i=0;i0&&(n=F(e.totalheight,t)-r);var a=0;e.width.number>0&&(a=F(e.width,t));var i={height:V(r+n)};a>0&&(i.width=V(a)),n>0&&(i.verticalAlign=V(-n));var o=new j(e.src,e.alt,i);return o.height=r,o.depth=n,o},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mglyph",[]);r.setAttribute("alt",e.alt);var n=F(e.height,t),a=0;if(e.totalheight.number>0&&(a=F(e.totalheight,t)-n,r.setAttribute("valign",V(-a))),r.setAttribute("height",V(n+a)),e.width.number>0){var i=F(e.width,t);r.setAttribute("width",V(i))}return r.setAttribute("src",e.src),r}}),ot({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=Ut(t[0],"size");if(r.settings.strict){var i="m"===n[1],o="mu"===a.value.unit;i?(o||r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" supports only mu units, not "+a.value.unit+" units"),"math"!==r.mode&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" works only in math mode")):o&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" doesn't support mu units")}return{type:"kern",mode:r.mode,dimension:a.value}},htmlBuilder:function(e,t){return Ke.makeGlue(e.dimension,t)},mathmlBuilder:function(e,t){var r=F(e.dimension,t);return new Tt.SpaceNode(r)}}),ot({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"lap",mode:r.mode,alignment:n.slice(5),body:a}},htmlBuilder:function(e,t){var r;"clap"===e.alignment?(r=Ke.makeSpan([],[wt(e.body,t)]),r=Ke.makeSpan(["inner"],[r],t)):r=Ke.makeSpan(["inner"],[wt(e.body,t)]);var n=Ke.makeSpan(["fix"],[]),a=Ke.makeSpan([e.alignment],[r,n],t),i=Ke.makeSpan(["strut"]);return i.style.height=V(a.height+a.depth),a.depth&&(i.style.verticalAlign=V(-a.depth)),a.children.unshift(i),a=Ke.makeSpan(["thinbox"],[a],t),Ke.makeSpan(["mord","vbox"],[a],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mpadded",[Rt(e.body,t)]);if("rlap"!==e.alignment){var n="llap"===e.alignment?"-1":"-0.5";r.setAttribute("lspace",n+"width")}return r.setAttribute("width","0px"),r}}),ot({type:"styling",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){var r=e.funcName,n=e.parser,a=n.mode;n.switchMode("math");var i="\\("===r?"\\)":"$",o=n.parseExpression(!1,i);return n.expect(i),n.switchMode(a),{type:"styling",mode:n.mode,style:"text",body:o}}}),ot({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){throw new n("Mismatched "+e.funcName)}});var mn=function(e,t){switch(t.style.size){case x.DISPLAY.size:return e.display;case x.TEXT.size:return e.text;case x.SCRIPT.size:return e.script;case x.SCRIPTSCRIPT.size:return e.scriptscript;default:return e.text}};ot({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:function(e,t){return{type:"mathchoice",mode:e.parser.mode,display:ht(t[0]),text:ht(t[1]),script:ht(t[2]),scriptscript:ht(t[3])}},htmlBuilder:function(e,t){var r=mn(e,t),n=ft(r,t,!1);return Ke.makeFragment(n)},mathmlBuilder:function(e,t){var r=mn(e,t);return It(r,t)}});var cn=function(e,t,r,n,a,i,o){e=Ke.makeSpan([],[e]);var s,h,m,c=r&&l.isCharacterBox(r);if(t){var u=wt(t,n.havingStyle(a.sup()),n);h={elem:u,kern:Math.max(n.fontMetrics().bigOpSpacing1,n.fontMetrics().bigOpSpacing3-u.depth)}}if(r){var p=wt(r,n.havingStyle(a.sub()),n);s={elem:p,kern:Math.max(n.fontMetrics().bigOpSpacing2,n.fontMetrics().bigOpSpacing4-p.height)}}if(h&&s){var d=n.fontMetrics().bigOpSpacing5+s.elem.height+s.elem.depth+s.kern+e.depth+o;m=Ke.makeVList({positionType:"bottom",positionData:d,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:V(-i)},{type:"kern",size:s.kern},{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:V(i)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}else if(s){var f=e.height-o;m=Ke.makeVList({positionType:"top",positionData:f,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:V(-i)},{type:"kern",size:s.kern},{type:"elem",elem:e}]},n)}else{if(!h)return e;var g=e.depth+o;m=Ke.makeVList({positionType:"bottom",positionData:g,children:[{type:"elem",elem:e},{type:"kern",size:h.kern},{type:"elem",elem:h.elem,marginLeft:V(i)},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}var v=[m];if(s&&0!==i&&!c){var b=Ke.makeSpan(["mspace"],[],n);b.style.marginRight=V(i),v.unshift(b)}return Ke.makeSpan(["mop","op-limits"],v,n)},un=["\\smallint"],pn=function(e,t){var r,n,a,i=!1;"supsub"===e.type?(r=e.sup,n=e.sub,a=Ut(e.base,"op"),i=!0):a=Ut(e,"op");var o,s=t.style,h=!1;if(s.size===x.DISPLAY.size&&a.symbol&&!l.contains(un,a.name)&&(h=!0),a.symbol){var m=h?"Size2-Regular":"Size1-Regular",c="";if("\\oiint"!==a.name&&"\\oiiint"!==a.name||(c=a.name.substr(1),a.name="oiint"===c?"\\iint":"\\iiint"),o=Ke.makeSymbol(a.name,m,"math",t,["mop","op-symbol",h?"large-op":"small-op"]),c.length>0){var u=o.italic,p=Ke.staticSvg(c+"Size"+(h?"2":"1"),t);o=Ke.makeVList({positionType:"individualShift",children:[{type:"elem",elem:o,shift:0},{type:"elem",elem:p,shift:h?.08:0}]},t),a.name="\\"+c,o.classes.unshift("mop"),o.italic=u}}else if(a.body){var d=ft(a.body,t,!0);1===d.length&&d[0]instanceof Z?(o=d[0]).classes[0]="mop":o=Ke.makeSpan(["mop"],d,t)}else{for(var f=[],g=1;g0){for(var s=a.body.map((function(e){var t=e.text;return"string"==typeof t?{type:"textord",mode:e.mode,text:t}:e})),l=ft(s,t.withFont("mathrm"),!0),h=0;h=0?s.setAttribute("height",V(a)):(s.setAttribute("height",V(a)),s.setAttribute("depth",V(-a))),s.setAttribute("voffset",V(a)),s}});var yn=["\\tiny","\\sixptsize","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"];ot({type:"sizing",names:yn,props:{numArgs:0,allowedInText:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!1,r);return{type:"sizing",mode:a.mode,size:yn.indexOf(n)+1,body:i}},htmlBuilder:function(e,t){var r=t.havingSize(e.size);return bn(e.body,r,t)},mathmlBuilder:function(e,t){var r=t.havingSize(e.size),n=Nt(e.body,r),a=new Tt.MathNode("mstyle",n);return a.setAttribute("mathsize",V(r.sizeMultiplier)),a}}),ot({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=!1,i=!1,o=r[0]&&Ut(r[0],"ordgroup");if(o)for(var s="",l=0;lr.height+r.depth+i&&(i=(i+c-r.height-r.depth)/2);var u=l.height-r.height-i-h;r.style.paddingLeft=V(m);var p=Ke.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r,wrapperClasses:["svg-align"]},{type:"kern",size:-(r.height+u)},{type:"elem",elem:l},{type:"kern",size:h}]},t);if(e.index){var d=t.havingStyle(x.SCRIPTSCRIPT),f=wt(e.index,d,t),g=.6*(p.height-p.depth),v=Ke.makeVList({positionType:"shift",positionData:-g,children:[{type:"elem",elem:f}]},t),b=Ke.makeSpan(["root"],[v]);return Ke.makeSpan(["mord","sqrt"],[b,p],t)}return Ke.makeSpan(["mord","sqrt"],[p],t)},mathmlBuilder:function(e,t){var r=e.body,n=e.index;return n?new Tt.MathNode("mroot",[Rt(r,t),Rt(n,t)]):new Tt.MathNode("msqrt",[Rt(r,t)])}});var xn={display:x.DISPLAY,text:x.TEXT,script:x.SCRIPT,scriptscript:x.SCRIPTSCRIPT};ot({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!0,r),o=n.slice(1,n.length-5);return{type:"styling",mode:a.mode,style:o,body:i}},htmlBuilder:function(e,t){var r=xn[e.style],n=t.havingStyle(r).withFont("");return bn(e.body,n,t)},mathmlBuilder:function(e,t){var r=xn[e.style],n=t.havingStyle(r),a=Nt(e.body,n),i=new Tt.MathNode("mstyle",a),o={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]}[e.style];return i.setAttribute("scriptlevel",o[0]),i.setAttribute("displaystyle",o[1]),i}});var wn=function(e,t){var r=e.base;return r?"op"===r.type?r.limits&&(t.style.size===x.DISPLAY.size||r.alwaysHandleSupSub)?pn:null:"operatorname"===r.type?r.alwaysHandleSupSub&&(t.style.size===x.DISPLAY.size||r.limits)?vn:null:"accent"===r.type?l.isCharacterBox(r.base)?Wt:null:"horizBrace"===r.type&&!e.sub===r.isOver?ln:null:null};st({type:"supsub",htmlBuilder:function(e,t){var r=wn(e,t);if(r)return r(e,t);var n,a,i,o=e.base,s=e.sup,h=e.sub,m=wt(o,t),c=t.fontMetrics(),u=0,p=0,d=o&&l.isCharacterBox(o);if(s){var f=t.havingStyle(t.style.sup());n=wt(s,f,t),d||(u=m.height-f.fontMetrics().supDrop*f.sizeMultiplier/t.sizeMultiplier)}if(h){var g=t.havingStyle(t.style.sub());a=wt(h,g,t),d||(p=m.depth+g.fontMetrics().subDrop*g.sizeMultiplier/t.sizeMultiplier)}i=t.style===x.DISPLAY?c.sup1:t.style.cramped?c.sup3:c.sup2;var v,b=t.sizeMultiplier,y=V(.5/c.ptPerEm/b),w=null;if(a){var k=e.base&&"op"===e.base.type&&e.base.name&&("\\oiint"===e.base.name||"\\oiiint"===e.base.name);(m instanceof Z||k)&&(w=V(-m.italic))}if(n&&a){u=Math.max(u,i,n.depth+.25*c.xHeight),p=Math.max(p,c.sub2);var S=4*c.defaultRuleThickness;if(u-n.depth-(a.height-p)0&&(u+=M,p-=M)}var z=[{type:"elem",elem:a,shift:p,marginRight:y,marginLeft:w},{type:"elem",elem:n,shift:-u,marginRight:y}];v=Ke.makeVList({positionType:"individualShift",children:z},t)}else if(a){p=Math.max(p,c.sub1,a.height-.8*c.xHeight);var A=[{type:"elem",elem:a,marginLeft:w,marginRight:y}];v=Ke.makeVList({positionType:"shift",positionData:p,children:A},t)}else{if(!n)throw new Error("supsub must have either sup or sub.");u=Math.max(u,i,n.depth+.25*c.xHeight),v=Ke.makeVList({positionType:"shift",positionData:-u,children:[{type:"elem",elem:n,marginRight:y}]},t)}var T=yt(m,"right")||"mord";return Ke.makeSpan([T],[m,Ke.makeSpan(["msupsub"],[v])],t)},mathmlBuilder:function(e,t){var r,n=!1;e.base&&"horizBrace"===e.base.type&&!!e.sup===e.base.isOver&&(n=!0,r=e.base.isOver),!e.base||"op"!==e.base.type&&"operatorname"!==e.base.type||(e.base.parentIsSupSub=!0);var a,i=[Rt(e.base,t)];if(e.sub&&i.push(Rt(e.sub,t)),e.sup&&i.push(Rt(e.sup,t)),n)a=r?"mover":"munder";else if(e.sub)if(e.sup){var o=e.base;a=o&&"op"===o.type&&o.limits&&t.style===x.DISPLAY||o&&"operatorname"===o.type&&o.alwaysHandleSupSub&&(t.style===x.DISPLAY||o.limits)?"munderover":"msubsup"}else{var s=e.base;a=s&&"op"===s.type&&s.limits&&(t.style===x.DISPLAY||s.alwaysHandleSupSub)||s&&"operatorname"===s.type&&s.alwaysHandleSupSub&&(s.limits||t.style===x.DISPLAY)?"munder":"msub"}else{var l=e.base;a=l&&"op"===l.type&&l.limits&&(t.style===x.DISPLAY||l.alwaysHandleSupSub)||l&&"operatorname"===l.type&&l.alwaysHandleSupSub&&(l.limits||t.style===x.DISPLAY)?"mover":"msup"}return new Tt.MathNode(a,i)}}),st({type:"atom",htmlBuilder:function(e,t){return Ke.mathsym(e.text,e.mode,t,["m"+e.family])},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mo",[Bt(e.text,e.mode)]);if("bin"===e.family){var n=qt(e,t);"bold-italic"===n&&r.setAttribute("mathvariant",n)}else"punct"===e.family?r.setAttribute("separator","true"):"open"!==e.family&&"close"!==e.family||r.setAttribute("stretchy","false");return r}});var kn={mi:"italic",mn:"normal",mtext:"normal"};st({type:"mathord",htmlBuilder:function(e,t){return Ke.makeOrd(e,t,"mathord")},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mi",[Bt(e.text,e.mode,t)]),n=qt(e,t)||"italic";return n!==kn[r.type]&&r.setAttribute("mathvariant",n),r}}),st({type:"textord",htmlBuilder:function(e,t){return Ke.makeOrd(e,t,"textord")},mathmlBuilder:function(e,t){var r,n=Bt(e.text,e.mode,t),a=qt(e,t)||"normal";return r="text"===e.mode?new Tt.MathNode("mtext",[n]):/[0-9]/.test(e.text)?new Tt.MathNode("mn",[n]):"\\prime"===e.text?new Tt.MathNode("mo",[n]):new Tt.MathNode("mi",[n]),a!==kn[r.type]&&r.setAttribute("mathvariant",a),r}});var Sn={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},Mn={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};st({type:"spacing",htmlBuilder:function(e,t){if(Mn.hasOwnProperty(e.text)){var r=Mn[e.text].className||"";if("text"===e.mode){var a=Ke.makeOrd(e,t,"textord");return a.classes.push(r),a}return Ke.makeSpan(["mspace",r],[Ke.mathsym(e.text,e.mode,t)],t)}if(Sn.hasOwnProperty(e.text))return Ke.makeSpan(["mspace",Sn[e.text]],[],t);throw new n('Unknown type of space "'+e.text+'"')},mathmlBuilder:function(e,t){if(!Mn.hasOwnProperty(e.text)){if(Sn.hasOwnProperty(e.text))return new Tt.MathNode("mspace");throw new n('Unknown type of space "'+e.text+'"')}return new Tt.MathNode("mtext",[new Tt.TextNode("\xa0")])}});var zn=function(){var e=new Tt.MathNode("mtd",[]);return e.setAttribute("width","50%"),e};st({type:"tag",mathmlBuilder:function(e,t){var r=new Tt.MathNode("mtable",[new Tt.MathNode("mtr",[zn(),new Tt.MathNode("mtd",[It(e.body,t)]),zn(),new Tt.MathNode("mtd",[It(e.tag,t)])])]);return r.setAttribute("width","100%"),r}});var An={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},Tn={"\\textbf":"textbf","\\textmd":"textmd"},Bn={"\\textit":"textit","\\textup":"textup"},Cn=function(e,t){var r=e.font;return r?An[r]?t.withTextFontFamily(An[r]):Tn[r]?t.withTextFontWeight(Tn[r]):t.withTextFontShape(Bn[r]):t};ot({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"text",mode:r.mode,body:ht(a),font:n}},htmlBuilder:function(e,t){var r=Cn(e,t),n=ft(e.body,r,!0);return Ke.makeSpan(["mord","text"],n,r)},mathmlBuilder:function(e,t){var r=Cn(e,t);return It(e.body,r)}}),ot({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){return{type:"underline",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=wt(e.body,t),n=Ke.makeLineSpan("underline-line",t),a=t.fontMetrics().defaultRuleThickness,i=Ke.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:a},{type:"elem",elem:n},{type:"kern",size:3*a},{type:"elem",elem:r}]},t);return Ke.makeSpan(["mord","underline"],[i],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode("mo",[new Tt.TextNode("\u203e")]);r.setAttribute("stretchy","true");var n=new Tt.MathNode("munder",[Rt(e.body,t),r]);return n.setAttribute("accentunder","true"),n}}),ot({type:"vcenter",names:["\\vcenter"],props:{numArgs:1,argTypes:["original"],allowedInText:!1},handler:function(e,t){return{type:"vcenter",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=wt(e.body,t),n=t.fontMetrics().axisHeight,a=.5*(r.height-n-(r.depth+n));return Ke.makeVList({positionType:"shift",positionData:a,children:[{type:"elem",elem:r}]},t)},mathmlBuilder:function(e,t){return new Tt.MathNode("mpadded",[Rt(e.body,t)],["vcenter"])}}),ot({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler:function(e,t,r){throw new n("\\verb ended by end of line instead of matching delimiter")},htmlBuilder:function(e,t){for(var r=qn(e),n=[],a=t.havingStyle(t.style.text()),i=0;i0;)this.endGroup()},t.has=function(e){return this.current.hasOwnProperty(e)||this.builtins.hasOwnProperty(e)},t.get=function(e){return this.current.hasOwnProperty(e)?this.current[e]:this.builtins[e]},t.set=function(e,t,r){if(void 0===r&&(r=!1),r){for(var n=0;n0&&(this.undefStack[this.undefStack.length-1][e]=t)}else{var a=this.undefStack[this.undefStack.length-1];a&&!a.hasOwnProperty(e)&&(a[e]=this.current[e])}null==t?delete this.current[e]:this.current[e]=t},e}(),Hn=Hr;Er("\\noexpand",(function(e){var t=e.popToken();return e.isExpandable(t.text)&&(t.noexpand=!0,t.treatAsRelax=!0),{tokens:[t],numArgs:0}})),Er("\\expandafter",(function(e){var t=e.popToken();return e.expandOnce(!0),{tokens:[t],numArgs:0}})),Er("\\@firstoftwo",(function(e){return{tokens:e.consumeArgs(2)[0],numArgs:0}})),Er("\\@secondoftwo",(function(e){return{tokens:e.consumeArgs(2)[1],numArgs:0}})),Er("\\@ifnextchar",(function(e){var t=e.consumeArgs(3);e.consumeSpaces();var r=e.future();return 1===t[0].length&&t[0][0].text===r.text?{tokens:t[1],numArgs:0}:{tokens:t[2],numArgs:0}})),Er("\\@ifstar","\\@ifnextchar *{\\@firstoftwo{#1}}"),Er("\\TextOrMath",(function(e){var t=e.consumeArgs(2);return"text"===e.mode?{tokens:t[0],numArgs:0}:{tokens:t[1],numArgs:0}}));var En={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,A:10,b:11,B:11,c:12,C:12,d:13,D:13,e:14,E:14,f:15,F:15};Er("\\char",(function(e){var t,r=e.popToken(),a="";if("'"===r.text)t=8,r=e.popToken();else if('"'===r.text)t=16,r=e.popToken();else if("`"===r.text)if("\\"===(r=e.popToken()).text[0])a=r.text.charCodeAt(1);else{if("EOF"===r.text)throw new n("\\char` missing argument");a=r.text.charCodeAt(0)}else t=10;if(t){if(null==(a=En[r.text])||a>=t)throw new n("Invalid base-"+t+" digit "+r.text);for(var i;null!=(i=En[e.future().text])&&i":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};Er("\\dots",(function(e){var t="\\dotso",r=e.expandAfterFuture().text;return r in Dn?t=Dn[r]:("\\not"===r.substr(0,4)||r in ae.math&&l.contains(["bin","rel"],ae.math[r].group))&&(t="\\dotsb"),t}));var Pn={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};Er("\\dotso",(function(e){return e.future().text in Pn?"\\ldots\\,":"\\ldots"})),Er("\\dotsc",(function(e){var t=e.future().text;return t in Pn&&","!==t?"\\ldots\\,":"\\ldots"})),Er("\\cdots",(function(e){return e.future().text in Pn?"\\@cdots\\,":"\\@cdots"})),Er("\\dotsb","\\cdots"),Er("\\dotsm","\\cdots"),Er("\\dotsi","\\!\\cdots"),Er("\\dotsx","\\ldots\\,"),Er("\\DOTSI","\\relax"),Er("\\DOTSB","\\relax"),Er("\\DOTSX","\\relax"),Er("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),Er("\\,","\\tmspace+{3mu}{.1667em}"),Er("\\thinspace","\\,"),Er("\\>","\\mskip{4mu}"),Er("\\:","\\tmspace+{4mu}{.2222em}"),Er("\\medspace","\\:"),Er("\\;","\\tmspace+{5mu}{.2777em}"),Er("\\thickspace","\\;"),Er("\\!","\\tmspace-{3mu}{.1667em}"),Er("\\negthinspace","\\!"),Er("\\negmedspace","\\tmspace-{4mu}{.2222em}"),Er("\\negthickspace","\\tmspace-{5mu}{.277em}"),Er("\\enspace","\\kern.5em "),Er("\\enskip","\\hskip.5em\\relax"),Er("\\quad","\\hskip1em\\relax"),Er("\\qquad","\\hskip2em\\relax"),Er("\\tag","\\@ifstar\\tag@literal\\tag@paren"),Er("\\tag@paren","\\tag@literal{({#1})}"),Er("\\tag@literal",(function(e){if(e.macros.get("\\df@tag"))throw new n("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"})),Er("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),Er("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),Er("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),Er("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),Er("\\pmb","\\html@mathml{\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}{\\mathbf{#1}}"),Er("\\newline","\\\\\\relax"),Er("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}");var Fn=V(T["Main-Regular"]["T".charCodeAt(0)][1]-.7*T["Main-Regular"]["A".charCodeAt(0)][1]);Er("\\LaTeX","\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{"+Fn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),Er("\\KaTeX","\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{"+Fn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),Er("\\hspace","\\@ifstar\\@hspacer\\@hspace"),Er("\\@hspace","\\hskip #1\\relax"),Er("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),Er("\\ordinarycolon",":"),Er("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}"),Er("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'),Er("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'),Er("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'),Er("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'),Er("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'),Er("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'),Er("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'),Er("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'),Er("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'),Er("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'),Er("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'),Er("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'),Er("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'),Er("\u2237","\\dblcolon"),Er("\u2239","\\eqcolon"),Er("\u2254","\\coloneqq"),Er("\u2255","\\eqqcolon"),Er("\u2a74","\\Coloneqq"),Er("\\ratio","\\vcentcolon"),Er("\\coloncolon","\\dblcolon"),Er("\\colonequals","\\coloneqq"),Er("\\coloncolonequals","\\Coloneqq"),Er("\\equalscolon","\\eqqcolon"),Er("\\equalscoloncolon","\\Eqqcolon"),Er("\\colonminus","\\coloneq"),Er("\\coloncolonminus","\\Coloneq"),Er("\\minuscolon","\\eqcolon"),Er("\\minuscoloncolon","\\Eqcolon"),Er("\\coloncolonapprox","\\Colonapprox"),Er("\\coloncolonsim","\\Colonsim"),Er("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Er("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Er("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Er("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Er("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"),Er("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),Er("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),Er("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),Er("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),Er("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}"),Er("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}"),Er("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),Er("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),Er("\\gvertneqq","\\html@mathml{\\@gvertneqq}{\u2269}"),Er("\\lvertneqq","\\html@mathml{\\@lvertneqq}{\u2268}"),Er("\\ngeqq","\\html@mathml{\\@ngeqq}{\u2271}"),Er("\\ngeqslant","\\html@mathml{\\@ngeqslant}{\u2271}"),Er("\\nleqq","\\html@mathml{\\@nleqq}{\u2270}"),Er("\\nleqslant","\\html@mathml{\\@nleqslant}{\u2270}"),Er("\\nshortmid","\\html@mathml{\\@nshortmid}{\u2224}"),Er("\\nshortparallel","\\html@mathml{\\@nshortparallel}{\u2226}"),Er("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{\u2288}"),Er("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{\u2289}"),Er("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{\u228a}"),Er("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{\u2acb}"),Er("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{\u228b}"),Er("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{\u2acc}"),Er("\\imath","\\html@mathml{\\@imath}{\u0131}"),Er("\\jmath","\\html@mathml{\\@jmath}{\u0237}"),Er("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"),Er("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"),Er("\u27e6","\\llbracket"),Er("\u27e7","\\rrbracket"),Er("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"),Er("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"),Er("\u2983","\\lBrace"),Er("\u2984","\\rBrace"),Er("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"),Er("\u29b5","\\minuso"),Er("\\darr","\\downarrow"),Er("\\dArr","\\Downarrow"),Er("\\Darr","\\Downarrow"),Er("\\lang","\\langle"),Er("\\rang","\\rangle"),Er("\\uarr","\\uparrow"),Er("\\uArr","\\Uparrow"),Er("\\Uarr","\\Uparrow"),Er("\\N","\\mathbb{N}"),Er("\\R","\\mathbb{R}"),Er("\\Z","\\mathbb{Z}"),Er("\\alef","\\aleph"),Er("\\alefsym","\\aleph"),Er("\\Alpha","\\mathrm{A}"),Er("\\Beta","\\mathrm{B}"),Er("\\bull","\\bullet"),Er("\\Chi","\\mathrm{X}"),Er("\\clubs","\\clubsuit"),Er("\\cnums","\\mathbb{C}"),Er("\\Complex","\\mathbb{C}"),Er("\\Dagger","\\ddagger"),Er("\\diamonds","\\diamondsuit"),Er("\\empty","\\emptyset"),Er("\\Epsilon","\\mathrm{E}"),Er("\\Eta","\\mathrm{H}"),Er("\\exist","\\exists"),Er("\\harr","\\leftrightarrow"),Er("\\hArr","\\Leftrightarrow"),Er("\\Harr","\\Leftrightarrow"),Er("\\hearts","\\heartsuit"),Er("\\image","\\Im"),Er("\\infin","\\infty"),Er("\\Iota","\\mathrm{I}"),Er("\\isin","\\in"),Er("\\Kappa","\\mathrm{K}"),Er("\\larr","\\leftarrow"),Er("\\lArr","\\Leftarrow"),Er("\\Larr","\\Leftarrow"),Er("\\lrarr","\\leftrightarrow"),Er("\\lrArr","\\Leftrightarrow"),Er("\\Lrarr","\\Leftrightarrow"),Er("\\Mu","\\mathrm{M}"),Er("\\natnums","\\mathbb{N}"),Er("\\Nu","\\mathrm{N}"),Er("\\Omicron","\\mathrm{O}"),Er("\\plusmn","\\pm"),Er("\\rarr","\\rightarrow"),Er("\\rArr","\\Rightarrow"),Er("\\Rarr","\\Rightarrow"),Er("\\real","\\Re"),Er("\\reals","\\mathbb{R}"),Er("\\Reals","\\mathbb{R}"),Er("\\Rho","\\mathrm{P}"),Er("\\sdot","\\cdot"),Er("\\sect","\\S"),Er("\\spades","\\spadesuit"),Er("\\sub","\\subset"),Er("\\sube","\\subseteq"),Er("\\supe","\\supseteq"),Er("\\Tau","\\mathrm{T}"),Er("\\thetasym","\\vartheta"),Er("\\weierp","\\wp"),Er("\\Zeta","\\mathrm{Z}"),Er("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),Er("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),Er("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),Er("\\bra","\\mathinner{\\langle{#1}|}"),Er("\\ket","\\mathinner{|{#1}\\rangle}"),Er("\\braket","\\mathinner{\\langle{#1}\\rangle}"),Er("\\Bra","\\left\\langle#1\\right|"),Er("\\Ket","\\left|#1\\right\\rangle");var Vn=function(e){return function(t){var r=t.consumeArg().tokens,n=t.consumeArg().tokens,a=t.consumeArg().tokens,i=t.consumeArg().tokens,o=t.macros.get("|"),s=t.macros.get("\\|");t.macros.beginGroup();var l=function(t){return function(r){e&&(r.macros.set("|",o),a.length&&r.macros.set("\\|",s));var i=t;!t&&a.length&&("|"===r.future().text&&(r.popToken(),i=!0));return{tokens:i?a:n,numArgs:0}}};t.macros.set("|",l(!1)),a.length&&t.macros.set("\\|",l(!0));var h=t.consumeArg().tokens,m=t.expandTokens([].concat(i,h,r));return t.macros.endGroup(),{tokens:m.reverse(),numArgs:0}}};Er("\\bra@ket",Vn(!1)),Er("\\bra@set",Vn(!0)),Er("\\Braket","\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"),Er("\\Set","\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"),Er("\\set","\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"),Er("\\angln","{\\angl n}"),Er("\\blue","\\textcolor{##6495ed}{#1}"),Er("\\orange","\\textcolor{##ffa500}{#1}"),Er("\\pink","\\textcolor{##ff00af}{#1}"),Er("\\red","\\textcolor{##df0030}{#1}"),Er("\\green","\\textcolor{##28ae7b}{#1}"),Er("\\gray","\\textcolor{gray}{#1}"),Er("\\purple","\\textcolor{##9d38bd}{#1}"),Er("\\blueA","\\textcolor{##ccfaff}{#1}"),Er("\\blueB","\\textcolor{##80f6ff}{#1}"),Er("\\blueC","\\textcolor{##63d9ea}{#1}"),Er("\\blueD","\\textcolor{##11accd}{#1}"),Er("\\blueE","\\textcolor{##0c7f99}{#1}"),Er("\\tealA","\\textcolor{##94fff5}{#1}"),Er("\\tealB","\\textcolor{##26edd5}{#1}"),Er("\\tealC","\\textcolor{##01d1c1}{#1}"),Er("\\tealD","\\textcolor{##01a995}{#1}"),Er("\\tealE","\\textcolor{##208170}{#1}"),Er("\\greenA","\\textcolor{##b6ffb0}{#1}"),Er("\\greenB","\\textcolor{##8af281}{#1}"),Er("\\greenC","\\textcolor{##74cf70}{#1}"),Er("\\greenD","\\textcolor{##1fab54}{#1}"),Er("\\greenE","\\textcolor{##0d923f}{#1}"),Er("\\goldA","\\textcolor{##ffd0a9}{#1}"),Er("\\goldB","\\textcolor{##ffbb71}{#1}"),Er("\\goldC","\\textcolor{##ff9c39}{#1}"),Er("\\goldD","\\textcolor{##e07d10}{#1}"),Er("\\goldE","\\textcolor{##a75a05}{#1}"),Er("\\redA","\\textcolor{##fca9a9}{#1}"),Er("\\redB","\\textcolor{##ff8482}{#1}"),Er("\\redC","\\textcolor{##f9685d}{#1}"),Er("\\redD","\\textcolor{##e84d39}{#1}"),Er("\\redE","\\textcolor{##bc2612}{#1}"),Er("\\maroonA","\\textcolor{##ffbde0}{#1}"),Er("\\maroonB","\\textcolor{##ff92c6}{#1}"),Er("\\maroonC","\\textcolor{##ed5fa6}{#1}"),Er("\\maroonD","\\textcolor{##ca337c}{#1}"),Er("\\maroonE","\\textcolor{##9e034e}{#1}"),Er("\\purpleA","\\textcolor{##ddd7ff}{#1}"),Er("\\purpleB","\\textcolor{##c6b9fc}{#1}"),Er("\\purpleC","\\textcolor{##aa87ff}{#1}"),Er("\\purpleD","\\textcolor{##7854ab}{#1}"),Er("\\purpleE","\\textcolor{##543b78}{#1}"),Er("\\mintA","\\textcolor{##f5f9e8}{#1}"),Er("\\mintB","\\textcolor{##edf2df}{#1}"),Er("\\mintC","\\textcolor{##e0e5cc}{#1}"),Er("\\grayA","\\textcolor{##f6f7f7}{#1}"),Er("\\grayB","\\textcolor{##f0f1f2}{#1}"),Er("\\grayC","\\textcolor{##e3e5e6}{#1}"),Er("\\grayD","\\textcolor{##d6d8da}{#1}"),Er("\\grayE","\\textcolor{##babec2}{#1}"),Er("\\grayF","\\textcolor{##888d93}{#1}"),Er("\\grayG","\\textcolor{##626569}{#1}"),Er("\\grayH","\\textcolor{##3b3e40}{#1}"),Er("\\grayI","\\textcolor{##21242c}{#1}"),Er("\\kaBlue","\\textcolor{##314453}{#1}"),Er("\\kaGreen","\\textcolor{##71B307}{#1}");var Gn={"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0},Un=function(){function e(e,t,r){this.settings=void 0,this.expansionCount=void 0,this.lexer=void 0,this.macros=void 0,this.stack=void 0,this.mode=void 0,this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new On(Hn,t.macros),this.mode=r,this.stack=[]}var t=e.prototype;return t.feed=function(e){this.lexer=new Rn(e,this.settings)},t.switchMode=function(e){this.mode=e},t.beginGroup=function(){this.macros.beginGroup()},t.endGroup=function(){this.macros.endGroup()},t.endGroups=function(){this.macros.endGroups()},t.future=function(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]},t.popToken=function(){return this.future(),this.stack.pop()},t.pushToken=function(e){this.stack.push(e)},t.pushTokens=function(e){var t;(t=this.stack).push.apply(t,e)},t.scanArgument=function(e){var t,r,n;if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;t=this.popToken();var a=this.consumeArg(["]"]);n=a.tokens,r=a.end}else{var i=this.consumeArg();n=i.tokens,t=i.start,r=i.end}return this.pushToken(new Dr("EOF",r.loc)),this.pushTokens(n),t.range(r,"")},t.consumeSpaces=function(){for(;;){if(" "!==this.future().text)break;this.stack.pop()}},t.consumeArg=function(e){var t=[],r=e&&e.length>0;r||this.consumeSpaces();var a,i=this.future(),o=0,s=0;do{if(a=this.popToken(),t.push(a),"{"===a.text)++o;else if("}"===a.text){if(-1===--o)throw new n("Extra }",a)}else if("EOF"===a.text)throw new n("Unexpected end of input in a macro argument, expected '"+(e&&r?e[s]:"}")+"'",a);if(e&&r)if((0===o||1===o&&"{"===e[s])&&a.text===e[s]){if(++s===e.length){t.splice(-s,s);break}}else s=0}while(0!==o||r);return"{"===i.text&&"}"===t[t.length-1].text&&(t.pop(),t.shift()),t.reverse(),{tokens:t,start:i,end:a}},t.consumeArgs=function(e,t){if(t){if(t.length!==e+1)throw new n("The length of delimiters doesn't match the number of args!");for(var r=t[0],a=0;athis.settings.maxExpand)throw new n("Too many expansions: infinite loop or need to increase maxExpand setting");var i=a.tokens,o=this.consumeArgs(a.numArgs,a.delimiters);if(a.numArgs)for(var s=(i=i.slice()).length-1;s>=0;--s){var l=i[s];if("#"===l.text){if(0===s)throw new n("Incomplete placeholder at end of macro body",l);if("#"===(l=i[--s]).text)i.splice(s+1,1);else{if(!/^[1-9]$/.test(l.text))throw new n("Not a valid argument number",l);var h;(h=i).splice.apply(h,[s,2].concat(o[+l.text-1]))}}}return this.pushTokens(i),i},t.expandAfterFuture=function(){return this.expandOnce(),this.future()},t.expandNextToken=function(){for(;;){var e=this.expandOnce();if(e instanceof Dr)return e.treatAsRelax&&(e.text="\\relax"),this.stack.pop()}throw new Error},t.expandMacro=function(e){return this.macros.has(e)?this.expandTokens([new Dr(e)]):void 0},t.expandTokens=function(e){var t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;){var n=this.expandOnce(!0);n instanceof Dr&&(n.treatAsRelax&&(n.noexpand=!1,n.treatAsRelax=!1),t.push(this.stack.pop()))}return t},t.expandMacroAsText=function(e){var t=this.expandMacro(e);return t?t.map((function(e){return e.text})).join(""):t},t._getExpansion=function(e){var t=this.macros.get(e);if(null==t)return t;if(1===e.length){var r=this.lexer.catcodes[e];if(null!=r&&13!==r)return}var n="function"==typeof t?t(this):t;if("string"==typeof n){var a=0;if(-1!==n.indexOf("#"))for(var i=n.replace(/##/g,"");-1!==i.indexOf("#"+(a+1));)++a;for(var o=new Rn(n,this.settings),s=[],l=o.lex();"EOF"!==l.text;)s.push(l),l=o.lex();return s.reverse(),{tokens:s,numArgs:a}}return n},t.isDefined=function(e){return this.macros.has(e)||Nn.hasOwnProperty(e)||ae.math.hasOwnProperty(e)||ae.text.hasOwnProperty(e)||Gn.hasOwnProperty(e)},t.isExpandable=function(e){var t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:Nn.hasOwnProperty(e)&&!Nn[e].primitive},e}(),Yn=/^[\u208a\u208b\u208c\u208d\u208e\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u1d66\u1d67\u1d68\u1d69\u1d6a]/,Xn=Object.freeze({"\u208a":"+","\u208b":"-","\u208c":"=","\u208d":"(","\u208e":")","\u2080":"0","\u2081":"1","\u2082":"2","\u2083":"3","\u2084":"4","\u2085":"5","\u2086":"6","\u2087":"7","\u2088":"8","\u2089":"9","\u2090":"a","\u2091":"e","\u2095":"h","\u1d62":"i","\u2c7c":"j","\u2096":"k","\u2097":"l","\u2098":"m","\u2099":"n","\u2092":"o","\u209a":"p","\u1d63":"r","\u209b":"s","\u209c":"t","\u1d64":"u","\u1d65":"v","\u2093":"x","\u1d66":"\u03b2","\u1d67":"\u03b3","\u1d68":"\u03c1","\u1d69":"\u03d5","\u1d6a":"\u03c7","\u207a":"+","\u207b":"-","\u207c":"=","\u207d":"(","\u207e":")","\u2070":"0","\xb9":"1","\xb2":"2","\xb3":"3","\u2074":"4","\u2075":"5","\u2076":"6","\u2077":"7","\u2078":"8","\u2079":"9","\u1d2c":"A","\u1d2e":"B","\u1d30":"D","\u1d31":"E","\u1d33":"G","\u1d34":"H","\u1d35":"I","\u1d36":"J","\u1d37":"K","\u1d38":"L","\u1d39":"M","\u1d3a":"N","\u1d3c":"O","\u1d3e":"P","\u1d3f":"R","\u1d40":"T","\u1d41":"U","\u2c7d":"V","\u1d42":"W","\u1d43":"a","\u1d47":"b","\u1d9c":"c","\u1d48":"d","\u1d49":"e","\u1da0":"f","\u1d4d":"g","\u02b0":"h","\u2071":"i","\u02b2":"j","\u1d4f":"k","\u02e1":"l","\u1d50":"m","\u207f":"n","\u1d52":"o","\u1d56":"p","\u02b3":"r","\u02e2":"s","\u1d57":"t","\u1d58":"u","\u1d5b":"v","\u02b7":"w","\u02e3":"x","\u02b8":"y","\u1dbb":"z","\u1d5d":"\u03b2","\u1d5e":"\u03b3","\u1d5f":"\u03b4","\u1d60":"\u03d5","\u1d61":"\u03c7","\u1dbf":"\u03b8"}),Wn={"\u0301":{text:"\\'",math:"\\acute"},"\u0300":{text:"\\`",math:"\\grave"},"\u0308":{text:'\\"',math:"\\ddot"},"\u0303":{text:"\\~",math:"\\tilde"},"\u0304":{text:"\\=",math:"\\bar"},"\u0306":{text:"\\u",math:"\\breve"},"\u030c":{text:"\\v",math:"\\check"},"\u0302":{text:"\\^",math:"\\hat"},"\u0307":{text:"\\.",math:"\\dot"},"\u030a":{text:"\\r",math:"\\mathring"},"\u030b":{text:"\\H"},"\u0327":{text:"\\c"}},_n={"\xe1":"a\u0301","\xe0":"a\u0300","\xe4":"a\u0308","\u01df":"a\u0308\u0304","\xe3":"a\u0303","\u0101":"a\u0304","\u0103":"a\u0306","\u1eaf":"a\u0306\u0301","\u1eb1":"a\u0306\u0300","\u1eb5":"a\u0306\u0303","\u01ce":"a\u030c","\xe2":"a\u0302","\u1ea5":"a\u0302\u0301","\u1ea7":"a\u0302\u0300","\u1eab":"a\u0302\u0303","\u0227":"a\u0307","\u01e1":"a\u0307\u0304","\xe5":"a\u030a","\u01fb":"a\u030a\u0301","\u1e03":"b\u0307","\u0107":"c\u0301","\u1e09":"c\u0327\u0301","\u010d":"c\u030c","\u0109":"c\u0302","\u010b":"c\u0307","\xe7":"c\u0327","\u010f":"d\u030c","\u1e0b":"d\u0307","\u1e11":"d\u0327","\xe9":"e\u0301","\xe8":"e\u0300","\xeb":"e\u0308","\u1ebd":"e\u0303","\u0113":"e\u0304","\u1e17":"e\u0304\u0301","\u1e15":"e\u0304\u0300","\u0115":"e\u0306","\u1e1d":"e\u0327\u0306","\u011b":"e\u030c","\xea":"e\u0302","\u1ebf":"e\u0302\u0301","\u1ec1":"e\u0302\u0300","\u1ec5":"e\u0302\u0303","\u0117":"e\u0307","\u0229":"e\u0327","\u1e1f":"f\u0307","\u01f5":"g\u0301","\u1e21":"g\u0304","\u011f":"g\u0306","\u01e7":"g\u030c","\u011d":"g\u0302","\u0121":"g\u0307","\u0123":"g\u0327","\u1e27":"h\u0308","\u021f":"h\u030c","\u0125":"h\u0302","\u1e23":"h\u0307","\u1e29":"h\u0327","\xed":"i\u0301","\xec":"i\u0300","\xef":"i\u0308","\u1e2f":"i\u0308\u0301","\u0129":"i\u0303","\u012b":"i\u0304","\u012d":"i\u0306","\u01d0":"i\u030c","\xee":"i\u0302","\u01f0":"j\u030c","\u0135":"j\u0302","\u1e31":"k\u0301","\u01e9":"k\u030c","\u0137":"k\u0327","\u013a":"l\u0301","\u013e":"l\u030c","\u013c":"l\u0327","\u1e3f":"m\u0301","\u1e41":"m\u0307","\u0144":"n\u0301","\u01f9":"n\u0300","\xf1":"n\u0303","\u0148":"n\u030c","\u1e45":"n\u0307","\u0146":"n\u0327","\xf3":"o\u0301","\xf2":"o\u0300","\xf6":"o\u0308","\u022b":"o\u0308\u0304","\xf5":"o\u0303","\u1e4d":"o\u0303\u0301","\u1e4f":"o\u0303\u0308","\u022d":"o\u0303\u0304","\u014d":"o\u0304","\u1e53":"o\u0304\u0301","\u1e51":"o\u0304\u0300","\u014f":"o\u0306","\u01d2":"o\u030c","\xf4":"o\u0302","\u1ed1":"o\u0302\u0301","\u1ed3":"o\u0302\u0300","\u1ed7":"o\u0302\u0303","\u022f":"o\u0307","\u0231":"o\u0307\u0304","\u0151":"o\u030b","\u1e55":"p\u0301","\u1e57":"p\u0307","\u0155":"r\u0301","\u0159":"r\u030c","\u1e59":"r\u0307","\u0157":"r\u0327","\u015b":"s\u0301","\u1e65":"s\u0301\u0307","\u0161":"s\u030c","\u1e67":"s\u030c\u0307","\u015d":"s\u0302","\u1e61":"s\u0307","\u015f":"s\u0327","\u1e97":"t\u0308","\u0165":"t\u030c","\u1e6b":"t\u0307","\u0163":"t\u0327","\xfa":"u\u0301","\xf9":"u\u0300","\xfc":"u\u0308","\u01d8":"u\u0308\u0301","\u01dc":"u\u0308\u0300","\u01d6":"u\u0308\u0304","\u01da":"u\u0308\u030c","\u0169":"u\u0303","\u1e79":"u\u0303\u0301","\u016b":"u\u0304","\u1e7b":"u\u0304\u0308","\u016d":"u\u0306","\u01d4":"u\u030c","\xfb":"u\u0302","\u016f":"u\u030a","\u0171":"u\u030b","\u1e7d":"v\u0303","\u1e83":"w\u0301","\u1e81":"w\u0300","\u1e85":"w\u0308","\u0175":"w\u0302","\u1e87":"w\u0307","\u1e98":"w\u030a","\u1e8d":"x\u0308","\u1e8b":"x\u0307","\xfd":"y\u0301","\u1ef3":"y\u0300","\xff":"y\u0308","\u1ef9":"y\u0303","\u0233":"y\u0304","\u0177":"y\u0302","\u1e8f":"y\u0307","\u1e99":"y\u030a","\u017a":"z\u0301","\u017e":"z\u030c","\u1e91":"z\u0302","\u017c":"z\u0307","\xc1":"A\u0301","\xc0":"A\u0300","\xc4":"A\u0308","\u01de":"A\u0308\u0304","\xc3":"A\u0303","\u0100":"A\u0304","\u0102":"A\u0306","\u1eae":"A\u0306\u0301","\u1eb0":"A\u0306\u0300","\u1eb4":"A\u0306\u0303","\u01cd":"A\u030c","\xc2":"A\u0302","\u1ea4":"A\u0302\u0301","\u1ea6":"A\u0302\u0300","\u1eaa":"A\u0302\u0303","\u0226":"A\u0307","\u01e0":"A\u0307\u0304","\xc5":"A\u030a","\u01fa":"A\u030a\u0301","\u1e02":"B\u0307","\u0106":"C\u0301","\u1e08":"C\u0327\u0301","\u010c":"C\u030c","\u0108":"C\u0302","\u010a":"C\u0307","\xc7":"C\u0327","\u010e":"D\u030c","\u1e0a":"D\u0307","\u1e10":"D\u0327","\xc9":"E\u0301","\xc8":"E\u0300","\xcb":"E\u0308","\u1ebc":"E\u0303","\u0112":"E\u0304","\u1e16":"E\u0304\u0301","\u1e14":"E\u0304\u0300","\u0114":"E\u0306","\u1e1c":"E\u0327\u0306","\u011a":"E\u030c","\xca":"E\u0302","\u1ebe":"E\u0302\u0301","\u1ec0":"E\u0302\u0300","\u1ec4":"E\u0302\u0303","\u0116":"E\u0307","\u0228":"E\u0327","\u1e1e":"F\u0307","\u01f4":"G\u0301","\u1e20":"G\u0304","\u011e":"G\u0306","\u01e6":"G\u030c","\u011c":"G\u0302","\u0120":"G\u0307","\u0122":"G\u0327","\u1e26":"H\u0308","\u021e":"H\u030c","\u0124":"H\u0302","\u1e22":"H\u0307","\u1e28":"H\u0327","\xcd":"I\u0301","\xcc":"I\u0300","\xcf":"I\u0308","\u1e2e":"I\u0308\u0301","\u0128":"I\u0303","\u012a":"I\u0304","\u012c":"I\u0306","\u01cf":"I\u030c","\xce":"I\u0302","\u0130":"I\u0307","\u0134":"J\u0302","\u1e30":"K\u0301","\u01e8":"K\u030c","\u0136":"K\u0327","\u0139":"L\u0301","\u013d":"L\u030c","\u013b":"L\u0327","\u1e3e":"M\u0301","\u1e40":"M\u0307","\u0143":"N\u0301","\u01f8":"N\u0300","\xd1":"N\u0303","\u0147":"N\u030c","\u1e44":"N\u0307","\u0145":"N\u0327","\xd3":"O\u0301","\xd2":"O\u0300","\xd6":"O\u0308","\u022a":"O\u0308\u0304","\xd5":"O\u0303","\u1e4c":"O\u0303\u0301","\u1e4e":"O\u0303\u0308","\u022c":"O\u0303\u0304","\u014c":"O\u0304","\u1e52":"O\u0304\u0301","\u1e50":"O\u0304\u0300","\u014e":"O\u0306","\u01d1":"O\u030c","\xd4":"O\u0302","\u1ed0":"O\u0302\u0301","\u1ed2":"O\u0302\u0300","\u1ed6":"O\u0302\u0303","\u022e":"O\u0307","\u0230":"O\u0307\u0304","\u0150":"O\u030b","\u1e54":"P\u0301","\u1e56":"P\u0307","\u0154":"R\u0301","\u0158":"R\u030c","\u1e58":"R\u0307","\u0156":"R\u0327","\u015a":"S\u0301","\u1e64":"S\u0301\u0307","\u0160":"S\u030c","\u1e66":"S\u030c\u0307","\u015c":"S\u0302","\u1e60":"S\u0307","\u015e":"S\u0327","\u0164":"T\u030c","\u1e6a":"T\u0307","\u0162":"T\u0327","\xda":"U\u0301","\xd9":"U\u0300","\xdc":"U\u0308","\u01d7":"U\u0308\u0301","\u01db":"U\u0308\u0300","\u01d5":"U\u0308\u0304","\u01d9":"U\u0308\u030c","\u0168":"U\u0303","\u1e78":"U\u0303\u0301","\u016a":"U\u0304","\u1e7a":"U\u0304\u0308","\u016c":"U\u0306","\u01d3":"U\u030c","\xdb":"U\u0302","\u016e":"U\u030a","\u0170":"U\u030b","\u1e7c":"V\u0303","\u1e82":"W\u0301","\u1e80":"W\u0300","\u1e84":"W\u0308","\u0174":"W\u0302","\u1e86":"W\u0307","\u1e8c":"X\u0308","\u1e8a":"X\u0307","\xdd":"Y\u0301","\u1ef2":"Y\u0300","\u0178":"Y\u0308","\u1ef8":"Y\u0303","\u0232":"Y\u0304","\u0176":"Y\u0302","\u1e8e":"Y\u0307","\u0179":"Z\u0301","\u017d":"Z\u030c","\u1e90":"Z\u0302","\u017b":"Z\u0307","\u03ac":"\u03b1\u0301","\u1f70":"\u03b1\u0300","\u1fb1":"\u03b1\u0304","\u1fb0":"\u03b1\u0306","\u03ad":"\u03b5\u0301","\u1f72":"\u03b5\u0300","\u03ae":"\u03b7\u0301","\u1f74":"\u03b7\u0300","\u03af":"\u03b9\u0301","\u1f76":"\u03b9\u0300","\u03ca":"\u03b9\u0308","\u0390":"\u03b9\u0308\u0301","\u1fd2":"\u03b9\u0308\u0300","\u1fd1":"\u03b9\u0304","\u1fd0":"\u03b9\u0306","\u03cc":"\u03bf\u0301","\u1f78":"\u03bf\u0300","\u03cd":"\u03c5\u0301","\u1f7a":"\u03c5\u0300","\u03cb":"\u03c5\u0308","\u03b0":"\u03c5\u0308\u0301","\u1fe2":"\u03c5\u0308\u0300","\u1fe1":"\u03c5\u0304","\u1fe0":"\u03c5\u0306","\u03ce":"\u03c9\u0301","\u1f7c":"\u03c9\u0300","\u038e":"\u03a5\u0301","\u1fea":"\u03a5\u0300","\u03ab":"\u03a5\u0308","\u1fe9":"\u03a5\u0304","\u1fe8":"\u03a5\u0306","\u038f":"\u03a9\u0301","\u1ffa":"\u03a9\u0300"},jn=function(){function e(e,t){this.mode=void 0,this.gullet=void 0,this.settings=void 0,this.leftrightDepth=void 0,this.nextToken=void 0,this.mode="math",this.gullet=new Un(e,t,this.mode),this.settings=t,this.leftrightDepth=0}var t=e.prototype;return t.expect=function(e,t){if(void 0===t&&(t=!0),this.fetch().text!==e)throw new n("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()},t.consume=function(){this.nextToken=null},t.fetch=function(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken},t.switchMode=function(e){this.mode=e,this.gullet.switchMode(e)},t.parse=function(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");try{var e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e}finally{this.gullet.endGroups()}},t.subparse=function(e){var t=this.nextToken;this.consume(),this.gullet.pushToken(new Dr("}")),this.gullet.pushTokens(e);var r=this.parseExpression(!1);return this.expect("}"),this.nextToken=t,r},t.parseExpression=function(t,r){for(var n=[];;){"math"===this.mode&&this.consumeSpaces();var a=this.fetch();if(-1!==e.endOfExpression.indexOf(a.text))break;if(r&&a.text===r)break;if(t&&Nn[a.text]&&Nn[a.text].infix)break;var i=this.parseAtom(r);if(!i)break;"internal"!==i.type&&n.push(i)}return"text"===this.mode&&this.formLigatures(n),this.handleInfixNodes(n)},t.handleInfixNodes=function(e){for(var t,r=-1,a=0;a=0&&this.settings.reportNonstrict("unicodeTextInMathMode",'Latin-1/Unicode text character "'+t[0]+'" used in math mode',e);var s,l=ae[this.mode][t].group,h=Lr.range(e);if(te.hasOwnProperty(l)){var m=l;s={type:"atom",mode:this.mode,family:m,loc:h,text:t}}else s={type:l,mode:this.mode,loc:h,text:t};i=s}else{if(!(t.charCodeAt(0)>=128))return null;this.settings.strict&&(S(t.charCodeAt(0))?"math"===this.mode&&this.settings.reportNonstrict("unicodeTextInMathMode",'Unicode text character "'+t[0]+'" used in math mode',e):this.settings.reportNonstrict("unknownSymbol",'Unrecognized Unicode character "'+t[0]+'" ('+t.charCodeAt(0)+")",e)),i={type:"textord",mode:"text",loc:Lr.range(e),text:t}}if(this.consume(),o)for(var c=0;c":">","<":"<",'"':""","'":"'"},R=/[&><"']/g,Z={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(R,function(e){return O[e]})},hyphenate:function(e){return e.replace(I,"-$1").toLowerCase()},getBaseElem:C,isCharacterBox:function(e){e=C(e);return"mathord"===e.type||"textord"===e.type||"atom"===e.type},protocolFromUrl:function(e){e=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=e?e[1]:"_relative"}},E={displayMode:{type:"boolean",description:"Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.",cli:"-d, --display-mode"},output:{type:{enum:["htmlAndMathml","html","mathml"]},description:"Determines the markup language of the output.",cli:"-F, --format "},leqno:{type:"boolean",description:"Render display math in leqno style (left-justified tags)."},fleqn:{type:"boolean",description:"Render display math flush left."},throwOnError:{type:"boolean",default:!0,cli:"-t, --no-throw-on-error",cliDescription:"Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error."},errorColor:{type:"string",default:"#cc0000",cli:"-c, --error-color ",cliDescription:"A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.",cliProcessor:function(e){return"#"+e}},macros:{type:"object",cli:"-m, --macro ",cliDescription:"Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).",cliDefault:[],cliProcessor:function(e,t){return t.push(e),t}},minRuleThickness:{type:"number",description:"Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.",processor:function(e){return Math.max(0,e)},cli:"--min-rule-thickness ",cliProcessor:parseFloat},colorIsTextColor:{type:"boolean",description:"Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.",cli:"-b, --color-is-text-color"},strict:{type:[{enum:["warn","ignore","error"]},"boolean","function"],description:"Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.",cli:"-S, --strict",cliDefault:!1},trust:{type:["boolean","function"],description:"Trust the input, enabling all HTML features such as \\url.",cli:"-T, --trust"},maxSize:{type:"number",default:1/0,description:"If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large",processor:function(e){return Math.max(0,e)},cli:"-s, --max-size ",cliProcessor:parseInt},maxExpand:{type:"number",default:1e3,description:"Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.",processor:function(e){return Math.max(0,e)},cli:"-e, --max-expand ",cliProcessor:function(e){return"Infinity"===e?1/0:parseInt(e)}},globalGroup:{type:"boolean",cli:!1}};(t=W.prototype).reportNonstrict=function(e,t,r){var n=this.strict;if((n="function"==typeof n?n(e,t,r):n)&&"ignore"!==n){if(!0===n||"error"===n)throw new $("LaTeX-incompatible input and strict mode is set to 'error': "+t+" ["+e+"]",r);"warn"===n?"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"):"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+n+"': "+t+" ["+e+"]")}},t.useStrictBehavior=function(e,t,r){var n=this.strict;if("function"==typeof n)try{n=n(e,t,r)}catch(e){n="error"}return!(!n||"ignore"===n||!0!==n&&"error"!==n&&("warn"===n?"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"):"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+n+"': "+t+" ["+e+"]"),1))},t.isTrusted=function(e){e.url&&!e.protocol&&(e.protocol=Z.protocolFromUrl(e.url));e="function"==typeof this.trust?this.trust(e):this.trust;return Boolean(e)};var H=W,e=((t=X.prototype).sup=function(){return L[D[this.id]]},t.sub=function(){return L[P[this.id]]},t.fracNum=function(){return L[F[this.id]]},t.fracDen=function(){return L[V[this.id]]},t.cramp=function(){return L[G[this.id]]},t.text=function(){return L[U[this.id]]},X),L=[new e(0,0,!(t.isTight=function(){return 2<=this.size})),new e(1,0,!0),new e(2,1,!1),new e(3,1,!0),new e(4,2,!1),new e(5,2,!0),new e(6,3,!1),new e(7,3,!0)],D=[4,5,4,5,6,7,6,7],P=[5,5,5,5,7,7,7,7],F=[2,3,4,5,6,7,6,7],V=[3,3,5,5,7,7,7,7],G=[1,1,3,3,5,5,7,7],U=[0,1,2,3,2,3,2,3],K={DISPLAY:L[0],TEXT:L[2],SCRIPT:L[4],SCRIPTSCRIPT:L[6]},Y=[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}];function X(e,t,r){this.id=void 0,this.size=void 0,this.cramped=void 0,this.id=e,this.size=t,this.cramped=r}function W(e){for(var t in this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0,this.errorColor=void 0,this.macros=void 0,this.minRuleThickness=void 0,this.colorIsTextColor=void 0,this.strict=void 0,this.trust=void 0,this.maxSize=void 0,this.maxExpand=void 0,this.globalGroup=void 0,e=e||{},E){var r;E.hasOwnProperty(t)&&(r=E[t],this[t]=void 0!==e[t]?r.processor?r.processor(e[t]):e[t]:function(e){if(e.default)return e.default;if(e=e.type,"string"!=typeof(e=Array.isArray(e)?e[0]:e))return e.enum[0];switch(e){case"boolean":return!1;case"string":return"";case"number":return 0;case"object":return{}}}(r))}}var j=[];function _(e){for(var t=0;t=j[t]&&e<=j[t+1])return 1}Y.forEach(function(e){return e.blocks.forEach(function(e){return j.push.apply(j,e)})});var ne={doubleleftarrow:"M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",doublerightarrow:"M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",leftarrow:"M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",leftbrace:"M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",leftbraceunder:"M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",leftgroup:"M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",leftgroupunder:"M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",leftharpoon:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",leftharpoonplus:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",leftharpoondown:"M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",leftharpoondownplus:"M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",lefthook:"M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",leftlinesegment:"M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",leftmapsto:"M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",leftToFrom:"M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",longequal:"M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",midbrace:"M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",midbraceunder:"M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",oiintSize1:"M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",oiintSize2:"M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",oiiintSize1:"M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",oiiintSize2:"M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",rightarrow:"M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",rightbrace:"M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",rightbraceunder:"M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",rightgroup:"M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",rightgroupunder:"M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",rightharpoon:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",rightharpoonplus:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",rightharpoondown:"M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",rightharpoondownplus:"M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",righthook:"M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",rightlinesegment:"M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",rightToFrom:"M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",twoheadleftarrow:"M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",twoheadrightarrow:"M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",tilde1:"M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",tilde2:"M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",tilde3:"M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",tilde4:"M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",vec:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",widehat1:"M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",widehat2:"M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat3:"M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat4:"M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widecheck1:"M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",widecheck2:"M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck3:"M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck4:"M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",baraboveleftarrow:"M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",rightarrowabovebar:"M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",baraboveshortleftharpoon:"M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",rightharpoonaboveshortbar:"M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",shortbaraboveleftharpoon:"M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",shortrightharpoonabovebar:"M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"},ie=((t=le.prototype).hasClass=function(e){return Z.contains(this.classes,e)},t.toNode=function(){for(var e=document.createDocumentFragment(),t=0;t"}var ve=t,we={pt:1,mm:7227/2540,cm:7227/254,in:72.27,bp:1.00375,pc:12,dd:1238/1157,cc:14856/1157,nd:685/642,nc:1370/107,sp:1/65536,px:1.00375},ke={ex:!0,em:!0,mu:!0},Q=function(e){return+e.toFixed(4)+"em"},Se=((e=He.prototype).setAttribute=function(e,t){this.attributes[e]=t},e.hasClass=function(e){return Z.contains(this.classes,e)},e.toNode=function(){return be.call(this,"span")},e.toMarkup=function(){return xe.call(this,"span")},He),Me=((t=Ee.prototype).setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return Z.contains(this.classes,e)},t.toNode=function(){return be.call(this,"a")},t.toMarkup=function(){return xe.call(this,"a")},Ee),ze=((e=Re.prototype).hasClass=function(e){return Z.contains(this.classes,e)},e.toNode=function(){var e,t=document.createElement("img");for(e in t.src=this.src,t.alt=this.alt,t.className="mord",this.style)this.style.hasOwnProperty(e)&&(t.style[e]=this.style[e]);return t},e.toMarkup=function(){var e,t=""+this.alt+""},Re),Ae={"î":"ı̂","ï":"ı̈","í":"ı́","ì":"ı̀"},b=((t=Oe.prototype).hasClass=function(e){return Z.contains(this.classes,e)},t.toNode=function(){var e,t=document.createTextNode(this.text),r=null;for(e in 0"+i)+"":i},Oe),Te=((e=Ie.prototype).toNode=function(){var e,t=document.createElementNS("http://www.w3.org/2000/svg","svg");for(e in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,e)&&t.setAttribute(e,this.attributes[e]);for(var r=0;r"},Ie),Be=((t=qe.prototype).toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","path");return this.alternate?e.setAttribute("d",this.alternate):e.setAttribute("d",ne[this.pathName]),e},t.toMarkup=function(){return this.alternate?"":""},qe),Ce=((e=Ne.prototype).toNode=function(){var e,t=document.createElementNS("http://www.w3.org/2000/svg","line");for(e in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,e)&&t.setAttribute(e,this.attributes[e]);return t},e.toMarkup=function(){var e,t=""},Ne);function Ne(e){this.attributes=void 0,this.attributes=e||{}}function qe(e,t){this.pathName=void 0,this.alternate=void 0,this.pathName=e,this.alternate=t}function Ie(e,t){this.children=void 0,this.attributes=void 0,this.children=e||[],this.attributes=t||{}}function Oe(e,t,r,n,i,a,o,s){this.text=void 0,this.height=void 0,this.depth=void 0,this.italic=void 0,this.skew=void 0,this.width=void 0,this.maxFontSize=void 0,this.classes=void 0,this.style=void 0,this.text=e,this.height=t||0,this.depth=r||0,this.italic=n||0,this.skew=i||0,this.width=a||0,this.classes=o||[],this.style=s||{},this.maxFontSize=0;e=function(e){for(var t=0;t=i[0]&&e<=i[1])return r.name}return null}(this.text.charCodeAt(0));e&&this.classes.push(e+"_fallback"),/[\xee\xef\xed\xec]/.test(this.text)&&(this.text=Ae[this.text])}function Re(e,t,r){this.src=void 0,this.alt=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.alt=t,this.src=e,this.classes=["mord"],this.style=r}function Ee(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,ye.call(this,t,n),this.children=r||[],this.setAttribute("href",e)}function He(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.width=void 0,this.maxFontSize=void 0,this.style=void 0,ye.call(this,e,r,n),this.children=t||[]}function Le(e){if(e instanceof b)return e;throw new Error("Expected symbolNode but got "+String(e)+".")}var De={bin:1,close:1,inner:1,open:1,punct:1,rel:1},Pe={"accent-token":1,mathord:1,"op-token":1,spacing:1,textord:1},Fe={math:{},text:{}},p=Fe;function r(e,t,r,n,i,a){Fe[e][i]={font:t,group:r,replace:n},a&&n&&(Fe[e][n]=Fe[e][i])}var n="math",i="text",a="main",t="ams",e="accent-token",o="bin",s="close",Ve="inner",l="mathord",h="op-token",m="open",c="punct",u="rel",d="spacing",f="textord",Ge=(r(n,a,u,"≡","\\equiv",!0),r(n,a,u,"≺","\\prec",!0),r(n,a,u,"≻","\\succ",!0),r(n,a,u,"∼","\\sim",!0),r(n,a,u,"⊥","\\perp"),r(n,a,u,"⪯","\\preceq",!0),r(n,a,u,"⪰","\\succeq",!0),r(n,a,u,"≃","\\simeq",!0),r(n,a,u,"∣","\\mid",!0),r(n,a,u,"≪","\\ll",!0),r(n,a,u,"≫","\\gg",!0),r(n,a,u,"≍","\\asymp",!0),r(n,a,u,"∥","\\parallel"),r(n,a,u,"⋈","\\bowtie",!0),r(n,a,u,"⌣","\\smile",!0),r(n,a,u,"⊑","\\sqsubseteq",!0),r(n,a,u,"⊒","\\sqsupseteq",!0),r(n,a,u,"≐","\\doteq",!0),r(n,a,u,"⌢","\\frown",!0),r(n,a,u,"∋","\\ni",!0),r(n,a,u,"∝","\\propto",!0),r(n,a,u,"⊢","\\vdash",!0),r(n,a,u,"⊣","\\dashv",!0),r(n,a,u,"∋","\\owns"),r(n,a,c,".","\\ldotp"),r(n,a,c,"⋅","\\cdotp"),r(n,a,f,"#","\\#"),r(i,a,f,"#","\\#"),r(n,a,f,"&","\\&"),r(i,a,f,"&","\\&"),r(n,a,f,"ℵ","\\aleph",!0),r(n,a,f,"∀","\\forall",!0),r(n,a,f,"ℏ","\\hbar",!0),r(n,a,f,"∃","\\exists",!0),r(n,a,f,"∇","\\nabla",!0),r(n,a,f,"♭","\\flat",!0),r(n,a,f,"ℓ","\\ell",!0),r(n,a,f,"♮","\\natural",!0),r(n,a,f,"♣","\\clubsuit",!0),r(n,a,f,"℘","\\wp",!0),r(n,a,f,"♯","\\sharp",!0),r(n,a,f,"♢","\\diamondsuit",!0),r(n,a,f,"ℜ","\\Re",!0),r(n,a,f,"♡","\\heartsuit",!0),r(n,a,f,"ℑ","\\Im",!0),r(n,a,f,"♠","\\spadesuit",!0),r(n,a,f,"§","\\S",!0),r(i,a,f,"§","\\S"),r(n,a,f,"¶","\\P",!0),r(i,a,f,"¶","\\P"),r(n,a,f,"†","\\dag"),r(i,a,f,"†","\\dag"),r(i,a,f,"†","\\textdagger"),r(n,a,f,"‡","\\ddag"),r(i,a,f,"‡","\\ddag"),r(i,a,f,"‡","\\textdaggerdbl"),r(n,a,s,"⎱","\\rmoustache",!0),r(n,a,m,"⎰","\\lmoustache",!0),r(n,a,s,"⟯","\\rgroup",!0),r(n,a,m,"⟮","\\lgroup",!0),r(n,a,o,"∓","\\mp",!0),r(n,a,o,"⊖","\\ominus",!0),r(n,a,o,"⊎","\\uplus",!0),r(n,a,o,"⊓","\\sqcap",!0),r(n,a,o,"∗","\\ast"),r(n,a,o,"⊔","\\sqcup",!0),r(n,a,o,"◯","\\bigcirc",!0),r(n,a,o,"∙","\\bullet",!0),r(n,a,o,"‡","\\ddagger"),r(n,a,o,"≀","\\wr",!0),r(n,a,o,"⨿","\\amalg"),r(n,a,o,"&","\\And"),r(n,a,u,"⟵","\\longleftarrow",!0),r(n,a,u,"⇐","\\Leftarrow",!0),r(n,a,u,"⟸","\\Longleftarrow",!0),r(n,a,u,"⟶","\\longrightarrow",!0),r(n,a,u,"⇒","\\Rightarrow",!0),r(n,a,u,"⟹","\\Longrightarrow",!0),r(n,a,u,"↔","\\leftrightarrow",!0),r(n,a,u,"⟷","\\longleftrightarrow",!0),r(n,a,u,"⇔","\\Leftrightarrow",!0),r(n,a,u,"⟺","\\Longleftrightarrow",!0),r(n,a,u,"↦","\\mapsto",!0),r(n,a,u,"⟼","\\longmapsto",!0),r(n,a,u,"↗","\\nearrow",!0),r(n,a,u,"↩","\\hookleftarrow",!0),r(n,a,u,"↪","\\hookrightarrow",!0),r(n,a,u,"↘","\\searrow",!0),r(n,a,u,"↼","\\leftharpoonup",!0),r(n,a,u,"⇀","\\rightharpoonup",!0),r(n,a,u,"↙","\\swarrow",!0),r(n,a,u,"↽","\\leftharpoondown",!0),r(n,a,u,"⇁","\\rightharpoondown",!0),r(n,a,u,"↖","\\nwarrow",!0),r(n,a,u,"⇌","\\rightleftharpoons",!0),r(n,t,u,"≮","\\nless",!0),r(n,t,u,"","\\@nleqslant"),r(n,t,u,"","\\@nleqq"),r(n,t,u,"⪇","\\lneq",!0),r(n,t,u,"≨","\\lneqq",!0),r(n,t,u,"","\\@lvertneqq"),r(n,t,u,"⋦","\\lnsim",!0),r(n,t,u,"⪉","\\lnapprox",!0),r(n,t,u,"⊀","\\nprec",!0),r(n,t,u,"⋠","\\npreceq",!0),r(n,t,u,"⋨","\\precnsim",!0),r(n,t,u,"⪹","\\precnapprox",!0),r(n,t,u,"≁","\\nsim",!0),r(n,t,u,"","\\@nshortmid"),r(n,t,u,"∤","\\nmid",!0),r(n,t,u,"⊬","\\nvdash",!0),r(n,t,u,"⊭","\\nvDash",!0),r(n,t,u,"⋪","\\ntriangleleft"),r(n,t,u,"⋬","\\ntrianglelefteq",!0),r(n,t,u,"⊊","\\subsetneq",!0),r(n,t,u,"","\\@varsubsetneq"),r(n,t,u,"⫋","\\subsetneqq",!0),r(n,t,u,"","\\@varsubsetneqq"),r(n,t,u,"≯","\\ngtr",!0),r(n,t,u,"","\\@ngeqslant"),r(n,t,u,"","\\@ngeqq"),r(n,t,u,"⪈","\\gneq",!0),r(n,t,u,"≩","\\gneqq",!0),r(n,t,u,"","\\@gvertneqq"),r(n,t,u,"⋧","\\gnsim",!0),r(n,t,u,"⪊","\\gnapprox",!0),r(n,t,u,"⊁","\\nsucc",!0),r(n,t,u,"⋡","\\nsucceq",!0),r(n,t,u,"⋩","\\succnsim",!0),r(n,t,u,"⪺","\\succnapprox",!0),r(n,t,u,"≆","\\ncong",!0),r(n,t,u,"","\\@nshortparallel"),r(n,t,u,"∦","\\nparallel",!0),r(n,t,u,"⊯","\\nVDash",!0),r(n,t,u,"⋫","\\ntriangleright"),r(n,t,u,"⋭","\\ntrianglerighteq",!0),r(n,t,u,"","\\@nsupseteqq"),r(n,t,u,"⊋","\\supsetneq",!0),r(n,t,u,"","\\@varsupsetneq"),r(n,t,u,"⫌","\\supsetneqq",!0),r(n,t,u,"","\\@varsupsetneqq"),r(n,t,u,"⊮","\\nVdash",!0),r(n,t,u,"⪵","\\precneqq",!0),r(n,t,u,"⪶","\\succneqq",!0),r(n,t,u,"","\\@nsubseteqq"),r(n,t,o,"⊴","\\unlhd"),r(n,t,o,"⊵","\\unrhd"),r(n,t,u,"↚","\\nleftarrow",!0),r(n,t,u,"↛","\\nrightarrow",!0),r(n,t,u,"⇍","\\nLeftarrow",!0),r(n,t,u,"⇏","\\nRightarrow",!0),r(n,t,u,"↮","\\nleftrightarrow",!0),r(n,t,u,"⇎","\\nLeftrightarrow",!0),r(n,t,u,"△","\\vartriangle"),r(n,t,f,"ℏ","\\hslash"),r(n,t,f,"▽","\\triangledown"),r(n,t,f,"◊","\\lozenge"),r(n,t,f,"Ⓢ","\\circledS"),r(n,t,f,"®","\\circledR"),r(i,t,f,"®","\\circledR"),r(n,t,f,"∡","\\measuredangle",!0),r(n,t,f,"∄","\\nexists"),r(n,t,f,"℧","\\mho"),r(n,t,f,"Ⅎ","\\Finv",!0),r(n,t,f,"⅁","\\Game",!0),r(n,t,f,"‵","\\backprime"),r(n,t,f,"▲","\\blacktriangle"),r(n,t,f,"▼","\\blacktriangledown"),r(n,t,f,"■","\\blacksquare"),r(n,t,f,"⧫","\\blacklozenge"),r(n,t,f,"★","\\bigstar"),r(n,t,f,"∢","\\sphericalangle",!0),r(n,t,f,"∁","\\complement",!0),r(n,t,f,"ð","\\eth",!0),r(i,a,f,"ð","ð"),r(n,t,f,"╱","\\diagup"),r(n,t,f,"╲","\\diagdown"),r(n,t,f,"□","\\square"),r(n,t,f,"□","\\Box"),r(n,t,f,"◊","\\Diamond"),r(n,t,f,"¥","\\yen",!0),r(i,t,f,"¥","\\yen",!0),r(n,t,f,"✓","\\checkmark",!0),r(i,t,f,"✓","\\checkmark"),r(n,t,f,"ℶ","\\beth",!0),r(n,t,f,"ℸ","\\daleth",!0),r(n,t,f,"ℷ","\\gimel",!0),r(n,t,f,"ϝ","\\digamma",!0),r(n,t,f,"ϰ","\\varkappa"),r(n,t,m,"┌","\\@ulcorner",!0),r(n,t,s,"┐","\\@urcorner",!0),r(n,t,m,"└","\\@llcorner",!0),r(n,t,s,"┘","\\@lrcorner",!0),r(n,t,u,"≦","\\leqq",!0),r(n,t,u,"⩽","\\leqslant",!0),r(n,t,u,"⪕","\\eqslantless",!0),r(n,t,u,"≲","\\lesssim",!0),r(n,t,u,"⪅","\\lessapprox",!0),r(n,t,u,"≊","\\approxeq",!0),r(n,t,o,"⋖","\\lessdot"),r(n,t,u,"⋘","\\lll",!0),r(n,t,u,"≶","\\lessgtr",!0),r(n,t,u,"⋚","\\lesseqgtr",!0),r(n,t,u,"⪋","\\lesseqqgtr",!0),r(n,t,u,"≑","\\doteqdot"),r(n,t,u,"≓","\\risingdotseq",!0),r(n,t,u,"≒","\\fallingdotseq",!0),r(n,t,u,"∽","\\backsim",!0),r(n,t,u,"⋍","\\backsimeq",!0),r(n,t,u,"⫅","\\subseteqq",!0),r(n,t,u,"⋐","\\Subset",!0),r(n,t,u,"⊏","\\sqsubset",!0),r(n,t,u,"≼","\\preccurlyeq",!0),r(n,t,u,"⋞","\\curlyeqprec",!0),r(n,t,u,"≾","\\precsim",!0),r(n,t,u,"⪷","\\precapprox",!0),r(n,t,u,"⊲","\\vartriangleleft"),r(n,t,u,"⊴","\\trianglelefteq"),r(n,t,u,"⊨","\\vDash",!0),r(n,t,u,"⊪","\\Vvdash",!0),r(n,t,u,"⌣","\\smallsmile"),r(n,t,u,"⌢","\\smallfrown"),r(n,t,u,"≏","\\bumpeq",!0),r(n,t,u,"≎","\\Bumpeq",!0),r(n,t,u,"≧","\\geqq",!0),r(n,t,u,"⩾","\\geqslant",!0),r(n,t,u,"⪖","\\eqslantgtr",!0),r(n,t,u,"≳","\\gtrsim",!0),r(n,t,u,"⪆","\\gtrapprox",!0),r(n,t,o,"⋗","\\gtrdot"),r(n,t,u,"⋙","\\ggg",!0),r(n,t,u,"≷","\\gtrless",!0),r(n,t,u,"⋛","\\gtreqless",!0),r(n,t,u,"⪌","\\gtreqqless",!0),r(n,t,u,"≖","\\eqcirc",!0),r(n,t,u,"≗","\\circeq",!0),r(n,t,u,"≜","\\triangleq",!0),r(n,t,u,"∼","\\thicksim"),r(n,t,u,"≈","\\thickapprox"),r(n,t,u,"⫆","\\supseteqq",!0),r(n,t,u,"⋑","\\Supset",!0),r(n,t,u,"⊐","\\sqsupset",!0),r(n,t,u,"≽","\\succcurlyeq",!0),r(n,t,u,"⋟","\\curlyeqsucc",!0),r(n,t,u,"≿","\\succsim",!0),r(n,t,u,"⪸","\\succapprox",!0),r(n,t,u,"⊳","\\vartriangleright"),r(n,t,u,"⊵","\\trianglerighteq"),r(n,t,u,"⊩","\\Vdash",!0),r(n,t,u,"∣","\\shortmid"),r(n,t,u,"∥","\\shortparallel"),r(n,t,u,"≬","\\between",!0),r(n,t,u,"⋔","\\pitchfork",!0),r(n,t,u,"∝","\\varpropto"),r(n,t,u,"◀","\\blacktriangleleft"),r(n,t,u,"∴","\\therefore",!0),r(n,t,u,"∍","\\backepsilon"),r(n,t,u,"▶","\\blacktriangleright"),r(n,t,u,"∵","\\because",!0),r(n,t,u,"⋘","\\llless"),r(n,t,u,"⋙","\\gggtr"),r(n,t,o,"⊲","\\lhd"),r(n,t,o,"⊳","\\rhd"),r(n,t,u,"≂","\\eqsim",!0),r(n,a,u,"⋈","\\Join"),r(n,t,u,"≑","\\Doteq",!0),r(n,t,o,"∔","\\dotplus",!0),r(n,t,o,"∖","\\smallsetminus"),r(n,t,o,"⋒","\\Cap",!0),r(n,t,o,"⋓","\\Cup",!0),r(n,t,o,"⩞","\\doublebarwedge",!0),r(n,t,o,"⊟","\\boxminus",!0),r(n,t,o,"⊞","\\boxplus",!0),r(n,t,o,"⋇","\\divideontimes",!0),r(n,t,o,"⋉","\\ltimes",!0),r(n,t,o,"⋊","\\rtimes",!0),r(n,t,o,"⋋","\\leftthreetimes",!0),r(n,t,o,"⋌","\\rightthreetimes",!0),r(n,t,o,"⋏","\\curlywedge",!0),r(n,t,o,"⋎","\\curlyvee",!0),r(n,t,o,"⊝","\\circleddash",!0),r(n,t,o,"⊛","\\circledast",!0),r(n,t,o,"⋅","\\centerdot"),r(n,t,o,"⊺","\\intercal",!0),r(n,t,o,"⋒","\\doublecap"),r(n,t,o,"⋓","\\doublecup"),r(n,t,o,"⊠","\\boxtimes",!0),r(n,t,u,"⇢","\\dashrightarrow",!0),r(n,t,u,"⇠","\\dashleftarrow",!0),r(n,t,u,"⇇","\\leftleftarrows",!0),r(n,t,u,"⇆","\\leftrightarrows",!0),r(n,t,u,"⇚","\\Lleftarrow",!0),r(n,t,u,"↞","\\twoheadleftarrow",!0),r(n,t,u,"↢","\\leftarrowtail",!0),r(n,t,u,"↫","\\looparrowleft",!0),r(n,t,u,"⇋","\\leftrightharpoons",!0),r(n,t,u,"↶","\\curvearrowleft",!0),r(n,t,u,"↺","\\circlearrowleft",!0),r(n,t,u,"↰","\\Lsh",!0),r(n,t,u,"⇈","\\upuparrows",!0),r(n,t,u,"↿","\\upharpoonleft",!0),r(n,t,u,"⇃","\\downharpoonleft",!0),r(n,a,u,"⊶","\\origof",!0),r(n,a,u,"⊷","\\imageof",!0),r(n,t,u,"⊸","\\multimap",!0),r(n,t,u,"↭","\\leftrightsquigarrow",!0),r(n,t,u,"⇉","\\rightrightarrows",!0),r(n,t,u,"⇄","\\rightleftarrows",!0),r(n,t,u,"↠","\\twoheadrightarrow",!0),r(n,t,u,"↣","\\rightarrowtail",!0),r(n,t,u,"↬","\\looparrowright",!0),r(n,t,u,"↷","\\curvearrowright",!0),r(n,t,u,"↻","\\circlearrowright",!0),r(n,t,u,"↱","\\Rsh",!0),r(n,t,u,"⇊","\\downdownarrows",!0),r(n,t,u,"↾","\\upharpoonright",!0),r(n,t,u,"⇂","\\downharpoonright",!0),r(n,t,u,"⇝","\\rightsquigarrow",!0),r(n,t,u,"⇝","\\leadsto"),r(n,t,u,"⇛","\\Rrightarrow",!0),r(n,t,u,"↾","\\restriction"),r(n,a,f,"‘","`"),r(n,a,f,"$","\\$"),r(i,a,f,"$","\\$"),r(i,a,f,"$","\\textdollar"),r(n,a,f,"%","\\%"),r(i,a,f,"%","\\%"),r(n,a,f,"_","\\_"),r(i,a,f,"_","\\_"),r(i,a,f,"_","\\textunderscore"),r(n,a,f,"∠","\\angle",!0),r(n,a,f,"∞","\\infty",!0),r(n,a,f,"′","\\prime"),r(n,a,f,"△","\\triangle"),r(n,a,f,"Γ","\\Gamma",!0),r(n,a,f,"Δ","\\Delta",!0),r(n,a,f,"Θ","\\Theta",!0),r(n,a,f,"Λ","\\Lambda",!0),r(n,a,f,"Ξ","\\Xi",!0),r(n,a,f,"Π","\\Pi",!0),r(n,a,f,"Σ","\\Sigma",!0),r(n,a,f,"Υ","\\Upsilon",!0),r(n,a,f,"Φ","\\Phi",!0),r(n,a,f,"Ψ","\\Psi",!0),r(n,a,f,"Ω","\\Omega",!0),r(n,a,f,"A","Α"),r(n,a,f,"B","Β"),r(n,a,f,"E","Ε"),r(n,a,f,"Z","Ζ"),r(n,a,f,"H","Η"),r(n,a,f,"I","Ι"),r(n,a,f,"K","Κ"),r(n,a,f,"M","Μ"),r(n,a,f,"N","Ν"),r(n,a,f,"O","Ο"),r(n,a,f,"P","Ρ"),r(n,a,f,"T","Τ"),r(n,a,f,"X","Χ"),r(n,a,f,"¬","\\neg",!0),r(n,a,f,"¬","\\lnot"),r(n,a,f,"⊤","\\top"),r(n,a,f,"⊥","\\bot"),r(n,a,f,"∅","\\emptyset"),r(n,t,f,"∅","\\varnothing"),r(n,a,l,"α","\\alpha",!0),r(n,a,l,"β","\\beta",!0),r(n,a,l,"γ","\\gamma",!0),r(n,a,l,"δ","\\delta",!0),r(n,a,l,"ϵ","\\epsilon",!0),r(n,a,l,"ζ","\\zeta",!0),r(n,a,l,"η","\\eta",!0),r(n,a,l,"θ","\\theta",!0),r(n,a,l,"ι","\\iota",!0),r(n,a,l,"κ","\\kappa",!0),r(n,a,l,"λ","\\lambda",!0),r(n,a,l,"μ","\\mu",!0),r(n,a,l,"ν","\\nu",!0),r(n,a,l,"ξ","\\xi",!0),r(n,a,l,"ο","\\omicron",!0),r(n,a,l,"π","\\pi",!0),r(n,a,l,"ρ","\\rho",!0),r(n,a,l,"σ","\\sigma",!0),r(n,a,l,"τ","\\tau",!0),r(n,a,l,"υ","\\upsilon",!0),r(n,a,l,"ϕ","\\phi",!0),r(n,a,l,"χ","\\chi",!0),r(n,a,l,"ψ","\\psi",!0),r(n,a,l,"ω","\\omega",!0),r(n,a,l,"ε","\\varepsilon",!0),r(n,a,l,"ϑ","\\vartheta",!0),r(n,a,l,"ϖ","\\varpi",!0),r(n,a,l,"ϱ","\\varrho",!0),r(n,a,l,"ς","\\varsigma",!0),r(n,a,l,"φ","\\varphi",!0),r(n,a,o,"∗","*",!0),r(n,a,o,"+","+"),r(n,a,o,"−","-",!0),r(n,a,o,"⋅","\\cdot",!0),r(n,a,o,"∘","\\circ",!0),r(n,a,o,"÷","\\div",!0),r(n,a,o,"±","\\pm",!0),r(n,a,o,"×","\\times",!0),r(n,a,o,"∩","\\cap",!0),r(n,a,o,"∪","\\cup",!0),r(n,a,o,"∖","\\setminus",!0),r(n,a,o,"∧","\\land"),r(n,a,o,"∨","\\lor"),r(n,a,o,"∧","\\wedge",!0),r(n,a,o,"∨","\\vee",!0),r(n,a,f,"√","\\surd"),r(n,a,m,"⟨","\\langle",!0),r(n,a,m,"∣","\\lvert"),r(n,a,m,"∥","\\lVert"),r(n,a,s,"?","?"),r(n,a,s,"!","!"),r(n,a,s,"⟩","\\rangle",!0),r(n,a,s,"∣","\\rvert"),r(n,a,s,"∥","\\rVert"),r(n,a,u,"=","="),r(n,a,u,":",":"),r(n,a,u,"≈","\\approx",!0),r(n,a,u,"≅","\\cong",!0),r(n,a,u,"≥","\\ge"),r(n,a,u,"≥","\\geq",!0),r(n,a,u,"←","\\gets"),r(n,a,u,">","\\gt",!0),r(n,a,u,"∈","\\in",!0),r(n,a,u,"","\\@not"),r(n,a,u,"⊂","\\subset",!0),r(n,a,u,"⊃","\\supset",!0),r(n,a,u,"⊆","\\subseteq",!0),r(n,a,u,"⊇","\\supseteq",!0),r(n,t,u,"⊈","\\nsubseteq",!0),r(n,t,u,"⊉","\\nsupseteq",!0),r(n,a,u,"⊨","\\models"),r(n,a,u,"←","\\leftarrow",!0),r(n,a,u,"≤","\\le"),r(n,a,u,"≤","\\leq",!0),r(n,a,u,"<","\\lt",!0),r(n,a,u,"→","\\rightarrow",!0),r(n,a,u,"→","\\to"),r(n,t,u,"≱","\\ngeq",!0),r(n,t,u,"≰","\\nleq",!0),r(n,a,d," ","\\ "),r(n,a,d," ","\\space"),r(n,a,d," ","\\nobreakspace"),r(i,a,d," ","\\ "),r(i,a,d," "," "),r(i,a,d," ","\\space"),r(i,a,d," ","\\nobreakspace"),r(n,a,d,null,"\\nobreak"),r(n,a,d,null,"\\allowbreak"),r(n,a,c,",",","),r(n,a,c,";",";"),r(n,t,o,"⊼","\\barwedge",!0),r(n,t,o,"⊻","\\veebar",!0),r(n,a,o,"⊙","\\odot",!0),r(n,a,o,"⊕","\\oplus",!0),r(n,a,o,"⊗","\\otimes",!0),r(n,a,f,"∂","\\partial",!0),r(n,a,o,"⊘","\\oslash",!0),r(n,t,o,"⊚","\\circledcirc",!0),r(n,t,o,"⊡","\\boxdot",!0),r(n,a,o,"△","\\bigtriangleup"),r(n,a,o,"▽","\\bigtriangledown"),r(n,a,o,"†","\\dagger"),r(n,a,o,"⋄","\\diamond"),r(n,a,o,"⋆","\\star"),r(n,a,o,"◃","\\triangleleft"),r(n,a,o,"▹","\\triangleright"),r(n,a,m,"{","\\{"),r(i,a,f,"{","\\{"),r(i,a,f,"{","\\textbraceleft"),r(n,a,s,"}","\\}"),r(i,a,f,"}","\\}"),r(i,a,f,"}","\\textbraceright"),r(n,a,m,"{","\\lbrace"),r(n,a,s,"}","\\rbrace"),r(n,a,m,"[","\\lbrack",!0),r(i,a,f,"[","\\lbrack",!0),r(n,a,s,"]","\\rbrack",!0),r(i,a,f,"]","\\rbrack",!0),r(n,a,m,"(","\\lparen",!0),r(n,a,s,")","\\rparen",!0),r(i,a,f,"<","\\textless",!0),r(i,a,f,">","\\textgreater",!0),r(n,a,m,"⌊","\\lfloor",!0),r(n,a,s,"⌋","\\rfloor",!0),r(n,a,m,"⌈","\\lceil",!0),r(n,a,s,"⌉","\\rceil",!0),r(n,a,f,"\\","\\backslash"),r(n,a,f,"∣","|"),r(n,a,f,"∣","\\vert"),r(i,a,f,"|","\\textbar",!0),r(n,a,f,"∥","\\|"),r(n,a,f,"∥","\\Vert"),r(i,a,f,"∥","\\textbardbl"),r(i,a,f,"~","\\textasciitilde"),r(i,a,f,"\\","\\textbackslash"),r(i,a,f,"^","\\textasciicircum"),r(n,a,u,"↑","\\uparrow",!0),r(n,a,u,"⇑","\\Uparrow",!0),r(n,a,u,"↓","\\downarrow",!0),r(n,a,u,"⇓","\\Downarrow",!0),r(n,a,u,"↕","\\updownarrow",!0),r(n,a,u,"⇕","\\Updownarrow",!0),r(n,a,h,"∐","\\coprod"),r(n,a,h,"⋁","\\bigvee"),r(n,a,h,"⋀","\\bigwedge"),r(n,a,h,"⨄","\\biguplus"),r(n,a,h,"⋂","\\bigcap"),r(n,a,h,"⋃","\\bigcup"),r(n,a,h,"∫","\\int"),r(n,a,h,"∫","\\intop"),r(n,a,h,"∬","\\iint"),r(n,a,h,"∭","\\iiint"),r(n,a,h,"∏","\\prod"),r(n,a,h,"∑","\\sum"),r(n,a,h,"⨂","\\bigotimes"),r(n,a,h,"⨁","\\bigoplus"),r(n,a,h,"⨀","\\bigodot"),r(n,a,h,"∮","\\oint"),r(n,a,h,"∯","\\oiint"),r(n,a,h,"∰","\\oiiint"),r(n,a,h,"⨆","\\bigsqcup"),r(n,a,h,"∫","\\smallint"),r(i,a,Ve,"…","\\textellipsis"),r(n,a,Ve,"…","\\mathellipsis"),r(i,a,Ve,"…","\\ldots",!0),r(n,a,Ve,"…","\\ldots",!0),r(n,a,Ve,"⋯","\\@cdots",!0),r(n,a,Ve,"⋱","\\ddots",!0),r(n,a,f,"⋮","\\varvdots"),r(n,a,e,"ˊ","\\acute"),r(n,a,e,"ˋ","\\grave"),r(n,a,e,"¨","\\ddot"),r(n,a,e,"~","\\tilde"),r(n,a,e,"ˉ","\\bar"),r(n,a,e,"˘","\\breve"),r(n,a,e,"ˇ","\\check"),r(n,a,e,"^","\\hat"),r(n,a,e,"⃗","\\vec"),r(n,a,e,"˙","\\dot"),r(n,a,e,"˚","\\mathring"),r(n,a,l,"","\\@imath"),r(n,a,l,"","\\@jmath"),r(n,a,f,"ı","ı"),r(n,a,f,"ȷ","ȷ"),r(i,a,f,"ı","\\i",!0),r(i,a,f,"ȷ","\\j",!0),r(i,a,f,"ß","\\ss",!0),r(i,a,f,"æ","\\ae",!0),r(i,a,f,"œ","\\oe",!0),r(i,a,f,"ø","\\o",!0),r(i,a,f,"Æ","\\AE",!0),r(i,a,f,"Œ","\\OE",!0),r(i,a,f,"Ø","\\O",!0),r(i,a,e,"ˊ","\\'"),r(i,a,e,"ˋ","\\`"),r(i,a,e,"ˆ","\\^"),r(i,a,e,"˜","\\~"),r(i,a,e,"ˉ","\\="),r(i,a,e,"˘","\\u"),r(i,a,e,"˙","\\."),r(i,a,e,"¸","\\c"),r(i,a,e,"˚","\\r"),r(i,a,e,"ˇ","\\v"),r(i,a,e,"¨",'\\"'),r(i,a,e,"˝","\\H"),r(i,a,e,"◯","\\textcircled"),{"--":!0,"---":!0,"``":!0,"''":!0});r(i,a,f,"–","--",!0),r(i,a,f,"–","\\textendash"),r(i,a,f,"—","---",!0),r(i,a,f,"—","\\textemdash"),r(i,a,f,"‘","`",!0),r(i,a,f,"‘","\\textquoteleft"),r(i,a,f,"’","'",!0),r(i,a,f,"’","\\textquoteright"),r(i,a,f,"“","``",!0),r(i,a,f,"“","\\textquotedblleft"),r(i,a,f,"”","''",!0),r(i,a,f,"”","\\textquotedblright"),r(n,a,f,"°","\\degree",!0),r(i,a,f,"°","\\degree"),r(i,a,f,"°","\\textdegree",!0),r(n,a,f,"£","\\pounds"),r(n,a,f,"£","\\mathsterling",!0),r(i,a,f,"£","\\pounds"),r(i,a,f,"£","\\textsterling",!0),r(n,t,f,"✠","\\maltese"),r(i,t,f,"✠","\\maltese");for(var Ue='0123456789/@."',Ye=0;Yet&&(t=a.height),a.depth>r&&(r=a.depth),a.maxFontSize>n&&(n=a.maxFontSize)}e.height=t,e.depth=r,e.maxFontSize=n}function v(e,t,r,n){return e=new Se(e,t,r,n),it(e),e}function at(e,t,r,n){return new Se(e,t,r,n)}function ot(e){return e=new ie(e),it(e),e}function st(e,t,r){var n="";switch(e){case"amsrm":n="AMS";break;case"textrm":n="Main";break;case"textsf":n="SansSerif";break;case"texttt":n="Typewriter";break;default:n=e}return n+"-"+("textbf"===t&&"textit"===r?"BoldItalic":"textbf"===t?"Bold":"textit"===t?"Italic":"Regular")}var lt=[["mathbf","textbf","Main-Bold"],["mathbf","textbf","Main-Bold"],["mathnormal","textit","Math-Italic"],["mathnormal","textit","Math-Italic"],["boldsymbol","boldsymbol","Main-BoldItalic"],["boldsymbol","boldsymbol","Main-BoldItalic"],["mathscr","textscr","Script-Regular"],["","",""],["","",""],["","",""],["mathfrak","textfrak","Fraktur-Regular"],["mathfrak","textfrak","Fraktur-Regular"],["mathbb","textbb","AMS-Regular"],["mathbb","textbb","AMS-Regular"],["","",""],["","",""],["mathsf","textsf","SansSerif-Regular"],["mathsf","textsf","SansSerif-Regular"],["mathboldsf","textboldsf","SansSerif-Bold"],["mathboldsf","textboldsf","SansSerif-Bold"],["mathitsf","textitsf","SansSerif-Italic"],["mathitsf","textitsf","SansSerif-Italic"],["","",""],["","",""],["mathtt","texttt","Typewriter-Regular"],["mathtt","texttt","Typewriter-Regular"]],ht=[["mathbf","textbf","Main-Bold"],["","",""],["mathsf","textsf","SansSerif-Regular"],["mathboldsf","textboldsf","SansSerif-Bold"],["mathtt","texttt","Typewriter-Regular"]],mt={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathit:{variant:"italic",fontName:"Main-Italic"},mathnormal:{variant:"italic",fontName:"Math-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}},ct={vec:["vec",.471,.714],oiintSize1:["oiintSize1",.957,.499],oiintSize2:["oiintSize2",1.472,.659],oiiintSize1:["oiiintSize1",1.304,.499],oiiintSize2:["oiiintSize2",1.98,.659]},ee={fontMap:mt,makeSymbol:nt,mathsym:function(e,t,r,n){return void 0===n&&(n=[]),"boldsymbol"===r.font&&rt(e,"Main-Bold",t).metrics?nt(e,"Main-Bold",t,r,n.concat(["mathbf"])):"\\"===e||"main"===p[t][e].font?nt(e,"Main-Regular",t,r,n):nt(e,"AMS-Regular",t,r,n.concat(["amsrm"]))},makeSpan:v,makeSvgSpan:at,makeLineSpan:function(e,t,r){e=v([e],[],t);return e.height=Math.max(r||t.fontMetrics().defaultRuleThickness,t.minRuleThickness),e.style.borderBottomWidth=Q(e.height),e.maxFontSize=1,e},makeAnchor:function(e,t,r,n){e=new Me(e,t,r,n);return it(e),e},makeFragment:ot,wrapFragment:function(e,t){return e instanceof ie?v([],[e],t):e},makeVList:function(e,t){for(var e=function(e){if("individualShift"===e.positionType){for(var t=e.children,r=[t[0]],n=-t[0].shift-t[0].elem.depth,i=n,a=1;a"},m.toText=function(){return this.children.map(function(e){return e.toText()}).join("")};var Ht=Ft,Lt=((s=Pt.prototype).toNode=function(){return document.createTextNode(this.text)},s.toMarkup=function(){return Z.escape(this.toText())},s.toText=function(){return this.text},Pt),M={MathNode:Ht,TextNode:Lt,SpaceNode:((u=Dt.prototype).toNode=function(){if(this.character)return document.createTextNode(this.character);var e=document.createElementNS("http://www.w3.org/1998/Math/MathML","mspace");return e.setAttribute("width",Q(this.width)),e},u.toMarkup=function(){return this.character?""+this.character+"":''},u.toText=function(){return this.character||" "},Dt),newDocumentFragment:qt},z=function(e,t){if(!e)return new M.MathNode("mrow");if(gt[e.type])return gt[e.type](e,t);throw new $("Got group of unknown type: '"+e.type+"'")};function Dt(e){this.width=void 0,this.character=void 0,this.width=e,this.character=.05555<=e&&e<=.05556?" ":.1666<=e&&e<=.1667?" ":.2222<=e&&e<=.2223?" ":.2777<=e&&e<=.2778?"  ":-.05556<=e&&e<=-.05555?" ⁣":-.1667<=e&&e<=-.1666?" ⁣":-.2223<=e&&e<=-.2222?" ⁣":-.2778<=e&&e<=-.2777?" ⁣":null}function Pt(e){this.text=void 0,this.text=e}function Ft(e,t,r){this.type=void 0,this.attributes=void 0,this.children=void 0,this.classes=void 0,this.type=e,this.attributes={},this.children=t||[],this.classes=r||[]}function Vt(e,t,r,n,i){e=S(e,r),r=1===e.length&&e[0]instanceof Ht&&Z.contains(["mrow","mtable"],e[0].type)?e[0]:new M.MathNode("mrow",e),e=new M.MathNode("annotation",[new M.TextNode(t)]),e.setAttribute("encoding","application/x-tex"),t=new M.MathNode("semantics",[r,e]),r=new M.MathNode("math",[t]);return r.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),n&&r.setAttribute("display","block"),ee.makeSpan([i?"katex":"katex-mathml"],[r])}function Gt(e){return(e=new M.MathNode("mo",[new M.TextNode(Wt[e.replace(/^\\/,"")])])).setAttribute("stretchy","true"),e}function Ut(f,g){var e=(r=function(){var e,t=4e5,r=f.label.substr(1);if(Z.contains(["widehat","widecheck","widetilde","utilde"],r))return a=5<(a="ordgroup"===(a=f.base).type?a.body.length:1)?"widehat"===r||"widecheck"===r?(s=420,t=2364,e=.42,r+"4"):(s=312,t=2340,e=.34,"tilde4"):(a=[1,1,2,2,3,3][a],"widehat"===r||"widecheck"===r?(t=[0,1062,2364,2364,2364][a],s=[0,239,300,360,420][a],e=[0,.24,.3,.3,.36,.42][a],r+a):(t=[0,600,1033,2339,2340][a],s=[0,260,286,306,312][a],e=[0,.26,.286,.3,.306,.34][a],"tilde"+a)),a=new Be(a),a=new Te([a],{width:"100%",height:Q(e),viewBox:"0 0 "+t+" "+s,preserveAspectRatio:"none"}),{span:ee.makeSvgSpan([],[a],g),minWidth:0,height:e};var n,i,a,o=[],s=jt[r],l=s[0],h=s[1],m=s[2],c=m/1e3,u=l.length;if(1===u)n=["hide-tail"],i=[s[3]];else if(2===u)n=["halfarrow-left","halfarrow-right"],i=["xMinYMin","xMaxYMin"];else{if(3!==u)throw new Error("Correct katexImagesData or update code here to support\n "+u+" children.");n=["brace-left","brace-center","brace-right"],i=["xMinYMin","xMidYMin","xMaxYMin"]}for(var p=0;p but got "+String(e)+".")}(re(e,t)),e.base=r):s=(r=A(e,"accent")).base;var r,n,e=re(s,t.havingCrampedStyle()),i=0;r.isShifty&&Z.isCharacterBox(s)&&(s=Z.getBaseElem(s),i=Le(re(s,t.havingCrampedStyle())).skew);var a,o,s="\\c"===r.label,l=s?e.height+e.depth:Math.min(e.height,t.fontMetrics().xHeight),h=r.isStretchy?(h=Ut(r,t),ee.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:e},{type:"elem",elem:h,wrapperClasses:["svg-align"],wrapperStyle:0":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"});w({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler:function(e,t){var r=e.parser,e=e.funcName;return{type:"cdlabel",mode:r.mode,side:e.slice(4),label:t[0]}},htmlBuilder:function(e,t){var r=t.havingStyle(t.style.sup()),r=ee.wrapFragment(re(e.label,r,t),t);return r.classes.push("cd-label-"+e.side),r.style.bottom=Q(.8-r.depth),r.height=0,r.depth=0,r},mathmlBuilder:function(e,t){t=new M.MathNode("mrow",[z(e.label,t)]);return(t=new M.MathNode("mpadded",[t])).setAttribute("width","0"),"left"===e.side&&t.setAttribute("lspace","-1width"),t.setAttribute("voffset","0.7em"),(t=new M.MathNode("mstyle",[t])).setAttribute("displaystyle","false"),t.setAttribute("scriptlevel","1"),t}}),w({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler:function(e,t){return{type:"cdlabelparent",mode:e.parser.mode,fragment:t[0]}},htmlBuilder:function(e,t){e=ee.wrapFragment(re(e.fragment,t),t);return e.classes.push("cd-vert-arrow"),e},mathmlBuilder:function(e,t){return new M.MathNode("mrow",[z(e.fragment,t)])}}),w({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){for(var e=e.parser,r=A(t[0],"ordgroup").body,n="",i=0;i>10),56320+(1023&t))),{type:"textord",mode:e.mode,text:t}}});function r0(e,t){return t=te(e.body,t.withColor(e.color),!1),ee.makeFragment(t)}function n0(e,t){return t=S(e.body,t.withColor(e.color)),(t=new M.MathNode("mstyle",t)).setAttribute("mathcolor",e.color),t}function i0(e){var t=e.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(t))throw new $("Expected a control sequence",e);return t}function a0(e,t,r,n){var i=e.gullet.macros.get(r.text);null==i&&(r.noexpand=!0,i={tokens:[r],numArgs:0,unexpandable:!e.gullet.isExpandable(r.text)}),e.gullet.macros.set(t,i,n)}function o0(e,t,r){if(r=he(p.math[e]&&p.math[e].replace||e,t,r))return r;throw new Error("Unsupported symbol "+e+" and font size "+t+".")}function s0(e,t,r,n){return t=r.havingBaseStyle(t),n=ee.makeSpan(n.concat(t.sizingClasses(r)),[e],r),e=t.sizeMultiplier/r.sizeMultiplier,n.height*=e,n.depth*=e,n.maxFontSize=t.sizeMultiplier,n}function l0(e,t,r){r=t.havingBaseStyle(r),r=(1-t.sizeMultiplier/r.sizeMultiplier)*t.fontMetrics().axisHeight,e.classes.push("delimcenter"),e.style.top=Q(r),e.height-=r,e.depth+=r}function h0(e,t,r,n,i,a){return e=ee.makeSymbol(e,"Size"+t+"-Regular",i,n),i=s0(ee.makeSpan(["delimsizing","size"+t],[e],n),K.TEXT,n,a),r&&l0(i,n,K.TEXT),i}function m0(e,t,r){return{type:"elem",elem:ee.makeSpan(["delimsizinginner","Size1-Regular"===t?"delim-size1":"delim-size4"],[ee.makeSpan([],[ee.makeSymbol(e,t,r)])])}}function c0(e,t,r){var n=(ae["Size4-Regular"][e.charCodeAt(0)]?ae["Size4-Regular"]:ae["Size1-Regular"])[e.charCodeAt(0)][4],e=new Be("inner",function(e,t){switch(e){case"⎜":return"M291 0 H417 V"+t+" H291z M291 0 H417 V"+t+" H291z";case"∣":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145z";case"∥":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145zM367 0 H410 V"+t+" H367z M367 0 H410 V"+t+" H367z";case"⎟":return"M457 0 H583 V"+t+" H457z M457 0 H583 V"+t+" H457z";case"⎢":return"M319 0 H403 V"+t+" H319z M319 0 H403 V"+t+" H319z";case"⎥":return"M263 0 H347 V"+t+" H263z M263 0 H347 V"+t+" H263z";case"⎪":return"M384 0 H504 V"+t+" H384z M384 0 H504 V"+t+" H384z";case"⏐":return"M312 0 H355 V"+t+" H312z M312 0 H355 V"+t+" H312z";case"‖":return"M257 0 H300 V"+t+" H257z M257 0 H300 V"+t+" H257zM478 0 H521 V"+t+" H478z M478 0 H521 V"+t+" H478z";default:return""}}(e,Math.round(1e3*t))),e=new Te([e],{width:Q(n),height:Q(t),style:"width:"+Q(n),viewBox:"0 0 "+1e3*n+" "+Math.round(1e3*t),preserveAspectRatio:"xMinYMin"});return(e=ee.makeSvgSpan([],[e],r)).height=t,e.style.height=Q(t),e.style.width=Q(n),{type:"elem",elem:e}}function u0(e,t,r,n,i,a){var o,s=o=f=e,l=null,h="Size1-Regular";"\\uparrow"===e?o=f="⏐":"\\Uparrow"===e?o=f="‖":"\\downarrow"===e?s=o="⏐":"\\Downarrow"===e?s=o="‖":"\\updownarrow"===e?(s="\\uparrow",o="⏐",f="\\downarrow"):"\\Updownarrow"===e?(s="\\Uparrow",o="‖",f="\\Downarrow"):Z.contains(b0,e)?o="∣":Z.contains(x0,e)?o="∥":"["===e||"\\lbrack"===e?(s="⎡",o="⎢",f="⎣",h="Size4-Regular"):"]"===e||"\\rbrack"===e?(s="⎤",o="⎥",f="⎦",h="Size4-Regular"):"\\lfloor"===e||"⌊"===e?(o=s="⎢",f="⎣",h="Size4-Regular"):"\\lceil"===e||"⌈"===e?(s="⎡",o=f="⎢",h="Size4-Regular"):"\\rfloor"===e||"⌋"===e?(o=s="⎥",f="⎦",h="Size4-Regular"):"\\rceil"===e||"⌉"===e?(s="⎤",o=f="⎥",h="Size4-Regular"):"("===e||"\\lparen"===e?(s="⎛",o="⎜",f="⎝",h="Size4-Regular"):")"===e||"\\rparen"===e?(s="⎞",o="⎟",f="⎠",h="Size4-Regular"):"\\{"===e||"\\lbrace"===e?(s="⎧",l="⎨",f="⎩",o="⎪",h="Size4-Regular"):"\\}"===e||"\\rbrace"===e?(s="⎫",l="⎬",f="⎭",o="⎪",h="Size4-Regular"):"\\lgroup"===e||"⟮"===e?(s="⎧",f="⎩",o="⎪",h="Size4-Regular"):"\\rgroup"===e||"⟯"===e?(s="⎫",f="⎭",o="⎪",h="Size4-Regular"):"\\lmoustache"===e||"⎰"===e?(s="⎧",f="⎭",o="⎪",h="Size4-Regular"):"\\rmoustache"!==e&&"⎱"!==e||(s="⎫",f="⎩",o="⎪",h="Size4-Regular");var e=(e=o0(s,h,i)).height+e.depth,m=(m=o0(o,h,i)).height+m.depth,c=(c=o0(f,h,i)).height+c.depth,u=0,p=1;null!==l&&(u=(d=o0(l,h,i)).height+d.depth,p=2);var t=(d=e+c+u)+Math.max(0,Math.ceil((t-d)/(p*m)))*p*m,d=n.fontMetrics().axisHeight,p=(r&&(d*=n.sizeMultiplier),t/2-d),d=((m=[]).push(m0(f,h,i)),m.push(y0),null===l?m.push(c0(o,t-e-c+.016,n)):(m.push(c0(o,r=(t-e-c-u)/2+.016,n)),m.push(y0),m.push(m0(l,h,i)),m.push(y0),m.push(c0(o,r,n))),m.push(y0),m.push(m0(s,h,i)),n.havingBaseStyle(K.TEXT)),f=ee.makeVList({positionType:"bottom",positionData:p,children:m},d);return s0(ee.makeSpan(["delimsizing","mult"],[f],d),K.TEXT,n,a)}function p0(n,e,t,r,i){return r=function(e,t){e*=1e3;var r="";switch(n){case"sqrtMain":r="M95,"+(622+e+80)+"\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl"+e/2.075+" -"+e+"\nc5.3,-9.3,12,-14,20,-14\nH400000v"+(40+e)+"H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM"+(834+e)+" 80h400000v"+(40+e)+"h-400000z";break;case"sqrtSize1":r="M263,"+(601+e+80)+"c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl"+e/2.084+" -"+e+"\nc4.7,-7.3,11,-11,19,-11\nH40000v"+(40+e)+"H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM"+(1001+e)+" 80h400000v"+(40+e)+"h-400000z";break;case"sqrtSize2":r="M983 "+(10+e+80)+"\nl"+e/3.13+" -"+e+"\nc4,-6.7,10,-10,18,-10 H400000v"+(40+e)+"\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM"+(1001+e)+" 80h400000v"+(40+e)+"h-400000z";break;case"sqrtSize3":r="M424,"+(2398+e+80)+"\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl"+e/4.223+" -"+e+"c4,-6.7,10,-10,18,-10 H400000\nv"+(40+e)+"H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M"+(1001+e)+" 80\nh400000v"+(40+e)+"h-400000z";break;case"sqrtSize4":r="M473,"+(2713+e+80)+"\nc339.3,-1799.3,509.3,-2700,510,-2702 l"+e/5.298+" -"+e+"\nc3.3,-7.3,9.3,-11,18,-11 H400000v"+(40+e)+"H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM"+(1001+e)+" 80h400000v"+(40+e)+"H1017.7z";break;case"sqrtTall":r="M702 "+(80+e)+"H400000"+(40+e)+"\nH742v"+(t-54-80-e)+"l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 80H400000v"+(40+e)+"H742z"}return r}(r,t),r=new Be(n,r),r=new Te([r],{width:"400em",height:Q(e),viewBox:"0 0 400000 "+t,preserveAspectRatio:"xMinYMin slice"}),ee.makeSvgSpan(["hide-tail"],[r],i)}function d0(e,t,r,n){for(var i=Math.min(2,3-n.style.size);i"!==e&&"\\gt"!==e&&"⟩"!==e||(e="\\rangle"),c=Z.contains(k0,e)?M0:Z.contains(v0,e)?A0:z0;var o,s,l,h,m,c=d0(e,t,c,n);return"small"===c.type?(o=e,s=c.style,l=r,h=n,m=a,o=ee.makeSymbol(o,"Main-Regular",i,h),o=s0(o,s,h,m),l&&l0(o,h,s),o):"large"===c.type?h0(e,c.size,r,n,i,a):u0(e,t,r,n,i,a)}w({type:"color",names:["\\textcolor"],props:{numArgs:2,allowedInText:!0,argTypes:["color","original"]},handler:function(e,t){var e=e.parser,r=A(t[0],"color-token").color,t=t[1];return{type:"color",mode:e.mode,color:r,body:k(t)}},htmlBuilder:r0,mathmlBuilder:n0}),w({type:"color",names:["\\color"],props:{numArgs:1,allowedInText:!0,argTypes:["color"]},handler:function(e,t){var r=e.parser,e=e.breakOnTokenText,t=A(t[0],"color-token").color,e=(r.gullet.macros.set("\\current@color",t),r.parseExpression(!0,e));return{type:"color",mode:r.mode,color:t,body:e}},htmlBuilder:r0,mathmlBuilder:n0}),w({type:"cr",names:["\\\\"],props:{numArgs:0,numOptionalArgs:1,argTypes:["size"],allowedInText:!0},handler:function(e,t,r){var e=e.parser,r=r[0],n=!e.settings.displayMode||!e.settings.useStrictBehavior("newLineInDisplayMode","In LaTeX, \\\\ or \\newline does nothing in display mode");return{type:"cr",mode:e.mode,newLine:n,size:r&&A(r,"size").value}},htmlBuilder:function(e,t){var r=ee.makeSpan(["mspace"],[],t);return e.newLine&&(r.classes.push("newline"),e.size&&(r.style.marginTop=Q(J(e.size,t)))),r},mathmlBuilder:function(e,t){var r=new M.MathNode("mspace");return e.newLine&&(r.setAttribute("linebreak","newline"),e.size&&r.setAttribute("height",Q(J(e.size,t)))),r}});var g0={"\\global":"\\global","\\long":"\\\\globallong","\\\\globallong":"\\\\globallong","\\def":"\\gdef","\\gdef":"\\gdef","\\edef":"\\xdef","\\xdef":"\\xdef","\\let":"\\\\globallet","\\futurelet":"\\\\globalfuture"},y0=(w({type:"internal",names:["\\global","\\long","\\\\globallong"],props:{numArgs:0,allowedInText:!0},handler:function(e){var t=e.parser,e=e.funcName,r=(t.consumeSpaces(),t.fetch());if(g0[r.text])return"\\global"!==e&&"\\\\globallong"!==e||(r.text=g0[r.text]),A(t.parseFunction(),"internal");throw new $("Invalid token after macro prefix",r)}}),w({type:"internal",names:["\\def","\\gdef","\\edef","\\xdef"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,e=e.funcName,r=t.gullet.popToken(),n=r.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(n))throw new $("Expected a control sequence",r);for(var i,a=0,o=[[]];"{"!==t.gullet.future().text;)if("#"===(r=t.gullet.popToken()).text){if("{"===t.gullet.future().text){i=t.gullet.future(),o[a].push("{");break}if(r=t.gullet.popToken(),!/^[1-9]$/.test(r.text))throw new $('Invalid argument number "'+r.text+'"');if(parseInt(r.text)!==a+1)throw new $('Argument number "'+r.text+'" out of order');a++,o.push([])}else{if("EOF"===r.text)throw new $("Expected a macro definition");o[a].push(r.text)}var s=t.gullet.consumeArg().tokens;return i&&s.unshift(i),"\\edef"!==e&&"\\xdef"!==e||(s=t.gullet.expandTokens(s)).reverse(),t.gullet.macros.set(n,{tokens:s,numArgs:a,delimiters:o},e===g0[e]),{type:"internal",mode:t.mode}}}),w({type:"internal",names:["\\let","\\\\globallet"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t,r,n=e.parser,e=e.funcName,i=i0(n.gullet.popToken());n.gullet.consumeSpaces(),r="="===(r=(t=n).gullet.popToken()).text&&" "===(r=t.gullet.popToken()).text?t.gullet.popToken():r;return a0(n,i,r,"\\\\globallet"===e),{type:"internal",mode:n.mode}}}),w({type:"internal",names:["\\futurelet","\\\\globalfuture"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e){var t=e.parser,e=e.funcName,r=i0(t.gullet.popToken()),n=t.gullet.popToken(),i=t.gullet.popToken();return a0(t,r,i,"\\\\globalfuture"===e),t.gullet.pushToken(i),t.gullet.pushToken(n),{type:"internal",mode:t.mode}}}),{type:"kern",size:-.008}),b0=["|","\\lvert","\\rvert","\\vert"],x0=["\\|","\\lVert","\\rVert","\\Vert"],v0=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","⌊","⌋","\\lceil","\\rceil","⌈","⌉","\\surd"],w0=["\\uparrow","\\downarrow","\\updownarrow","\\Uparrow","\\Downarrow","\\Updownarrow","|","\\|","\\vert","\\Vert","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","⟮","⟯","\\lmoustache","\\rmoustache","⎰","⎱"],k0=["<",">","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"],S0=[0,1.2,1.8,2.4,3],M0=[{type:"small",style:K.SCRIPTSCRIPT},{type:"small",style:K.SCRIPT},{type:"small",style:K.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}],z0=[{type:"small",style:K.SCRIPTSCRIPT},{type:"small",style:K.SCRIPT},{type:"small",style:K.TEXT},{type:"stack"}],A0=[{type:"small",style:K.SCRIPTSCRIPT},{type:"small",style:K.SCRIPT},{type:"small",style:K.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}],T0={sqrtImage:function(e,t){var r,n=t.havingBaseSizing(),i=d0("\\surd",e*n.sizeMultiplier,A0,n),n=n.sizeMultiplier,a=Math.max(0,t.minRuleThickness-t.fontMetrics().sqrtRuleThickness),o=0,s=0,l=0,i="small"===i.type?(e<1?n=1:e<1.4&&(n=.7),s=(1+a)/n,(r=p0("sqrtMain",o=(1+a+.08)/n,l=1e3+1e3*a+80,a,t)).style.minWidth="0.853em",.833/n):"large"===i.type?(l=1080*S0[i.size],s=(S0[i.size]+a)/n,o=(S0[i.size]+a+.08)/n,(r=p0("sqrtSize"+i.size,o,l,a,t)).style.minWidth="1.02em",1/n):(o=e+a+.08,s=e+a,l=Math.floor(1e3*e+a)+80,(r=p0("sqrtTall",o,l,a,t)).style.minWidth="0.742em",1.056);return r.height=s,r.style.height=Q(o),{span:r,advanceWidth:i,ruleWidth:(t.fontMetrics().sqrtRuleThickness+a)*n}},sizedDelim:function(e,t,r,n,i){if("<"===e||"\\lt"===e||"⟨"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"⟩"!==e||(e="\\rangle"),Z.contains(v0,e)||Z.contains(k0,e))return h0(e,t,!1,r,n,i);if(Z.contains(w0,e))return u0(e,S0[t],!1,r,n,i);throw new $("Illegal delimiter: '"+e+"'")},sizeToMaxHeight:S0,customSizedDelim:f0,leftRightDelim:function(e,t,r,n,i,a){var o=n.fontMetrics().axisHeight*n.sizeMultiplier,s=5/n.fontMetrics().ptPerEm,t=Math.max(t-o,r+o),r=Math.max(t/500*901,2*t-s);return f0(e,r,!0,n,i,a)}},B0={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},C0=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","⌊","⌋","\\lceil","\\rceil","⌈","⌉","<",">","\\langle","⟨","\\rangle","⟩","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","⟮","⟯","\\lmoustache","\\rmoustache","⎰","⎱","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];function N0(e,t){var r=$t(e);if(r&&Z.contains(C0,r.text))return r;throw new $(r?"Invalid delimiter '"+r.text+"' after '"+t.funcName+"'":"Invalid delimiter type '"+e.type+"'",e)}function q0(e){if(!e.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}w({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:function(e,t){t=N0(t[0],e);return{type:"delimsizing",mode:e.parser.mode,size:B0[e.funcName].size,mclass:B0[e.funcName].mclass,delim:t.text}},htmlBuilder:function(e,t){return"."===e.delim?ee.makeSpan([e.mclass]):T0.sizedDelim(e.delim,e.size,t,e.mode,[e.mclass])},mathmlBuilder:function(e){var t=[],t=("."!==e.delim&&t.push(It(e.delim,e.mode)),new M.MathNode("mo",t)),e=("mopen"===e.mclass||"mclose"===e.mclass?t.setAttribute("fence","true"):t.setAttribute("fence","false"),t.setAttribute("stretchy","true"),Q(T0.sizeToMaxHeight[e.size]));return t.setAttribute("minsize",e),t.setAttribute("maxsize",e),t}}),w({type:"leftright-right",names:["\\right"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser.gullet.macros.get("\\current@color");if(r&&"string"!=typeof r)throw new $("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:e.parser.mode,delim:N0(t[0],e).text,color:r}}}),w({type:"leftright",names:["\\left"],props:{numArgs:1,primitive:!0},handler:function(e,t){var t=N0(t[0],e),e=e.parser,r=(++e.leftrightDepth,e.parseExpression(!1)),n=(--e.leftrightDepth,e.expect("\\right",!1),A(e.parseFunction(),"leftright-right"));return{type:"leftright",mode:e.mode,body:r,left:t.text,right:n.delim,rightColor:n.color}},htmlBuilder:function(e,t){q0(e);for(var r,n=te(e.body,t,!0,["mopen","mclose"]),i=0,a=0,o=!1,s=0;sAV".indexOf(c)))throw new $('Expected one of "<>AV=|." after @',l[m]);for(var p=0;p<2;p++){for(var d=!0,f=m+1;f=K.SCRIPT.id?t.text():K.DISPLAY:"text"===e&&t.size===K.DISPLAY.size?t=K.TEXT:"script"===e?t=K.SCRIPT:"scriptscript"===e&&(t=K.SCRIPTSCRIPT),t}function ir(e,t){var r=nr(e.size,t.style),n=r.fracNum(),i=r.fracDen(),n=t.havingStyle(n),a=re(e.numer,n,t);e.continued&&(m=8.5/t.fontMetrics().ptPerEm,c=3.5/t.fontMetrics().ptPerEm,a.height=a.heightr.height+r.depth+i&&(i=(i+s-r.height-r.depth)/2),a.height-r.height-i-o),i=(r.style.paddingLeft=Q(n),ee.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r,wrapperClasses:["svg-align"]},{type:"kern",size:-(r.height+s)},{type:"elem",elem:a},{type:"kern",size:o}]},t));return e.index?(n=t.havingStyle(K.SCRIPTSCRIPT),r=re(e.index,n,t),s=.6*(i.height-i.depth),a=ee.makeVList({positionType:"shift",positionData:-s,children:[{type:"elem",elem:r}]},t),o=ee.makeSpan(["root"],[a]),ee.makeSpan(["mord","sqrt"],[o,i],t)):ee.makeSpan(["mord","sqrt"],[i],t)},mathmlBuilder:function(e,t){var r=e.body,e=e.index;return e?new M.MathNode("mroot",[z(r,t),z(e,t)]):new M.MathNode("msqrt",[z(r,t)])}}),{display:K.DISPLAY,text:K.TEXT,script:K.SCRIPT,scriptscript:K.SCRIPTSCRIPT}),Mr=(w({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,e=e.parser,r=e.parseExpression(!0,r),n=n.slice(1,n.length-5);return{type:"styling",mode:e.mode,style:n,body:r}},htmlBuilder:function(e,t){var r=Sr[e.style],r=t.havingStyle(r).withFont("");return xr(e.body,r,t)},mathmlBuilder:function(e,t){var r=Sr[e.style],t=t.havingStyle(r),r=S(e.body,t),t=new M.MathNode("mstyle",r),r={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]}[e.style];return t.setAttribute("scriptlevel",r[0]),t.setAttribute("displaystyle",r[1]),t}}),yt({type:"supsub",htmlBuilder:function(e,t){r=t;var r=(o=(a=e).base)?"op"===o.type?o.limits&&(r.style.size===K.DISPLAY.size||o.alwaysHandleSupSub)?cr:null:"operatorname"===o.type?o.alwaysHandleSupSub&&(r.style.size===K.DISPLAY.size||o.limits)?pr:null:"accent"===o.type?Z.isCharacterBox(o.base)?Zt:null:"horizBrace"===o.type&&!a.sub===o.isOver?sr:null:null;if(r)return r(e,t);var n,i,a=e.base,o=e.sup,r=e.sub,s=re(a,t),l=t.fontMetrics(),h=0,m=0,a=a&&Z.isCharacterBox(a),c=(o&&(c=t.havingStyle(t.style.sup()),n=re(o,c,t),a||(h=s.height-c.fontMetrics().supDrop*c.sizeMultiplier/t.sizeMultiplier)),r&&(o=t.havingStyle(t.style.sub()),i=re(r,o,t),a||(m=s.depth+o.fontMetrics().subDrop*o.sizeMultiplier/t.sizeMultiplier)),t.style===K.DISPLAY?l.sup1:t.style.cramped?l.sup3:l.sup2),r=t.sizeMultiplier,a=Q(.5/l.ptPerEm/r),o=null;if(i&&(r=e.base&&"op"===e.base.type&&e.base.name&&("\\oiint"===e.base.name||"\\oiiint"===e.base.name),(s instanceof b||r)&&(o=Q(-s.italic))),n&&i){h=Math.max(h,c,n.depth+.25*l.xHeight),m=Math.max(m,l.sub2);e=4*l.defaultRuleThickness;h-n.depth-(i.height-m)":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"}),Gr=(T("\\dots",function(e){var t="\\dotso",e=e.expandAfterFuture().text;return e in Vr?t=Vr[e]:("\\not"===e.substr(0,4)||e in p.math&&Z.contains(["bin","rel"],p.math[e].group))&&(t="\\dotsb"),t}),{")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0}),e=(T("\\dotso",function(e){return e.future().text in Gr?"\\ldots\\,":"\\ldots"}),T("\\dotsc",function(e){e=e.future().text;return e in Gr&&","!==e?"\\ldots\\,":"\\ldots"}),T("\\cdots",function(e){return e.future().text in Gr?"\\@cdots\\,":"\\@cdots"}),T("\\dotsb","\\cdots"),T("\\dotsm","\\cdots"),T("\\dotsi","\\!\\cdots"),T("\\dotsx","\\ldots\\,"),T("\\DOTSI","\\relax"),T("\\DOTSB","\\relax"),T("\\DOTSX","\\relax"),T("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),T("\\,","\\tmspace+{3mu}{.1667em}"),T("\\thinspace","\\,"),T("\\>","\\mskip{4mu}"),T("\\:","\\tmspace+{4mu}{.2222em}"),T("\\medspace","\\:"),T("\\;","\\tmspace+{5mu}{.2777em}"),T("\\thickspace","\\;"),T("\\!","\\tmspace-{3mu}{.1667em}"),T("\\negthinspace","\\!"),T("\\negmedspace","\\tmspace-{4mu}{.2222em}"),T("\\negthickspace","\\tmspace-{5mu}{.277em}"),T("\\enspace","\\kern.5em "),T("\\enskip","\\hskip.5em\\relax"),T("\\quad","\\hskip1em\\relax"),T("\\qquad","\\hskip2em\\relax"),T("\\tag","\\@ifstar\\tag@literal\\tag@paren"),T("\\tag@paren","\\tag@literal{({#1})}"),T("\\tag@literal",function(e){if(e.macros.get("\\df@tag"))throw new $("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"}),T("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),T("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),T("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),T("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),T("\\pmb","\\html@mathml{\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}{\\mathbf{#1}}"),T("\\newline","\\\\\\relax"),T("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}"),Q(ae["Main-Regular"]["T".charCodeAt(0)][1]-.7*ae["Main-Regular"]["A".charCodeAt(0)][1])),Ur=(T("\\LaTeX","\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{"+e+"}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),T("\\KaTeX","\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{"+e+"}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),T("\\hspace","\\@ifstar\\@hspacer\\@hspace"),T("\\@hspace","\\hskip #1\\relax"),T("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),T("\\ordinarycolon",":"),T("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}"),T("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'),T("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'),T("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'),T("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'),T("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'),T("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'),T("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'),T("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'),T("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'),T("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'),T("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'),T("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'),T("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'),T("∷","\\dblcolon"),T("∹","\\eqcolon"),T("≔","\\coloneqq"),T("≕","\\eqqcolon"),T("⩴","\\Coloneqq"),T("\\ratio","\\vcentcolon"),T("\\coloncolon","\\dblcolon"),T("\\colonequals","\\coloneqq"),T("\\coloncolonequals","\\Coloneqq"),T("\\equalscolon","\\eqqcolon"),T("\\equalscoloncolon","\\Eqqcolon"),T("\\colonminus","\\coloneq"),T("\\coloncolonminus","\\Coloneq"),T("\\minuscolon","\\eqcolon"),T("\\minuscoloncolon","\\Eqcolon"),T("\\coloncolonapprox","\\Colonapprox"),T("\\coloncolonsim","\\Colonsim"),T("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),T("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),T("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),T("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),T("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`∌}}"),T("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),T("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),T("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),T("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),T("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}"),T("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}"),T("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),T("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),T("\\gvertneqq","\\html@mathml{\\@gvertneqq}{≩}"),T("\\lvertneqq","\\html@mathml{\\@lvertneqq}{≨}"),T("\\ngeqq","\\html@mathml{\\@ngeqq}{≱}"),T("\\ngeqslant","\\html@mathml{\\@ngeqslant}{≱}"),T("\\nleqq","\\html@mathml{\\@nleqq}{≰}"),T("\\nleqslant","\\html@mathml{\\@nleqslant}{≰}"),T("\\nshortmid","\\html@mathml{\\@nshortmid}{∤}"),T("\\nshortparallel","\\html@mathml{\\@nshortparallel}{∦}"),T("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{⊈}"),T("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{⊉}"),T("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{⊊}"),T("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{⫋}"),T("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{⊋}"),T("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{⫌}"),T("\\imath","\\html@mathml{\\@imath}{ı}"),T("\\jmath","\\html@mathml{\\@jmath}{ȷ}"),T("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`⟦}}"),T("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`⟧}}"),T("⟦","\\llbracket"),T("⟧","\\rrbracket"),T("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`⦃}}"),T("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`⦄}}"),T("⦃","\\lBrace"),T("⦄","\\rBrace"),T("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`⦵}}"),T("⦵","\\minuso"),T("\\darr","\\downarrow"),T("\\dArr","\\Downarrow"),T("\\Darr","\\Downarrow"),T("\\lang","\\langle"),T("\\rang","\\rangle"),T("\\uarr","\\uparrow"),T("\\uArr","\\Uparrow"),T("\\Uarr","\\Uparrow"),T("\\N","\\mathbb{N}"),T("\\R","\\mathbb{R}"),T("\\Z","\\mathbb{Z}"),T("\\alef","\\aleph"),T("\\alefsym","\\aleph"),T("\\Alpha","\\mathrm{A}"),T("\\Beta","\\mathrm{B}"),T("\\bull","\\bullet"),T("\\Chi","\\mathrm{X}"),T("\\clubs","\\clubsuit"),T("\\cnums","\\mathbb{C}"),T("\\Complex","\\mathbb{C}"),T("\\Dagger","\\ddagger"),T("\\diamonds","\\diamondsuit"),T("\\empty","\\emptyset"),T("\\Epsilon","\\mathrm{E}"),T("\\Eta","\\mathrm{H}"),T("\\exist","\\exists"),T("\\harr","\\leftrightarrow"),T("\\hArr","\\Leftrightarrow"),T("\\Harr","\\Leftrightarrow"),T("\\hearts","\\heartsuit"),T("\\image","\\Im"),T("\\infin","\\infty"),T("\\Iota","\\mathrm{I}"),T("\\isin","\\in"),T("\\Kappa","\\mathrm{K}"),T("\\larr","\\leftarrow"),T("\\lArr","\\Leftarrow"),T("\\Larr","\\Leftarrow"),T("\\lrarr","\\leftrightarrow"),T("\\lrArr","\\Leftrightarrow"),T("\\Lrarr","\\Leftrightarrow"),T("\\Mu","\\mathrm{M}"),T("\\natnums","\\mathbb{N}"),T("\\Nu","\\mathrm{N}"),T("\\Omicron","\\mathrm{O}"),T("\\plusmn","\\pm"),T("\\rarr","\\rightarrow"),T("\\rArr","\\Rightarrow"),T("\\Rarr","\\Rightarrow"),T("\\real","\\Re"),T("\\reals","\\mathbb{R}"),T("\\Reals","\\mathbb{R}"),T("\\Rho","\\mathrm{P}"),T("\\sdot","\\cdot"),T("\\sect","\\S"),T("\\spades","\\spadesuit"),T("\\sub","\\subset"),T("\\sube","\\subseteq"),T("\\supe","\\supseteq"),T("\\Tau","\\mathrm{T}"),T("\\thetasym","\\vartheta"),T("\\weierp","\\wp"),T("\\Zeta","\\mathrm{Z}"),T("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),T("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),T("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),T("\\bra","\\mathinner{\\langle{#1}|}"),T("\\ket","\\mathinner{|{#1}\\rangle}"),T("\\braket","\\mathinner{\\langle{#1}\\rangle}"),T("\\Bra","\\left\\langle#1\\right|"),T("\\Ket","\\left|#1\\right\\rangle"),T("\\bra@ket",Pr(!1)),T("\\bra@set",Pr(!0)),T("\\Braket","\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}"),T("\\Set","\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}"),T("\\set","\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}"),T("\\angln","{\\angl n}"),T("\\blue","\\textcolor{##6495ed}{#1}"),T("\\orange","\\textcolor{##ffa500}{#1}"),T("\\pink","\\textcolor{##ff00af}{#1}"),T("\\red","\\textcolor{##df0030}{#1}"),T("\\green","\\textcolor{##28ae7b}{#1}"),T("\\gray","\\textcolor{gray}{#1}"),T("\\purple","\\textcolor{##9d38bd}{#1}"),T("\\blueA","\\textcolor{##ccfaff}{#1}"),T("\\blueB","\\textcolor{##80f6ff}{#1}"),T("\\blueC","\\textcolor{##63d9ea}{#1}"),T("\\blueD","\\textcolor{##11accd}{#1}"),T("\\blueE","\\textcolor{##0c7f99}{#1}"),T("\\tealA","\\textcolor{##94fff5}{#1}"),T("\\tealB","\\textcolor{##26edd5}{#1}"),T("\\tealC","\\textcolor{##01d1c1}{#1}"),T("\\tealD","\\textcolor{##01a995}{#1}"),T("\\tealE","\\textcolor{##208170}{#1}"),T("\\greenA","\\textcolor{##b6ffb0}{#1}"),T("\\greenB","\\textcolor{##8af281}{#1}"),T("\\greenC","\\textcolor{##74cf70}{#1}"),T("\\greenD","\\textcolor{##1fab54}{#1}"),T("\\greenE","\\textcolor{##0d923f}{#1}"),T("\\goldA","\\textcolor{##ffd0a9}{#1}"),T("\\goldB","\\textcolor{##ffbb71}{#1}"),T("\\goldC","\\textcolor{##ff9c39}{#1}"),T("\\goldD","\\textcolor{##e07d10}{#1}"),T("\\goldE","\\textcolor{##a75a05}{#1}"),T("\\redA","\\textcolor{##fca9a9}{#1}"),T("\\redB","\\textcolor{##ff8482}{#1}"),T("\\redC","\\textcolor{##f9685d}{#1}"),T("\\redD","\\textcolor{##e84d39}{#1}"),T("\\redE","\\textcolor{##bc2612}{#1}"),T("\\maroonA","\\textcolor{##ffbde0}{#1}"),T("\\maroonB","\\textcolor{##ff92c6}{#1}"),T("\\maroonC","\\textcolor{##ed5fa6}{#1}"),T("\\maroonD","\\textcolor{##ca337c}{#1}"),T("\\maroonE","\\textcolor{##9e034e}{#1}"),T("\\purpleA","\\textcolor{##ddd7ff}{#1}"),T("\\purpleB","\\textcolor{##c6b9fc}{#1}"),T("\\purpleC","\\textcolor{##aa87ff}{#1}"),T("\\purpleD","\\textcolor{##7854ab}{#1}"),T("\\purpleE","\\textcolor{##543b78}{#1}"),T("\\mintA","\\textcolor{##f5f9e8}{#1}"),T("\\mintB","\\textcolor{##edf2df}{#1}"),T("\\mintC","\\textcolor{##e0e5cc}{#1}"),T("\\grayA","\\textcolor{##f6f7f7}{#1}"),T("\\grayB","\\textcolor{##f0f1f2}{#1}"),T("\\grayC","\\textcolor{##e3e5e6}{#1}"),T("\\grayD","\\textcolor{##d6d8da}{#1}"),T("\\grayE","\\textcolor{##babec2}{#1}"),T("\\grayF","\\textcolor{##888d93}{#1}"),T("\\grayG","\\textcolor{##626569}{#1}"),T("\\grayH","\\textcolor{##3b3e40}{#1}"),T("\\grayI","\\textcolor{##21242c}{#1}"),T("\\kaBlue","\\textcolor{##314453}{#1}"),T("\\kaGreen","\\textcolor{##71B307}{#1}"),{"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0}),Yr=((t=Kr.prototype).feed=function(e){this.lexer=new Or(e,this.settings)},t.switchMode=function(e){this.mode=e},t.beginGroup=function(){this.macros.beginGroup()},t.endGroup=function(){this.macros.endGroup()},t.endGroups=function(){this.macros.endGroups()},t.future=function(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]},t.popToken=function(){return this.future(),this.stack.pop()},t.pushToken=function(e){this.stack.push(e)},t.pushTokens=function(e){var t;(t=this.stack).push.apply(t,e)},t.scanArgument=function(e){if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;var t=this.popToken(),e=this.consumeArg(["]"]),r=e.tokens,n=e.end}else{e=this.consumeArg();r=e.tokens,t=e.start,n=e.end}return this.pushToken(new D0("EOF",n.loc)),this.pushTokens(r),t.range(n,"")},t.consumeSpaces=function(){for(;" "===this.future().text;)this.stack.pop()},t.consumeArg=function(e){var t=[],r=e&&0this.settings.maxExpand)throw new $("Too many expansions: infinite loop or need to increase maxExpand setting");var i=n.tokens,a=this.consumeArgs(n.numArgs,n.delimiters);if(n.numArgs)for(var o=(i=i.slice()).length-1;0<=o;--o){var s=i[o];if("#"===s.text){if(0===o)throw new $("Incomplete placeholder at end of macro body",s);if("#"===(s=i[--o]).text)i.splice(o+1,1);else{if(!/^[1-9]$/.test(s.text))throw new $("Not a valid argument number",s);i.splice.apply(i,[o,2].concat(a[+s.text-1]))}}}return this.pushTokens(i),i},t.expandAfterFuture=function(){return this.expandOnce(),this.future()},t.expandNextToken=function(){for(;;){var e=this.expandOnce();if(e instanceof D0)return e.treatAsRelax&&(e.text="\\relax"),this.stack.pop()}throw new Error},t.expandMacro=function(e){return this.macros.has(e)?this.expandTokens([new D0(e)]):void 0},t.expandTokens=function(e){var t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;){var n=this.expandOnce(!0);n instanceof D0&&(n.treatAsRelax&&(n.noexpand=!1,n.treatAsRelax=!1),t.push(this.stack.pop()))}return t},t.expandMacroAsText=function(e){e=this.expandMacro(e);return e&&e.map(function(e){return e.text}).join("")},t._getExpansion=function(e){var t=this.macros.get(e);if(null==t)return t;if(1===e.length){e=this.lexer.catcodes[e];if(null!=e&&13!==e)return}e="function"==typeof t?t(this):t;if("string"!=typeof e)return e;var r=0;if(-1!==e.indexOf("#"))for(var n=e.replace(/##/g,"");-1!==n.indexOf("#"+(r+1));)++r;for(var i=new Or(e,this.settings),a=[],o=i.lex();"EOF"!==o.text;)a.push(o),o=i.lex();return a.reverse(),{tokens:a,numArgs:r}},t.isDefined=function(e){return this.macros.has(e)||qr.hasOwnProperty(e)||p.math.hasOwnProperty(e)||p.text.hasOwnProperty(e)||Ur.hasOwnProperty(e)},t.isExpandable=function(e){var t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:qr.hasOwnProperty(e)&&!qr[e].primitive},Kr),Xr=/^[\u208a\u208b\u208c\u208d\u208e\u2080\u2081\u2082\u2083\u2084\u2085\u2086\u2087\u2088\u2089\u2090\u2091\u2095\u1d62\u2c7c\u2096\u2097\u2098\u2099\u2092\u209a\u1d63\u209b\u209c\u1d64\u1d65\u2093\u1d66\u1d67\u1d68\u1d69\u1d6a]/,Wr=Object.freeze({"₊":"+","₋":"-","₌":"=","₍":"(","₎":")","₀":"0","₁":"1","₂":"2","₃":"3","₄":"4","₅":"5","₆":"6","₇":"7","₈":"8","₉":"9","ₐ":"a","ₑ":"e","ₕ":"h","ᵢ":"i","ⱼ":"j","ₖ":"k","ₗ":"l","ₘ":"m","ₙ":"n","ₒ":"o","ₚ":"p","ᵣ":"r","ₛ":"s","ₜ":"t","ᵤ":"u","ᵥ":"v","ₓ":"x","ᵦ":"β","ᵧ":"γ","ᵨ":"ρ","ᵩ":"ϕ","ᵪ":"χ","⁺":"+","⁻":"-","⁼":"=","⁽":"(","⁾":")","⁰":"0","¹":"1","²":"2","³":"3","⁴":"4","⁵":"5","⁶":"6","⁷":"7","⁸":"8","⁹":"9","ᴬ":"A","ᴮ":"B","ᴰ":"D","ᴱ":"E","ᴳ":"G","ᴴ":"H","ᴵ":"I","ᴶ":"J","ᴷ":"K","ᴸ":"L","ᴹ":"M","ᴺ":"N","ᴼ":"O","ᴾ":"P","ᴿ":"R","ᵀ":"T","ᵁ":"U","ⱽ":"V","ᵂ":"W","ᵃ":"a","ᵇ":"b","ᶜ":"c","ᵈ":"d","ᵉ":"e","ᶠ":"f","ᵍ":"g","ʰ":"h","ⁱ":"i","ʲ":"j","ᵏ":"k","ˡ":"l","ᵐ":"m","ⁿ":"n","ᵒ":"o","ᵖ":"p","ʳ":"r","ˢ":"s","ᵗ":"t","ᵘ":"u","ᵛ":"v","ʷ":"w","ˣ":"x","ʸ":"y","ᶻ":"z","ᵝ":"β","ᵞ":"γ","ᵟ":"δ","ᵠ":"ϕ","ᵡ":"χ","ᶿ":"θ"}),jr={"́":{text:"\\'",math:"\\acute"},"̀":{text:"\\`",math:"\\grave"},"̈":{text:'\\"',math:"\\ddot"},"̃":{text:"\\~",math:"\\tilde"},"̄":{text:"\\=",math:"\\bar"},"̆":{text:"\\u",math:"\\breve"},"̌":{text:"\\v",math:"\\check"},"̂":{text:"\\^",math:"\\hat"},"̇":{text:"\\.",math:"\\dot"},"̊":{text:"\\r",math:"\\mathring"},"̋":{text:"\\H"},"̧":{text:"\\c"}},_r={"á":"á","à":"à","ä":"ä","ǟ":"ǟ","ã":"ã","ā":"ā","ă":"ă","ắ":"ắ","ằ":"ằ","ẵ":"ẵ","ǎ":"ǎ","â":"â","ấ":"ấ","ầ":"ầ","ẫ":"ẫ","ȧ":"ȧ","ǡ":"ǡ","å":"å","ǻ":"ǻ","ḃ":"ḃ","ć":"ć","ḉ":"ḉ","č":"č","ĉ":"ĉ","ċ":"ċ","ç":"ç","ď":"ď","ḋ":"ḋ","ḑ":"ḑ","é":"é","è":"è","ë":"ë","ẽ":"ẽ","ē":"ē","ḗ":"ḗ","ḕ":"ḕ","ĕ":"ĕ","ḝ":"ḝ","ě":"ě","ê":"ê","ế":"ế","ề":"ề","ễ":"ễ","ė":"ė","ȩ":"ȩ","ḟ":"ḟ","ǵ":"ǵ","ḡ":"ḡ","ğ":"ğ","ǧ":"ǧ","ĝ":"ĝ","ġ":"ġ","ģ":"ģ","ḧ":"ḧ","ȟ":"ȟ","ĥ":"ĥ","ḣ":"ḣ","ḩ":"ḩ","í":"í","ì":"ì","ï":"ï","ḯ":"ḯ","ĩ":"ĩ","ī":"ī","ĭ":"ĭ","ǐ":"ǐ","î":"î","ǰ":"ǰ","ĵ":"ĵ","ḱ":"ḱ","ǩ":"ǩ","ķ":"ķ","ĺ":"ĺ","ľ":"ľ","ļ":"ļ","ḿ":"ḿ","ṁ":"ṁ","ń":"ń","ǹ":"ǹ","ñ":"ñ","ň":"ň","ṅ":"ṅ","ņ":"ņ","ó":"ó","ò":"ò","ö":"ö","ȫ":"ȫ","õ":"õ","ṍ":"ṍ","ṏ":"ṏ","ȭ":"ȭ","ō":"ō","ṓ":"ṓ","ṑ":"ṑ","ŏ":"ŏ","ǒ":"ǒ","ô":"ô","ố":"ố","ồ":"ồ","ỗ":"ỗ","ȯ":"ȯ","ȱ":"ȱ","ő":"ő","ṕ":"ṕ","ṗ":"ṗ","ŕ":"ŕ","ř":"ř","ṙ":"ṙ","ŗ":"ŗ","ś":"ś","ṥ":"ṥ","š":"š","ṧ":"ṧ","ŝ":"ŝ","ṡ":"ṡ","ş":"ş","ẗ":"ẗ","ť":"ť","ṫ":"ṫ","ţ":"ţ","ú":"ú","ù":"ù","ü":"ü","ǘ":"ǘ","ǜ":"ǜ","ǖ":"ǖ","ǚ":"ǚ","ũ":"ũ","ṹ":"ṹ","ū":"ū","ṻ":"ṻ","ŭ":"ŭ","ǔ":"ǔ","û":"û","ů":"ů","ű":"ű","ṽ":"ṽ","ẃ":"ẃ","ẁ":"ẁ","ẅ":"ẅ","ŵ":"ŵ","ẇ":"ẇ","ẘ":"ẘ","ẍ":"ẍ","ẋ":"ẋ","ý":"ý","ỳ":"ỳ","ÿ":"ÿ","ỹ":"ỹ","ȳ":"ȳ","ŷ":"ŷ","ẏ":"ẏ","ẙ":"ẙ","ź":"ź","ž":"ž","ẑ":"ẑ","ż":"ż","Á":"Á","À":"À","Ä":"Ä","Ǟ":"Ǟ","Ã":"Ã","Ā":"Ā","Ă":"Ă","Ắ":"Ắ","Ằ":"Ằ","Ẵ":"Ẵ","Ǎ":"Ǎ","Â":"Â","Ấ":"Ấ","Ầ":"Ầ","Ẫ":"Ẫ","Ȧ":"Ȧ","Ǡ":"Ǡ","Å":"Å","Ǻ":"Ǻ","Ḃ":"Ḃ","Ć":"Ć","Ḉ":"Ḉ","Č":"Č","Ĉ":"Ĉ","Ċ":"Ċ","Ç":"Ç","Ď":"Ď","Ḋ":"Ḋ","Ḑ":"Ḑ","É":"É","È":"È","Ë":"Ë","Ẽ":"Ẽ","Ē":"Ē","Ḗ":"Ḗ","Ḕ":"Ḕ","Ĕ":"Ĕ","Ḝ":"Ḝ","Ě":"Ě","Ê":"Ê","Ế":"Ế","Ề":"Ề","Ễ":"Ễ","Ė":"Ė","Ȩ":"Ȩ","Ḟ":"Ḟ","Ǵ":"Ǵ","Ḡ":"Ḡ","Ğ":"Ğ","Ǧ":"Ǧ","Ĝ":"Ĝ","Ġ":"Ġ","Ģ":"Ģ","Ḧ":"Ḧ","Ȟ":"Ȟ","Ĥ":"Ĥ","Ḣ":"Ḣ","Ḩ":"Ḩ","Í":"Í","Ì":"Ì","Ï":"Ï","Ḯ":"Ḯ","Ĩ":"Ĩ","Ī":"Ī","Ĭ":"Ĭ","Ǐ":"Ǐ","Î":"Î","İ":"İ","Ĵ":"Ĵ","Ḱ":"Ḱ","Ǩ":"Ǩ","Ķ":"Ķ","Ĺ":"Ĺ","Ľ":"Ľ","Ļ":"Ļ","Ḿ":"Ḿ","Ṁ":"Ṁ","Ń":"Ń","Ǹ":"Ǹ","Ñ":"Ñ","Ň":"Ň","Ṅ":"Ṅ","Ņ":"Ņ","Ó":"Ó","Ò":"Ò","Ö":"Ö","Ȫ":"Ȫ","Õ":"Õ","Ṍ":"Ṍ","Ṏ":"Ṏ","Ȭ":"Ȭ","Ō":"Ō","Ṓ":"Ṓ","Ṑ":"Ṑ","Ŏ":"Ŏ","Ǒ":"Ǒ","Ô":"Ô","Ố":"Ố","Ồ":"Ồ","Ỗ":"Ỗ","Ȯ":"Ȯ","Ȱ":"Ȱ","Ő":"Ő","Ṕ":"Ṕ","Ṗ":"Ṗ","Ŕ":"Ŕ","Ř":"Ř","Ṙ":"Ṙ","Ŗ":"Ŗ","Ś":"Ś","Ṥ":"Ṥ","Š":"Š","Ṧ":"Ṧ","Ŝ":"Ŝ","Ṡ":"Ṡ","Ş":"Ş","Ť":"Ť","Ṫ":"Ṫ","Ţ":"Ţ","Ú":"Ú","Ù":"Ù","Ü":"Ü","Ǘ":"Ǘ","Ǜ":"Ǜ","Ǖ":"Ǖ","Ǚ":"Ǚ","Ũ":"Ũ","Ṹ":"Ṹ","Ū":"Ū","Ṻ":"Ṻ","Ŭ":"Ŭ","Ǔ":"Ǔ","Û":"Û","Ů":"Ů","Ű":"Ű","Ṽ":"Ṽ","Ẃ":"Ẃ","Ẁ":"Ẁ","Ẅ":"Ẅ","Ŵ":"Ŵ","Ẇ":"Ẇ","Ẍ":"Ẍ","Ẋ":"Ẋ","Ý":"Ý","Ỳ":"Ỳ","Ÿ":"Ÿ","Ỹ":"Ỹ","Ȳ":"Ȳ","Ŷ":"Ŷ","Ẏ":"Ẏ","Ź":"Ź","Ž":"Ž","Ẑ":"Ẑ","Ż":"Ż","ά":"ά","ὰ":"ὰ","ᾱ":"ᾱ","ᾰ":"ᾰ","έ":"έ","ὲ":"ὲ","ή":"ή","ὴ":"ὴ","ί":"ί","ὶ":"ὶ","ϊ":"ϊ","ΐ":"ΐ","ῒ":"ῒ","ῑ":"ῑ","ῐ":"ῐ","ό":"ό","ὸ":"ὸ","ύ":"ύ","ὺ":"ὺ","ϋ":"ϋ","ΰ":"ΰ","ῢ":"ῢ","ῡ":"ῡ","ῠ":"ῠ","ώ":"ώ","ὼ":"ὼ","Ύ":"Ύ","Ὺ":"Ὺ","Ϋ":"Ϋ","Ῡ":"Ῡ","Ῠ":"Ῠ","Ώ":"Ώ","Ὼ":"Ὼ"},$r=((c=Zr.prototype).expect=function(e,t){if(void 0===t&&(t=!0),this.fetch().text!==e)throw new $("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()},c.consume=function(){this.nextToken=null},c.fetch=function(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken},c.switchMode=function(e){this.mode=e,this.gullet.switchMode(e)},c.parse=function(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");try{var e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e}finally{this.gullet.endGroups()}},c.subparse=function(e){var t=this.nextToken,e=(this.consume(),this.gullet.pushToken(new D0("}")),this.gullet.pushTokens(e),this.parseExpression(!1));return this.expect("}"),this.nextToken=t,e},c.parseExpression=function(e,t){for(var r=[];;){"math"===this.mode&&this.consumeSpaces();var n=this.fetch();if(-1!==Zr.endOfExpression.indexOf(n.text))break;if(t&&n.text===t)break;if(e&&qr[n.text]&&qr[n.text].infix)break;n=this.parseAtom(t);if(!n)break;"internal"!==n.type&&r.push(n)}return"text"===this.mode&&this.formLigatures(r),this.handleInfixNodes(r)},c.handleInfixNodes=function(e){for(var t,r,n,i=-1,a=0;a \ No newline at end of file diff --git a/mathtex-script-type.min.js b/mathtex-script-type.min.js new file mode 100644 index 000000000..af028303e --- /dev/null +++ b/mathtex-script-type.min.js @@ -0,0 +1 @@ +!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("katex"));else if("function"==typeof define&&define.amd)define(["katex"],t);else{var r="object"==typeof exports?t(require("katex")):t(e.katex);for(var n in r)("object"==typeof exports?exports:e)[n]=r[n]}}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o,i,a,u={};return o=n(771),i=n.n(o),a=document.body.getElementsByTagName("script"),(a=Array.prototype.slice.call(a)).forEach((function(e){if(!e.type||!e.type.match(/math\/tex/i))return-1;var t=null!=e.type.match(/mode\s*=\s*display(;|\s|\n|$)/),r=document.createElement(t?"div":"span");r.setAttribute("class",t?"equation":"inline-equation");try{i().render(e.text,r,{displayMode:t})}catch(t){r.textContent=e.text}e.parentNode.replaceChild(r,e)})),u=u.default}()})); \ No newline at end of file diff --git a/mstile-150x150.png b/mstile-150x150.png new file mode 100644 index 000000000..41ce5739a Binary files /dev/null and b/mstile-150x150.png differ diff --git a/nb5-logo-192x192.png b/nb5-logo-192x192.png new file mode 100644 index 000000000..1461945c1 Binary files /dev/null and b/nb5-logo-192x192.png differ diff --git a/nb5-logo-512x512.png b/nb5-logo-512x512.png new file mode 100644 index 000000000..f859fdf8d Binary files /dev/null and b/nb5-logo-512x512.png differ diff --git a/nb5.png b/nb5.png new file mode 100644 index 000000000..769f9da30 Binary files /dev/null and b/nb5.png differ diff --git a/nb5banner.png b/nb5banner.png new file mode 100644 index 000000000..51a1df5d3 Binary files /dev/null and b/nb5banner.png differ diff --git a/nb5logo.png b/nb5logo.png new file mode 100644 index 000000000..9f261685a Binary files /dev/null and b/nb5logo.png differ diff --git a/nojs.css b/nojs.css new file mode 100644 index 000000000..7e0ba6d16 --- /dev/null +++ b/nojs.css @@ -0,0 +1 @@ +.js{display:none} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 000000000..fae08c93c --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "tinysearch-engine", + "collaborators": [ + "Matthias Endler " + ], + "description": "A tiny search engine for static websites", + "version": "0.6.3", + "license": "Apache-2.0/MIT", + "files": [ + "tinysearch_engine_bg.wasm", + "tinysearch_engine.js", + "tinysearch_engine.d.ts" + ], + "module": "tinysearch_engine.js", + "homepage": "https://github.com/mre/tinysearch", + "types": "tinysearch_engine.d.ts", + "sideEffects": false +} \ No newline at end of file diff --git a/page/1/index.html b/page/1/index.html new file mode 100644 index 000000000..e301d6782 --- /dev/null +++ b/page/1/index.html @@ -0,0 +1,6 @@ + + + + +Redirect +

Click here to be redirected.

diff --git a/prestyle.js b/prestyle.js new file mode 100644 index 000000000..2516247f2 --- /dev/null +++ b/prestyle.js @@ -0,0 +1,4 @@ +const items = document.querySelectorAll('.preStyle'); +items.forEach(item => { + item.rel = 'stylesheet'; +}); diff --git a/reference/apps/cqlgen/index.html b/reference/apps/cqlgen/index.html new file mode 100644 index 000000000..46e725be2 --- /dev/null +++ b/reference/apps/cqlgen/index.html @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + cqlgen | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

cqlgen

+

cqlgen is a default CQL workload generator

+

With NB5, the cqld4 driver comes with a workload generator that can be used to generate a +workload yaml from a CQL schema file.

+

Development on this workload generator is just starting, but it is already in a useful state. +Eventually, workload observation and monitoring methods will be used to create workloads which +more accurately emulate those in-situ.

+

Inputs & Outputs

+

You need the cql schema for whatever keyspaces, types, and tables you want to include. +Optionally, you can provide a table stats file which is generated as +nodetool tablestats > tablestats.

+

Note: The table stats file provides results only for a single node. As such, you will want to +adjust a config parameter called partition_multiplier to improve accuracy of the generated +workload. Further, the file only contains traffic and data details since the last time your node +was restarted, thus it may not be representative of the overall character of your workload and data.

+

Usage

+

A typical cqlgen command looks like this:

+
nb5 cqlgen myschema.cql myworkload.yaml myhistograms
+
+
    +
  1. The first option is simply the name of the .cql file containing your schema.
  2. +
  3. The second is the name of the output yaml. The generator will not overwrite this file for you.
  4. +
  5. The third option is an optional table stats file created with nodetool tablestats >tablestats. +If provided, the reads, writes, and estimated partition counts will be used to weight the +workload to the tables and data sizes automatically.
  6. +
+

For now, it is almost certain that you'll need to extract the configs and tailor them as +described below. Then, when you run nb5 cqlgen ... the config files in the current directory will +be used.

+

Workload Patterns

+

The initial version of the cql workload generator provides these defaults:

+
    +
  • All keyspaces, tables, or types which are provided on the input are included in the workload.
  • +
  • All create syntax has "if not exists" added.
  • +
  • All drop syntax has "if exists" added.
  • +
  • All table DDL properties are ignored except for durable writes.
  • +
  • The default replication settings are as for local testing with SimpleReplicationStrategy. For +testing on a proper cluster with NetworkTopology or in Astra, you'll need to modify this in +the configs explained below.
  • +
  • All UDTs are converted to blobs. This will be replaced by a layer which understands UDTs very +soon.
  • +
  • Data bindings are created using the simplest possible binding recipes that work.
  • +
  • Cardinalities on partition-specific bindings are multiplied by 10. This presumes even data +distribution, replication factor 3, and 30 nodes. This method will be improved in the future.
  • +
  • For the main phase, reads, writes, updates, and scans are included, 1 each. +
      +
    • reads select * from a fully qualified predicate.
    • +
    • writes will write to all named fields.
    • +
    • updates change all fields with a fully qualified predicate.
    • +
    • scan-10 will read up to 10 consecutive rows from a partition with a partially qualified +predicate. This means the last clustering column is not included in the predicates. Single +key (1 partition component) tables do not have a scan created for them.
    • +
    • When partition estimates are provided, all read and writes statements have predicates for +the last partition component modified to modulo by the estimated partition cardinality.
    • +
    +
  • +
+

Fine Tuning

+

The generator uses two internal files for the purposes of setting defaults:

+
    +
  • cqlgen.conf - a yaml formatted configuration file.
  • +
  • cqlgen-bindings.yaml
  • +
+

Both of these files will be read from the internal nb5 resources unless you pull them into the +local directory with these commands:

+
nb5 --copy cqlgen/cqlgen-bindings.yaml
+nb5 --copy cqlgen/cqlgen.conf
+
+

The details of how to customize these files are included within them. The cqlgen-bindings.yaml +file contains default bindings by type. If you get UnresolvedBindingsException when trying to +generate a workload, then a binding for the type in question must be added to the +cqlgen-bindings.yaml file.

+

The cqlgen.conf controls much of the internal wiring of the workload generator. Modifying it +gives you the ability to enable and disable certain stages and behaviors, like:

+
    +
  • obfuscating all keyspace, table, and column names
  • +
  • keyspaces to include by name
  • +
  • tables to exclude by traffic
  • +
  • setting the replcation fields
  • +
  • default timeouts
  • +
  • block naming and construction (which type of operations are included in each)
  • +
+

These are mostly controlled by a series of processing phases known as transformers. +Some transformers depend on others upstream, but if the data provided is not sufficient, they +will silently pass-through.

+

This is a new feature of the NoSQLBench driver. If you are an early adopter, please reach out +with ideas, or for requests and support as needed.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/reference/apps/export-docs/index.html b/reference/apps/export-docs/index.html new file mode 100644 index 000000000..255666c6c --- /dev/null +++ b/reference/apps/export-docs/index.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + export-docs | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

export-docs

+

This is the built-in app that allows NB5 to export docs for integration into other systems. +During a build of NB5, this app is used to auto-inject much of the content into the doc site. +Invoking it as nb5 export-docs creates (or overwrites) a file called exported-docs.zip, +containing the markdown source files for binding functions, bundled apps, specifications, and so on.

+

Using this mechanism ensures that:

+
    +
  1. NB5 contributors who build drivers, bindings, or other modular pieces can use idiomatic forms of +documentation, allowing them to work in one code base.
  2. +
  3. Contributors are encouraged to make integrated tests follow a literate programming pattern, +so that they work as examples as well as verification tools.
  4. +
  5. Users of NB5 will never see documentation which is included in integrated tests, because any +failing test will prevent a failed build from being published or considered for a release.
  6. +
+

This is a relatively new mechanism that will be improved further.

+ +
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/reference/apps/index.html b/reference/apps/index.html new file mode 100644 index 000000000..df778dedf --- /dev/null +++ b/reference/apps/index.html @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + cqlgen | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

cqlgen

+

cqlgen is a default CQL workload generator

+

With NB5, the cqld4 driver comes with a workload generator that can be used to generate a +workload yaml from a CQL schema file.

+

Development on this workload generator is just starting, but it is already in a useful state. +Eventually, workload observation and monitoring methods will be used to create workloads which +more accurately emulate those in-situ.

+

Inputs & Outputs

+

You need the cql schema for whatever keyspaces, types, and tables you want to include. +Optionally, you can provide a table stats file which is generated as +nodetool tablestats > tablestats.

+

Note: The table stats file provides results only for a single node. As such, you will want to +adjust a config parameter called partition_multiplier to improve accuracy of the generated +workload. Further, the file only contains traffic and data details since the last time your node +was restarted, thus it may not be representative of the overall character of your workload and data.

+

Usage

+

A typical cqlgen command looks like this:

+
nb5 cqlgen myschema.cql myworkload.yaml myhistograms
+
+
    +
  1. The first option is simply the name of the .cql file containing your schema.
  2. +
  3. The second is the name of the output yaml. The generator will not overwrite this file for you.
  4. +
  5. The third option is an optional table stats file created with nodetool tablestats >tablestats. +If provided, the reads, writes, and estimated partition counts will be used to weight the +workload to the tables and data sizes automatically.
  6. +
+

For now, it is almost certain that you'll need to extract the configs and tailor them as +described below. Then, when you run nb5 cqlgen ... the config files in the current directory will +be used.

+

Workload Patterns

+

The initial version of the cql workload generator provides these defaults:

+
    +
  • All keyspaces, tables, or types which are provided on the input are included in the workload.
  • +
  • All create syntax has "if not exists" added.
  • +
  • All drop syntax has "if exists" added.
  • +
  • All table DDL properties are ignored except for durable writes.
  • +
  • The default replication settings are as for local testing with SimpleReplicationStrategy. For +testing on a proper cluster with NetworkTopology or in Astra, you'll need to modify this in +the configs explained below.
  • +
  • All UDTs are converted to blobs. This will be replaced by a layer which understands UDTs very +soon.
  • +
  • Data bindings are created using the simplest possible binding recipes that work.
  • +
  • Cardinalities on partition-specific bindings are multiplied by 10. This presumes even data +distribution, replication factor 3, and 30 nodes. This method will be improved in the future.
  • +
  • For the main phase, reads, writes, updates, and scans are included, 1 each. +
      +
    • reads select * from a fully qualified predicate.
    • +
    • writes will write to all named fields.
    • +
    • updates change all fields with a fully qualified predicate.
    • +
    • scan-10 will read up to 10 consecutive rows from a partition with a partially qualified +predicate. This means the last clustering column is not included in the predicates. Single +key (1 partition component) tables do not have a scan created for them.
    • +
    • When partition estimates are provided, all read and writes statements have predicates for +the last partition component modified to modulo by the estimated partition cardinality.
    • +
    +
  • +
+

Fine Tuning

+

The generator uses two internal files for the purposes of setting defaults:

+
    +
  • cqlgen.conf - a yaml formatted configuration file.
  • +
  • cqlgen-bindings.yaml
  • +
+

Both of these files will be read from the internal nb5 resources unless you pull them into the +local directory with these commands:

+
nb5 --copy cqlgen/cqlgen-bindings.yaml
+nb5 --copy cqlgen/cqlgen.conf
+
+

The details of how to customize these files are included within them. The cqlgen-bindings.yaml +file contains default bindings by type. If you get UnresolvedBindingsException when trying to +generate a workload, then a binding for the type in question must be added to the +cqlgen-bindings.yaml file.

+

The cqlgen.conf controls much of the internal wiring of the workload generator. Modifying it +gives you the ability to enable and disable certain stages and behaviors, like:

+
    +
  • obfuscating all keyspace, table, and column names
  • +
  • keyspaces to include by name
  • +
  • tables to exclude by traffic
  • +
  • setting the replcation fields
  • +
  • default timeouts
  • +
  • block naming and construction (which type of operations are included in each)
  • +
+

These are mostly controlled by a series of processing phases known as transformers. +Some transformers depend on others upstream, but if the data provided is not sufficient, they +will silently pass-through.

+

This is a new feature of the NoSQLBench driver. If you are an early adopter, please reach out +with ideas, or for requests and support as needed.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/reference/apps/virtdata/index.html b/reference/apps/virtdata/index.html new file mode 100644 index 000000000..e8c28f5ab --- /dev/null +++ b/reference/apps/virtdata/index.html @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + virdata | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

virdata

+

NB5 contains a bundled virtdata app which lets you verify bindings from the command line. +It is useful for sanity checking values as well as getting a concurrent performance baseline for +specific binding recipes.

+

diagnostic mode

+

The diagnose mode of virtdata can be used to explain binding resolution logic and potentially +how to fix a binding that doesn't resolve properly:

+
nb5 virtdata diagnose "Combinations('0-90-9'); ToInt();"
+
+

perftest mode

+

To see the options you can simply run nb5 virtdata testmapper, which gives you

+
ARGS: checkperf 'specifier' threads bufsize start end
+example: 'timeuuid()' 100 1000 0 10000
+specifier: A VirtData function specifier.
+threads: The number of concurrent threads to run.
+bufsize: The number of cycles to give each thread at a time.
+start: The start cycle for the test, inclusive.
+end: The end cycle for the test, exclusive.
+
+

Assuming you have a working binding recipe that you want to measure for +concurrent performance, you can use the form below:

+
nb5 virtdata testmapper "Combinations('0-90-9'); ToInt();" 96 1000 0 1000000
+
+

Here is what happens when you run this:

+
    +
  1. The binding is resolved.
  2. +
  3. A single thread (the first thread) generates the values into a reference buffer.
  4. +
  5. The specified number of threads is started, and synchronized for simultaneous start.
  6. +
  7. Each thread is given successive batches of input values from the cycle rage specified, in +chunks of bufsize each. A dot . is printed to the console for each completed chunk.
  8. +
  9. Once all threads are complete, each checks their values against the reference buffer, and an +exception is thrown if any difference are found. (This would mean concurrency is affecting +the values, which is not allowed for binding functions.)
  10. +
  11. After all chunks are generated and verified, statistics are displayed to the console:
  12. +
+

output details

+
1 run data = [derived values in brackets] +
2 specifier = 'Combinations('0-90-9'); ToInt();' +
3 threads = 96 +
4 min = 0 +
5 max = 1000000 +
6 [count] = 1000000 +
7 buffersize = 1000 +
8 [totalGenTimeMs] = 2408.874399 +
9 [totalCmpTimeMs] = 2274.510746 +
10 [genPerMs] = 39852.638 +
11 [cmpPerMs] = 42206.879 +
12 [genPerS] = 39852638.245 +
13 [cmpPerS] = 42206879.070 +
+

This shows that on a 12 core (24 thread) system, Around 40 million variates are able to be +generated from the above recipe (across all cores, of course).

+

In detail:

+
    +
  • [totalGenTimeMs] tracks the total time the thread pool spent generating data, in milliseconds.
  • +
  • [totalCmpTimeMs] tracks the total time the thread pool spent cross-checking data across threads.
  • +
  • [genPerMs] and [cmpPerMs] show the calculated rates for generation and validation per +millisecond, respectively.
  • +
  • [genPerS] and [cmpPerS] show the calculated rates for generation and validation per second, +respectively.
  • +
+

interpretation

+

This example shows how effective variate generation can be. This doesn't mean that you can +easily simulate 40 million operations with this data. However, it does anecdotally indicate +the proportional load that generation puts on the system. For example, if you were generating +around 400K ops/s from a client with only this binding, it would be reasonable that variate +generation consumes around (400,000/40,000,000) of the system's cycles, or around 1%.

+

More realistic testing scenarios are likely to use proportionally more due to the amount of data +generation which is needed. Still, generating synthetic data makes for a more capable testing +harnesses because of the extra headroom you leave in your system for other necessary work, like +managing a driver's connection pool or serdes on requests and responses.

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/reference/bindings/binding-concepts/index.html b/reference/bindings/binding-concepts/index.html new file mode 100644 index 000000000..52a30ae04 --- /dev/null +++ b/reference/bindings/binding-concepts/index.html @@ -0,0 +1,274 @@ + + + + + + + + + + + + + + + + Binding Concepts | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

NoSQLBench has a built-in library for the flexible management and expressive use of +procedural generation libraries. This section explains the core concepts +of this library, known as Virtual Data Set.

+

Basic Example

+

These functions can be stitched together in small recipes. When you give +these mapping functions useful names in your workloads, they are called +bindings.

+

Here is an example:

+
bindings:
+ numbers: NumberNameToString()
+ names: FirstNames()
+
+

These are two bindings that you can use in your workloads. The names on the left +are the binding names and the functions on the right are the binding recipes. +Altogether, we just call them bindings.

+

Variates (Samples)

+

A numeric sample that is drawn from a distribution for the purpose +of simulation or analysis is called a Variate.

+

Procedural Generation

+

Procedural generation is a category of algorithms and techniques which take +a set or stream of inputs and produce an output in a different form or structure. +While it may appear that procedural generation actually generates data, no output +can come from a void. These techniques simply perturb a value in some stateful way, +or map a coordinate system to another representation. Sometimes, both techniques are +combined together.

+

Uniform Variate

+

A variate (sample) drawn from a uniform (flat) distribution is what we are used +to seeing when we ask a system for a "random" value. These are often produced in +one of two very common forms, either a register full of bits as with most hashing +functions, or a floating point value between 0.0 and 1.0. (This is called the unit +interval).

+

Uniform variates are not really random. Without careful attention to API usage, +such random samples are not even unique from session to session. In many systems, +the programmer has to be very careful to seed the random generator or they will +get the same sequence of numbers every time they run their program. This turns out +to be a useful property, and the random number generators that behave this way are +usually called Pseudo-Random Number Generators, or PRNGs.

+

Apparently Random Variates

+

Uniform variates produced by PRNGs are not actually random, even though they may +pass certain tests for randomness. The streams of values produced are nearly +always measurably random by some meaningful standard. However, they can be +used again in exactly the same way with the same initial seed.

+

Deterministic Variates

+

If you intentionally avoid randomizing the initial seed for a PRNG, for example, +with the current timestamp, then it gives you a way to replay a sequence. +You can think of each initial seed as a bank of values which you can go back +to at any time. However, when using stateful PRNGs as a way to provide these +variates, your results will be order dependent.

+

Randomly Accessible Determinism

+

Instead of using a PRNG, it is possible to use a hash function instead. With a 64-bit +register, you have 2^64 (2^63 in practice due to available implementations) possible +values. If your hash function has high dispersion, then you will effectively +get the same result of apparent randomness as well as deterministic sequences, even +when you use simple sequences of inputs to your random() function. This allows +you to access a random value in bucket 57, for example, and go back to it at any +time and in any order to get the same value again.

+

Data Mapping Functions

+

The data mapping functions are the core building block of virtual data set. +Data mapping functions are generally pure functions. This simply means that +a generator function will always provide the same result given the same input. +The parameters that you will see on some binding recipes are not representative +of volatile state. These parameters are initializer values which are part of a +function's definition. For example a Mod(5) will always behave like a Mod(5), +as a pure function. But a Mod(7) will behave differently than a Mod(5), although +each function will always produce its own stable result for a given input.

+

Combining RNGs and Data Mapping Functions

+

Because pure functions play such a key part in procedural generation techniques, +the terms "data mapping function", "data mapper" and "data mapping library" will +be more common in the library than "generator". Conceptually, mapping functions +to not generate anything. It makes more sense to think of mapping data from one +domain to another. Even so, the data that is yielded by mapping functions can +appear quite realistic.

+

Because good RNGs do generally contain internal state, they aren't purely +functional. This means that in some cases -- those in which you need to have +random access to a virtual data set, hash functions make more sense. This +toolkit allows you to choose between the two in some cases. However, it +generally favors using hashing and pure-function approaches where possible. Even +the statistical curve simulations do this.

+

Bindings Template

+

It is often useful to have a template that describes a set of generator +functions that can be reused across many threads or other application scopes. A +bindings template is a way to capture the requested generator functions for +re-use, with actual scope instantiation of the generator functions controlled by +the usage point. For example, in a JEE app, you may have a bindings template in +the application scope, and a set of actual bindings within each request (thread +scope).

+ +

Back to top

+
+ +
+
+
+
+ +

Copyright © 2023-2023 NoSQLBench Project (BUILD)

+
+
+ + diff --git a/reference/bindings/funcref-collections/index.html b/reference/bindings/funcref-collections/index.html new file mode 100644 index 000000000..ba72e9d32 --- /dev/null +++ b/reference/bindings/funcref-collections/index.html @@ -0,0 +1,712 @@ + + + + + + + + + + + + + + + + collection functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + +
+ +

Collection functions allow you to construct Java Lists, Maps or Sets. +These functions often take the form of a higher-order function, where +the inner function definitions are called to determine the size of +the collection, the individual values to be added, etc.

+

For each type of collection, there exists multiple forms which allow you to control how the provided +function arguments are used to set the values into the collection.

+

Sized or Pair-wise functions

+

Any function in this category with Sized occuring in its name must be initialized with a sizing +function as an argument. For example, ListSized(Mod(5),NumberNameToString()) will create a list +which is sized by the first function -- a list between 0 and 4 elements in this case. With an input +value of 3L, the resulting List will contain 3 elements. With an input of 7L, it will contain 2 +elements.

+

Alternately, when a function does not contain Sized in its name, the arguments provided are used +as pair-wise mapping functions to the elements in the resulting collection.

+

Simply put, a Sized function will always require a sizing function as the first argument.

+

Stepped or Hashed or Same

+

Any function in this category which contains Stepped in its name will automatically increment the +input value used for each element in the collection. For example +ListStepped(NumberNameToString(),NumberNameToString()) will always creat a two-element List, but +the inputs to the provided functions will be i+0, i+1, where i is the input value to the ListStepped +function.

+

Alternately, any function in this category which contains Hashed in its name will automatically +hash the input value used for each element. This is useful when you want to create values within a +collection that vary significantly with respect of their common seed value. For example, +ListHashed(NumberNameToString(),NumberNameToString(),NumberNameToString()) will always provide a +three element List with values that are not obviously related to each other. For each additional +element added to the collection, the previous input is hashed, so there is a relationship, but it +will not be obvious nor discernable for most testing purposes.

+

If neither Stepped nor Hashed occurs in the function name, then every element function +gets the exact value given to the main function.

+

Overview of functions

+

All of the useful collection binding functions follow the same basic patterns above.

+

List Functions**

+ + + +
Same InputStepped InputHashed Input
Pair-wiseListFunctions(...)ListStepped(...)ListHashed(...)
SizedListSized(...)ListSizedStepped(...)ListSizedHashed(...)
+

The name ListFunctions(...) was chosen to avoid clashing with the existing List(...) function.

+

Set Functions

+

The values produced by the provided element functions for Sets do not check for duplicate values. +This means that you must ensure that your element functions yield distinct values to insert into +the collection as it is being built if you want to have a particular cardinality of values in your +collection. Overwrites are allowed, although they may not be intended in most cases.

+ + + +
Same InputStepped InputHashed Input
Pair-wiseSetFunctions(...)SetStepped(...)SetHashed(...)
SizedSetSized(...)SetSizedStepped(...)SetSizedHashed(...)
+

The name SetFunctions(...) was chosen to avoid clashing with the existing Set(...) function.

+

Map Functions

+

The values produced by the provided element functions for Maps do not check for duplicate values. +This means that you must ensure that your element functions yield distinct keys to insert into +the collection as it is being built if you want to have a particular cardinality of values in your +collection. Overwrites are allowed, although they may not be intended in most cases.

+ + + +
Same InputStepped InputHashed Input
Pair-wiseMapFunctions(...)MapStepped(...)MapHashed(...)
SizedMapSized(...)MapSizedStepped(...)MapSizedHashed(...)
+

The name MapFunctions(...) was chosen to avoid clashing with the existing Map(...) function.

+

For the key and value functions provided to a Map function, they are taken as even-odd pairs (starting +at zero). For sized functions, the last defined key function will be used for elements past +the size of the key functions provided. The same is true for the value functions. For example, +a call to MapSized(3,f(...),g(...),h(...)) will use f(...) and g(...) for the first key and value, +but from that point forward will use h(...) for all keys and g(...) for all values.

+

HashedLineToStringList

+

Creates a List<String> from a list of words in a file.

+
    +
  • long -> HashedLineToStringList(String: filename, int: minSize, int: maxSize) -> List
  • +
+

HashedLineToStringSet

+

Return a pseudo-randomly created Set from the values in the specified file.

+
    +
  • long -> HashedLineToStringSet(String: filename, int: minSize, int: maxSize) -> Set +
      +
    • example: HashedLineToStringSet('data/variable_words.txt',2,10)
    • +
    • Create a set of words sized between 2 and 10 elements
    • +
    +
  • +
+

HashedLineToStringStringMap

+

Create a String-String map from the specified file, ranging in size from 0 to the specified maximum.

+
    +
  • long -> HashedLineToStringStringMap(String: paramFile, int: maxSize) -> Map<String,String>
  • +
+

HashedRangeToLongList

+

Create a list of longs.

+
    +
  • long -> HashedRangeToLongList(int: minVal, int: maxVal, int: minSize, int: maxSize) -> List
  • +
+

Join

+

This takes any collection and concatenates the String representation with a specified delimiter.

+
    +
  • Collection -> Join(String: delim) -> String +
      +
    • example: Join(',')
    • +
    • Concatenate the incoming collection with ','
    • +
    +
  • +
+

List

+

Create a {@code List} from a long input based on two functions, the first to determine the list size, and the second to populate the list with object values. The input fed to the second function is incremented between elements.

+

To directly create Lists of Strings from the String version of the same mapping functions, simply use {@link +StringList} instead.

+

This function is not recommended, given that the other List functions are more clear about how they construct values. +This function may be removed in the next major release, but it will be retained as deprecated for now.

+
    +
  • long -> List(Object: sizeFunc, Object: valueFunc) -> List +
      +
    • example: List(HashRange(3,7),Add(15L))
    • +
    • create a list between 3 and 7 elements of Long values
    • +
    + + +

    ListFunctions

    +

    Create a List from a long input based on a set of provided functions. As a 'Pair-wise' function, the size of the resulting collection is determined directly by the number of provided element functions. As neither a 'Stepped' nor a 'Hashed' function, the input value used by each element function is the same as that provided to the outer function.

    +
      +
    • long -> ListFunctions(Object[]...: funcs) -> List +
        +
      • example: ListFunctions(NumberNameToString(),NumberNameToString(),NumberNameToString())
      • +
      • Create a list of object values of each function output. Produces values like ['one','one','one']
      • +
      + + +

      ListHashed

      +

      Create a List from a long input based on a set of provided functions. As a 'Pair-wise' function, the size of the resulting collection is determined directly by the number of provided element functions. As a 'Hashed' function, the input value is hashed again before being used by each element function.

      +
        +
      • long -> ListHashed(Object[]...: funcs) -> List +
          +
        • example: ListHashed(ToString(), WeightedStrings('text:1'))
        • +
        • Create a hash list of object values of each function output. ListHashed output ['2945182322382062539','text']
        • +
        + + +

        ListSized

        +

        Create a List from a long input based on a set of provided functions. As a 'Sized' function, the first argument is a function which determines the size of the resulting list. Additional functions provided are used to generate the elements to add to the collection. If the size is larger than the number of provided functions, the last provided function is used repeatedly as needed. As neither a 'Stepped' nor a 'Hashed' function, the input value used by each element function is the same as that provided to the outer function.

        +
          +
        • +

          long -> ListSized(Object: sizeFunc, Object[]...: funcs) -> List

          +
            +
          • example: ListSized(FixedValue(5), NumberNameToString(),NumberNameToString(), WeightedStrings('text:1'))
          • +
          • Create a sized list of object values of each function output. List size function will recursively call the last function tillend of the list size functions
          • +
          + +
        • +

          long -> ListSized(int: size, Object[]...: funcs) -> List

          + + +

          ListSizedHashed

          +

          Create a List from a long input based on a set of provided functions. As a 'Sized' function, the first argument is a function which determines the size of the resulting list. Additional functions provided are used to generate the elements to add to the collection. If the size is larger than the number of provided functions, the last provided function is used repeatedly as needed. As a 'Hashed' function, the input value is hashed again before being used by each element function.

          +
            +
          • +

            long -> ListSizedHashed(Object: sizeFunc, Object[]...: funcs) -> List

            +
              +
            • example: ListSizedHashed(FixedValue(5),long->ToString(),long->WeightedStrings('text:1'),long->ToString())
            • +
            • Create a sized hash list of object values of each function output. List size function will recursively call the last function tillend of the list size functions
            • +
            + +
          • +

            long -> ListSizedHashed(int: size, Object[]...: funcs) -> List

            + + +

            ListSizedStepped

            +

            Create a List from a long input based on a set of provided functions. As a 'Sized' function, the first argument is a function which determines the size of the resulting list. Additional functions provided are used to generate the elements to add to the collection. If the size is larger than the number of provided functions, the last provided function is used repeatedly as needed. As a 'Stepped' function, the input value is incremented before being used by each element function.

            +
              +
            • +

              long -> ListSizedStepped(Object: sizeFunc, Object[]...: funcs) -> List

              +
                +
              • example: ListFunctions(NumberNameToString(),NumberNameToString())
              • +
              • Create a list of ['one','one']
              • +
              + +
            • +

              long -> ListSizedStepped(int: size, Object[]...: funcs) -> List

              + + +

              ListStepped

              +

              Create a List from a long input based on a set of provided functions. As a 'Pair-wise' function, the size of the resulting collection is determined directly by the number of provided element functions. As a 'Stepped' function, the input value is incremented before being used by each element function.

              +
                +
              • long -> ListStepped(Object[]...: funcs) -> List +
                  +
                • example: ListStepped(NumberNameToString(),NumberNameToString())
                • +
                • Create a list of ['one','two']
                • +
                + + +

                Map

                +

                Create a {@code Map} from a long input based on three functions, the first to determine the map size, and the second to populate the map with key objects, and the third to populate the map with value objects. The long input fed to the second and third functions is incremented between entries. To directly create Maps with key and value Strings using the same mapping functions, simply use {@link StringMap} instead.

                +
                  +
                • +

                  long -> Map(function.LongToIntFunction: sizeFunc, function.LongFunction: keyFunc, function.LongFunction: valueFunc) -> Map<Object,Object>

                  +
                    +
                  • example: Map(HashRange(3,7),NumberNameToString(),HashRange(1300,1700))
                  • +
                  • create a map of size 3-7 entries, with a key of type string and a value of type int (Integer by autoboxing)
                  • +
                  + +
                • +

                  long -> Map(function.LongFunction[]...: objfuncs) -> Map<Object,Object>

                  +
                    +
                  • example: Map(NumberNameToString(),HashRange(1300,1700),NumberNameToString(),HashRange(3,7))
                  • +
                  • create a map of size 2, with a specific function for each key and each value
                  • +
                  + + +

                  MapFunctions

                  +

                  Create a Map from a long input based on a set of provided key and value functions. Any duplicate entries produced by the key functions are elided. As a 'Pair-wise' function, the size of the resulting collection is determined directly by the number of provided element functions. Since this is a map, the functions come in pairs, each even numbered function is a key function and each odd numbered function is the corresponding value function. As neither a 'Stepped' nor a 'Hashed' function, the input value used by each key and value function is the same as that provided to the outer function.

                  +
                    +
                  • long -> MapFunctions(Object[]...: funcs) -> Map<Object,Object> +
                      +
                    • example: MapFunctions(NumberNameToString(),NumberNameToString(),ToString(),ToString())
                    • +
                    • Create a map of object values. Produces values like {'one':'one'1:1}.
                    • +
                    +
                  • +
                  +

                  MapHashed

                  +

                  Create a Map from a long input based on a set of provided key and value functions. Any duplicate entries produced by the key functions are elided. As a 'Pair-wise' function, the size of the resulting collection is determined directly by the number of provided element functions. Since this is a map, the functions come in pairs, each even numbered function is a key function and each odd numbered function is the corresponding value function. As a 'Hashed' function, the input value is hashed again before being used by each key and value function.

                  +
                    +
                  • long -> MapHashed(Object[]...: funcs) -> Map<Object,Object> +
                      +
                    • example: MapHashed(NumberNameToString(),NumberNameToString(),ToString(),ToString())
                    • +
                    • Create a map of object values. Produces values like {'one':'one','4464361019114304900','4464361019114304900'}.
                    • +
                    +
                  • +
                  +

                  MapSized

                  +

                  Create a Map from a long input based on a set of provided key and value functions. Any duplicate entries produced by the key functions are elided. As a 'Sized' function, the first argument is a function which determines the size of the resulting map. Additional functions provided are used to generate the elements to add to the collection, as in the pair-wise mode of {@link MapFunctions}. If the size is larger than the number of provided functions, the last provided function is used repeatedly as needed. (respectively for key functions as well as value functions) As neither a 'Stepped' nor a 'Hashed' function, the input value used by each key and value function is the same as that provided to the outer function.

                  +
                    +
                  • +

                    long -> MapSized(Object: sizeFunc, Object[]...: funcs) -> Map<Object,Object>

                    +
                      +
                    • example: MapSized(1, NumberNameToString(),NumberNameToString(),ToString(),ToString())
                    • +
                    • Create a map of object values. Produces values like {'one':'one'1:1}.
                    • +
                    +
                  • +
                  • +

                    long -> MapSized(int: size, Object[]...: funcs) -> Map<Object,Object>

                    +
                  • +
                  +

                  MapSizedHashed

                  +

                  Create a Map from a long input based on a set of provided key and value functions. Any duplicate entries produced by the key functions are elided. As a 'Sized' function, the first argument is a function which determines the size of the resulting map. Additional functions provided are used to generate the elements to add to the collection, as in the pair-wise mode of {@link MapFunctions}. If the size is larger than the number of provided functions, the last provided function is used repeatedly as needed. (respectively for key functions as well as value functions) As a 'Hashed' function, the input value is hashed again before being used by each key and value function.

                  +
                    +
                  • +

                    long -> MapSizedHashed(Object: sizeFunc, Object[]...: funcs) -> Map<Object,Object>

                    +
                      +
                    • example: MapSizedHashed(1, NumberNameToString(),NumberNameToString(),ToString(),ToString())
                    • +
                    • Create a map of object values. Produces values like {'one':'one'1:1}.
                    • +
                    • example: MapSizedHashed(HashRange(3,5), NumberNameToString(),NumberNameToString())
                    • +
                    • Create a map of object values. Produces values like {'one':'one'1:1}.
                    • +
                    +
                  • +
                  • +

                    long -> MapSizedHashed(int: size, Object[]...: funcs) -> Map<Object,Object>

                    +
                  • +
                  +

                  MapSizedStepped

                  +

                  Create a Map from a long input based on a set of provided key and value functions. Any duplicate entries produced by the key functions are elided. As a 'Sized' function, the first argument is a function which determines the size of the resulting map. Additional functions provided are used to generate the elements to add to the collection, as in the pair-wise mode of {@link MapFunctions}. If the size is larger than the number of provided functions, the last provided function is used repeatedly as needed. (respectively for key functions as well as value functions) As a 'Stepped' function, the input value is incremented before being used by each key or value function.

                  +
                    +
                  • +

                    long -> MapSizedStepped(Object: sizeFunc, Object[]...: funcs) -> Map<Object,Object>

                    +
                      +
                    • example: MapSizedStepped(1, NumberNameToString(),NumberNameToString())
                    • +
                    • Create a map of object values. Produces values like {'one':'one'1:1}.
                    • +
                    +
                  • +
                  • +

                    long -> MapSizedStepped(int: size, Object[]...: funcs) -> Map<Object,Object>

                    +
                  • +
                  +

                  MapStepped

                  +

                  Create a Map from a long input based on a set of provided key and value functions. Any duplicate entries produced by the key functions are elided. As a 'Pair-wise' function, the size of the resulting collection is determined directly by the number of provided element functions. Since this is a map, the functions come in pairs, each even numbered function is a key function and each odd numbered function is the corresponding value function. As a 'Stepped' function, the input value is incremented before being used by each key or value function.

                  +
                    +
                  • long -> MapStepped(Object[]...: funcs) -> Map<Object,Object> +
                      +
                    • example: MapStepped(NumberNameToString(),NumberNameToString(),ToString(),ToString())
                    • +
                    • Create a map of object values. Produces values like {'one':'one'1:1}.
                    • +
                    +
                  • +
                  +

                  Set

                  +

                  Create a {@code Set} from a long input based on two functions, the first to determine the set size, and the second to populate the set with object values. The input fed to the second function is incremented between elements.

                  +

                  To create Sets of Strings from the String version of the same mapping functions, simply use {@link StringSet} +instead.

                  +
                    +
                  • +

                    long -> Set(function.LongToIntFunction: sizeFunc, function.LongFunction: valueFunc) -> Set

                    +
                      +
                    • example: Set(HashRange(3,7),Add(15L))
                    • +
                    • create a set between 3 and 7 elements of Long values
                    • +
                    + +
                  • +

                    long -> Set(function.LongToIntFunction: sizeFunc, function.LongUnaryOperator: valueFunc) -> Set

                    + +
                  • +

                    long -> Set(function.LongToIntFunction: sizeFunc, function.LongToIntFunction: valueFunc) -> Set

                    + +
                  • +

                    long -> Set(function.LongFunction: sizeFunc, function.LongFunction: valueFunc) -> Set

                    + +
                  • +

                    long -> Set(function.LongFunction: sizeFunc, function.LongUnaryOperator: valueFunc) -> Set

                    + +
                  • +

                    long -> Set(function.LongFunction: sizeFunc, function.LongToIntFunction: valueFunc) -> Set

                    + +
                  • +

                    long -> Set(function.LongUnaryOperator: sizeFunc, function.LongFunction: valueFunc) -> Set

                    + +
                  • +

                    long -> Set(function.LongUnaryOperator: sizeFunc, function.LongUnaryOperator: valueFunc) -> Set

                    + +
                  • +

                    long -> Set(function.LongUnaryOperator: sizeFunc, function.LongToIntFunction: valueFunc) -> Set

                    + + +

                    SetFunctions

                    +

                    Create a Set from a long input based on a set of provided functions. Any duplicate values are elided. As a 'Pair-wise' function, the size of the resulting collection is determined directly by the number of provided element functions. As neither a 'Stepped' nor a 'Hashed' function, the input value used by each element function is the same as that provided to the outer function.

                    +
                      +
                    • long -> SetFunctions(Object[]...: funcs) -> Set +
                        +
                      • example: SetFunctions(NumberNameToString(),NumberNameToString(),NumberNameToString())
                      • +
                      • Create a list of object values of each function output. Produces values like ['one'], as each function produces the same value.
                      • +
                      + + +

                      SetHashed

                      +

                      Create a Set from a long input based on a set of provided functions. As a 'Pair-wise' function, the size of the resulting collection is determined directly by the number of provided element functions, assuming no duplicate values. As a 'Hashed' function, the input value is hashed again before being used by each element function.

                      +
                        +
                      • long -> SetHashed(Object[]...: funcs) -> Set +
                          +
                        • example: SetHashed(ToString(), WeightedStrings('text:1'))
                        • +
                        • Create a hash list of object values of each function output, like ['2945182322382062539','text']
                        • +
                        + + +

                        SetSized

                        +

                        Create a Set from a long input based on a set of provided functions. As a 'Sized' function, the first argument is a function which determines the size of the resulting set. Additional functions provided are used to generate the elements to add to the collection. If the size is larger than the number of provided functions, the last provided function is used repeatedly as needed. As neither a 'Stepped' nor a 'Hashed' function, the input value used by each element function is the same as that provided to the outer function.

                        +
                          +
                        • +

                          long -> SetSized(Object: sizeFunc, Object[]...: funcs) -> Set

                          +
                            +
                          • example: SetSized(FixedValue(5), NumberNameToString(), WeightedStrings('text:1'))
                          • +
                          • Create a sized set of object values, like ['one','text'], because 'text' is duplicated 4 times
                          • +
                          + +
                        • +

                          long -> SetSized(int: size, Object[]...: funcs) -> Set

                          + + +

                          SetSizedHashed

                          +

                          Create a Set from a long input based on a set of provided functions. As a 'Sized' function, the first argument is a function which determines the size of the resulting set. Additional functions provided are used to generate the elements to add to the collection. If the size is larger than the number of provided functions, the last provided function is used repeatedly as needed. As a 'Hashed' function, the input value is hashed again before being used by each element function.

                          +
                            +
                          • +

                            long -> SetSizedHashed(Object: sizeFunc, Object[]...: funcs) -> Set

                            +
                              +
                            • example: SetSizedHashed(FixedValue(5),long->ToString(),long->WeightedStrings('text:1'),long->ToString())
                            • +
                            • Create a sized set of values like ['2945182322382062539', 'text', '37945690212757860', '287864597160630738', '3299224200079606887']
                            • +
                            + +
                          • +

                            long -> SetSizedHashed(int: size, Object[]...: funcs) -> Set

                            + + +

                            SetSizedStepped

                            +

                            Create a Set from a long input based on a set of provided functions. As a 'Sized' function, the first argument is a function which determines the size of the resulting set. Additional functions provided are used to generate the elements to add to the collection. If the size is larger than the number of provided functions, the last provided function is used repeatedly as needed. As a 'Stepped' function, the input value is incremented before being used by each element function.

                            +
                              +
                            • +

                              long -> SetSizedStepped(Object: sizeFunc, Object[]...: funcs) -> Set

                              +
                                +
                              • example: SetSizedStepped(Mod(3),NumberNameToString(),NumberNameToString())
                              • +
                              • Create a set, like ['three','four']
                              • +
                              + +
                            • +

                              long -> SetSizedStepped(int: size, Object[]...: funcs) -> Set

                              + + +

                              SetStepped

                              +

                              Create a Set from a long input based on a set of provided functions. As a 'Pair-wise' function, the size of the resulting collection is determined directly by the number of provided element functions, assuming no duplicate values. As a 'Stepped' function, the input value is incremented before being used by each element function.

                              +
                                +
                              • long -> SetStepped(Object[]...: funcs) -> Set +
                                  +
                                • example: SetStepped(NumberNameToString(),NumberNameToString())
                                • +
                                • Create a list of ['one','two']
                                • +
                                + + +

                                StringList

                                +

                                Create a {@code List} from a long value, based on two functions, the first to determine the list size, and the second to populate the list with String values. The input fed to the second function is incremented between elements. Regardless of the object type provided by the second function, {@link Object#toString()} is used to get the value to add to the list.

                                +

                                To create Lists of any type of object simply use {@link List} with an specific value mapping function.

                                +
                                  +
                                • long -> StringList(function.LongToIntFunction: sizeFunc, function.LongFunction: valueFunc) -> List +
                                    +
                                  • example: StringList(HashRange(3,7),Add(15L))
                                  • +
                                  • create a list between 3 and 7 elements of String representations of Long values
                                  • +
                                  + + +

                                  StringMap

                                  +

                                  Create a {@code Map} from a long input based on three functions, the first to determine the map size, and the second to populate the map with key objects, and the third to populate the map with value objects. The long input fed to the second and third functions is incremented between entries. Regardless of the object type provided by the second and third functions, {@link Object#toString()} is used to determine the key and value to add to the map. To create Maps of any key and value types, simply use {@link Map} with an specific key and value mapping functions.

                                  +
                                    +
                                  • +

                                    long -> StringMap(function.LongToIntFunction: sizeFunc, function.LongFunction: keyFunc, function.LongFunction: valueFunc) -> Map<String,String>

                                    +
                                      +
                                    • example: StringMap(HashRange(3,7),NumberNameToString(),HashRange(1300,1700))
                                    • +
                                    • create a map of size 3-7 entries, with a key of type string and a value of type int (Integer by autoboxing)
                                    • +
                                    + +
                                  • +

                                    long -> StringMap(function.LongFunction[]...: objfuncs) -> Map<String,String>

                                    +
                                      +
                                    • example: StringMap(NumberNameToString(),HashRange(1300,1700),NumberNameToString(),HashRange(3,7))
                                    • +
                                    • create a map of size 2, with a specific function for each key and each value
                                    • +
                                    + + +

                                    StringSet

                                    +

                                    Create a {@code Set} from a long based on two functions, the first to determine the set size, and the second to populate the set with String values. The input fed to the second function is incremented between elements. Regardless of the object type provided by the second function, {@link Object#toString()} is used to get the value to add to the list. To create Sets of any type of object simply use {@link Set} with a specific value mapping function.

                                    +
                                      +
                                    • +

                                      long -> StringSet(function.LongToIntFunction: sizeFunc, function.LongFunction: valueFunc) -> Set

                                      +
                                        +
                                      • example: StringSet(HashRange(3,7),Add(15L))
                                      • +
                                      • create a set between 3 and 7 elements of String representations of Long values
                                      • +
                                      + +
                                    • +

                                      long -> StringSet(function.LongToIntFunction: sizeFunc, function.LongUnaryOperator: valueFunc) -> Set

                                      +
                                    • +
                                    • +

                                      long -> StringSet(function.LongToIntFunction: sizeFunc, function.LongToIntFunction: valueFunc) -> Set

                                      +
                                    • +
                                    • +

                                      long -> StringSet(function.LongFunction<?>: sizeFunc, function.LongFunction: valueFunc) -> Set

                                      + +
                                    • +

                                      long -> StringSet(function.LongFunction<?>: sizeFunc, function.LongUnaryOperator: valueFunc) -> Set

                                      +
                                    • +
                                    • +

                                      long -> StringSet(function.LongFunction<?>: sizeFunc, function.LongToIntFunction: valueFunc) -> Set

                                      +
                                    • +
                                    • +

                                      long -> StringSet(function.LongUnaryOperator: sizeFunc, function.LongFunction: valueFunc) -> Set

                                      + +
                                    • +

                                      long -> StringSet(function.LongUnaryOperator: sizeFunc, function.LongUnaryOperator: valueFunc) -> Set

                                      +
                                    • +
                                    • +

                                      long -> StringSet(function.LongUnaryOperator: sizeFunc, function.LongToIntFunction: valueFunc) -> Set

                                      +
                                    • + + +

                                      Back to top

                                      + + + +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-conversion/index.html b/reference/bindings/funcref-conversion/index.html new file mode 100644 index 000000000..143c51c40 --- /dev/null +++ b/reference/bindings/funcref-conversion/index.html @@ -0,0 +1,1046 @@ + + + + + + + + + + + + + + + + conversion functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      Conversion functions simply allow values of one type +to be converted to another type in an obvious way.

                                      +

                                      ByteBufferSizedHashed

                                      +

                                      Create a ByteBuffer from a long input based on a provided size function. As a 'Sized' function, the first argument is a function which determines the size of the resulting ByteBuffer. As a 'Hashed' function, the input value is hashed again before being used as value.

                                      +
                                        +
                                      • +

                                        long -> ByteBufferSizedHashed(int: size) -> java.nio.ByteBuffer

                                        +
                                          +
                                        • example: ByteBufferSizedHashed(16)
                                        • +
                                        • Functionally identical to HashedToByteBuffer(16) but using dynamic sizing implementation
                                        • +
                                        • example: ByteBufferSizedHashed(HashRange(10, 14))
                                        • +
                                        • Create a ByteBuffer with variable limit (10 to 14)
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ByteBufferSizedHashed(Object: sizeFunc) -> java.nio.ByteBuffer

                                        +
                                      • +
                                      +

                                      ByteBufferToHex

                                      +

                                      Convert the contents of the input ByteBuffer to a String as hexadecimal. This function is retained to avoid breaking previous workload definitions, but you should use {@link ToHexString} instead.

                                      +
                                        +
                                      • java.nio.ByteBuffer -> ByteBufferToHex() -> String
                                      • +
                                      +

                                      DecimalFormat

                                      +

                                      Formats a floating point value to a string using the java.text.DecimalFormat

                                      +
                                        +
                                      • double -> DecimalFormat(String: format) -> String +
                                          +
                                        • example: DecimalFormat('.##')
                                        • +
                                        • converts a double value to a string with only two digits after the decimal
                                        • +
                                        +
                                      • +
                                      +

                                      DigestToByteBuffer

                                      +

                                      Computes the digest of the ByteBuffer on input and stores it in the output ByteBuffer. The digestTypes available are: MD2 MD5 SHA-1 SHA-224 SHA-256 SHA-384 SHA-512 SHA3-224 SHA3-256 SHA3-384 SHA3-512

                                      +
                                        +
                                      • +

                                        long -> DigestToByteBuffer(String: digestType) -> java.nio.ByteBuffer

                                        +
                                      • +
                                      • +

                                        java.nio.ByteBuffer -> DigestToByteBuffer(String: digestType) -> java.nio.ByteBuffer

                                        +
                                      • +
                                      +

                                      DoubleToFloat

                                      +

                                      Convert the input double value to the closest float value.

                                      +
                                        +
                                      • double -> DoubleToFloat() -> Float
                                      • +
                                      +

                                      EscapeJSON

                                      +

                                      Escape all special characters which are required to be escaped when found within JSON content according to the JSON spec

                                      +
                                      {@code
                                      +\b  Backspace (ascii code 08)
                                      +\f  Form feed (ascii code 0C)
                                      +\n  New line
                                      +\r  Carriage return
                                      +\t  Tab
                                      +\"  Double quote
                                      +\\  Backslash character
                                      +\/  Forward slash
                                      +}
                                      +
                                      +
                                        +
                                      • String -> EscapeJSON() -> String
                                      • +
                                      +

                                      Flow

                                      +

                                      Combine functions into one.

                                      +

                                      This function allows you to combine multiple other functions into one. This is often useful +for constructing more sophisticated recipes, when you don't have the ability to use +control flow or non-functional forms.

                                      +

                                      The functions will be stitched together using the same logic that VirtData uses when +combining flows outside functions. That said, if the functions selected are not the right ones, +then it is possible to end up with the wrong data type at the end. To remedy this, be sure +to add input and output qualifiers, like long-> or ->String where +appropriate, to ensure that VirtData selects the right functions within the flow.

                                      +
                                        +
                                      • long -> Flow(Object[]...: funcs) -> Object
                                      • +
                                      +

                                      Format

                                      +

                                      Apply the Java String.format method to an incoming object. @see Java 8 String.format(...) javadoc Note: This function can often be quite slow, so more direct methods are generally preferrable.

                                      +
                                        +
                                      • Object -> Format(String: format) -> String +
                                          +
                                        • example: Format('Y')
                                        • +
                                        • Yield the formatted year from a Java date object.
                                        • +
                                        +
                                      • +
                                      +

                                      HTMLEntityDecode

                                      +

                                      encode HTML Entities

                                      +
                                        +
                                      • String -> HTMLEntityDecode() -> String +
                                          +
                                        • example: HTMLEntityEncode()
                                        • +
                                        • Decode/Unescape input from HTML4 valid to text.
                                        • +
                                        +
                                      • +
                                      +

                                      HTMLEntityEncode

                                      +

                                      encode HTML Entities

                                      +
                                        +
                                      • String -> HTMLEntityEncode() -> String +
                                          +
                                        • example: HTMLEntityEncode()
                                        • +
                                        • Encode/Escape input into HTML4 valid entties.
                                        • +
                                        +
                                      • +
                                      +

                                      LongToByte

                                      +

                                      Convert the input long value to a byte, with negative values masked away.

                                      +
                                        +
                                      • long -> LongToByte() -> Byte
                                      • +
                                      +

                                      LongToShort

                                      +

                                      Convert the input value from long to short.

                                      +
                                        +
                                      • long -> LongToShort() -> Short
                                      • +
                                      +

                                      ModuloToBigDecimal

                                      +

                                      Return a {@code BigDecimal} value as the result of modulo division with the specified divisor.

                                      +
                                        +
                                      • +

                                        long -> ModuloToBigDecimal() -> java.math.BigDecimal

                                        +
                                      • +
                                      • +

                                        long -> ModuloToBigDecimal(long: modulo) -> java.math.BigDecimal

                                        +
                                      • +
                                      +

                                      ModuloToBigInt

                                      +

                                      Return a {@code BigInteger} value as the result of modulo division with the specified divisor.

                                      +
                                        +
                                      • +

                                        long -> ModuloToBigInt() -> java.math.BigInteger

                                        +
                                      • +
                                      • +

                                        long -> ModuloToBigInt(long: modulo) -> java.math.BigInteger

                                        +
                                      • +
                                      +

                                      ModuloToBoolean

                                      +

                                      Return a boolean value as the result of modulo division with the specified divisor.

                                      +
                                        +
                                      • long -> ModuloToBoolean() -> Boolean
                                      • +
                                      +

                                      ModuloToByte

                                      +

                                      Return a byte value as the result of modulo division with the specified divisor.

                                      +
                                        +
                                      • long -> ModuloToByte(long: modulo) -> Byte
                                      • +
                                      +

                                      ModuloToShort

                                      +

                                      Return a boolean value as the result of modulo division with the specified divisor.

                                      +
                                        +
                                      • long -> ModuloToShort(long: modulo) -> Short
                                      • +
                                      +

                                      SnappyComp

                                      +

                                      Compress the input using snappy compression

                                      +
                                        +
                                      • String -> SnappyComp() -> java.nio.ByteBuffer
                                      • +
                                      +

                                      StringDateWrapper

                                      +

                                      This function wraps an epoch time in milliseconds into a String as specified in the format. The valid formatters are documented at @see DateTimeFormat API Docs

                                      +
                                        +
                                      • long -> StringDateWrapper(String: format) -> String
                                      • +
                                      +

                                      ToBase64String

                                      +

                                      Computes the Base64 representation of the byte image of the input long.

                                      +
                                        +
                                      • +

                                        String -> ToBase64String() -> String

                                        +
                                          +
                                        • example: ToBase64String()
                                        • +
                                        • encode any input as Base64
                                        • +
                                        +
                                      • +
                                      • +

                                        UUID -> ToBase64String() -> String

                                        +
                                          +
                                        • example: ToBase64String()
                                        • +
                                        • Encode the bits of a UUID into a Base64 String
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToBase64String() -> String

                                        +
                                          +
                                        • example: ToBase64String()
                                        • +
                                        • Convert the bytes of a long input into a base64 String
                                        • +
                                        +
                                      • +
                                      +

                                      ToBigDecimal

                                      +

                                      Convert values to BigDecimals at configurable scale or precision.

                                      +

                                      ToBigDecimal(...) functions which take whole-numbered inputs may have +a scale parameter or a custom MathContext, but not both. The scale parameter +is not supported for String or Double input forms.

                                      +
                                        +
                                      • +

                                        double -> ToBigDecimal() -> java.math.BigDecimal

                                        +
                                          +
                                        • example: ToBigDecimal()
                                        • +
                                        • Convert all double values to BigDecimal values with no limits (using MathContext.UNLIMITED)
                                        • +
                                        +
                                      • +
                                      • +

                                        double -> ToBigDecimal(String: context) -> java.math.BigDecimal

                                        +
                                          +
                                        • +

                                          notes: Convert all input values to BigDecimal values with a specific MathContext. +The value for context can be one of UNLIMITED, +DECIMAL32, DECIMAL64, DECIMAL128, or any valid configuration supported by +{@link MathContext#MathContext(String)}, such as {@code "precision=32 roundingMode=CEILING"}. +In the latter form, roundingMode can be any valid value for {@link RoundingMode}, like +UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, or UNNECESSARY.

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('DECIMAL32')

                                          +
                                        • +
                                        • +

                                          IEEE 754R Decimal32 format, 7 digits, HALF_EVEN

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('DECIMAL64'),

                                          +
                                        • +
                                        • +

                                          IEEE 754R Decimal64 format, 16 digits, HALF_EVEN

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('DECIMAL128')

                                          +
                                        • +
                                        • +

                                          IEEE 754R Decimal128 format, 34 digits, HALF_EVEN

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('UNLIMITED')

                                          +
                                        • +
                                        • +

                                          unlimited precision, HALF_UP

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('precision=17 roundingMode=UNNECESSARY')

                                          +
                                        • +
                                        • +

                                          Custom precision with no rounding performed

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToBigDecimal() -> java.math.BigDecimal

                                        +
                                          +
                                        • example: ToBigDecimal()
                                        • +
                                        • Convert all long values to whole-numbered BigDecimal values
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToBigDecimal(int: scale) -> java.math.BigDecimal

                                        +
                                          +
                                        • example: ToBigDecimal(0)
                                        • +
                                        • Convert all long values to whole-numbered BigDecimal values
                                        • +
                                        • example: ToBigDecimal(2)
                                        • +
                                        • Convert long 'pennies' BigDecimal with 2 digits after decimal point
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToBigDecimal(String: context) -> java.math.BigDecimal

                                        +
                                          +
                                        • +

                                          notes: Convert all input values to BigDecimal values with a specific MathContext. This form is only +supported for scale=0, meaning whole numbers. The value for context can be one of UNLIMITED, +DECIMAL32, DECIMAL64, DECIMAL128, or any valid configuration supported by +{@link MathContext#MathContext(String)}, such as {@code "precision=32 roundingMode=CEILING"}. +In the latter form, roundingMode can be any valid value for {@link RoundingMode}, like +UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, or UNNECESSARY.

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('DECIMAL32')

                                          +
                                        • +
                                        • +

                                          IEEE 754R Decimal32 format, 7 digits, HALF_EVEN

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('DECIMAL64'),

                                          +
                                        • +
                                        • +

                                          IEEE 754R Decimal64 format, 16 digits, HALF_EVEN

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('DECIMAL128')

                                          +
                                        • +
                                        • +

                                          IEEE 754R Decimal128 format, 34 digits, HALF_EVEN

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('UNLIMITED')

                                          +
                                        • +
                                        • +

                                          unlimited precision, HALF_UP

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('precision=17 roundingMode=UNNECESSARY')

                                          +
                                        • +
                                        • +

                                          Custom precision with no rounding performed

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> ToBigDecimal() -> java.math.BigDecimal

                                        +
                                          +
                                        • example: ToBigDecimal()
                                        • +
                                        • Convert all int values to BigDecimal values with no limits (using MathContext.UNLIMITED)
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> ToBigDecimal(String: context) -> java.math.BigDecimal

                                        +
                                          +
                                        • +

                                          notes: Convert all input values to BigDecimal values with a specific MathContext. +The value for context can be one of UNLIMITED, +DECIMAL32, DECIMAL64, DECIMAL128, or any valid configuration supported by +{@link MathContext#MathContext(String)}, such as {@code "precision=32 roundingMode=CEILING"}. +In the latter form, roundingMode can be any valid value for {@link RoundingMode}, like +UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, or UNNECESSARY.

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('DECIMAL32')

                                          +
                                        • +
                                        • +

                                          IEEE 754R Decimal32 format, 7 digits, HALF_EVEN

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('DECIMAL64'),

                                          +
                                        • +
                                        • +

                                          IEEE 754R Decimal64 format, 16 digits, HALF_EVEN

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('DECIMAL128')

                                          +
                                        • +
                                        • +

                                          IEEE 754R Decimal128 format, 34 digits, HALF_EVEN

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('UNLIMITED')

                                          +
                                        • +
                                        • +

                                          unlimited precision, HALF_UP

                                          +
                                        • +
                                        • +

                                          example: ToBigDecimal('precision=17 roundingMode=UNNECESSARY')

                                          +
                                        • +
                                        • +

                                          Custom precision with no rounding performed

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        String -> ToBigDecimal() -> java.math.BigDecimal

                                        +
                                          +
                                        • example: Convert strings to BigDecimal according to default precision (unlimited) and rounding (HALF_UP)
                                        • +
                                        +
                                      • +
                                      • +

                                        String -> ToBigDecimal(String: context) -> java.math.BigDecimal

                                        +
                                          +
                                        • notes: Convert all input values to BigDecimal values with a specific MathContext. This form is only +supported for scale=0, meaning whole numbers. The value for context can be one of UNLIMITED, +DECIMAL32, DECIMAL64, DECIMAL128, or any valid configuration supported by +{@link MathContext#MathContext(String)}, such as {@code "precision=32 roundingMode=CEILING"}. +In the latter form, roundingMode can be any valid value for {@link RoundingMode}, like +UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN, or UNNECESSARY.
                                        • +
                                        +
                                      • +
                                      +

                                      ToBigInt

                                      +

                                      Convert the input value to a {@code BigInteger}

                                      +
                                        +
                                      • long -> ToBigInt() -> java.math.BigInteger
                                      • +
                                      +

                                      ToBoolean

                                      +

                                      Convert the input value to a {@code boolean}

                                      +
                                        +
                                      • +

                                        Float -> ToBoolean() -> Boolean

                                        +
                                      • +
                                      • +

                                        Double -> ToBoolean() -> Boolean

                                        +
                                      • +
                                      • +

                                        long -> ToBoolean() -> Boolean

                                        +
                                      • +
                                      • +

                                        Integer -> ToBoolean() -> Boolean

                                        +
                                      • +
                                      +

                                      ToByte

                                      +

                                      Convert the input value to a {@code Byte}.

                                      +
                                        +
                                      • +

                                        Float -> ToByte() -> Byte

                                        +
                                      • +
                                      • +

                                        Float -> ToByte(int: modulo) -> Byte

                                        +
                                      • +
                                      • +

                                        Short -> ToByte(int: scale) -> Byte

                                        +
                                      • +
                                      • +

                                        Short -> ToByte() -> Byte

                                        +
                                      • +
                                      • +

                                        String -> ToByte() -> Byte

                                        +
                                      • +
                                      • +

                                        long -> ToByte() -> Byte

                                        +
                                      • +
                                      • +

                                        long -> ToByte(int: modulo) -> Byte

                                        +
                                      • +
                                      • +

                                        int -> ToByte() -> Byte

                                        +
                                      • +
                                      • +

                                        int -> ToByte(int: modulo) -> Byte

                                        +
                                      • +
                                      • +

                                        double -> ToByte() -> Byte

                                        +
                                      • +
                                      • +

                                        double -> ToByte(int: modulo) -> Byte

                                        +
                                      • +
                                      +

                                      ToByteBuffer

                                      +

                                      Convert the input value to a {@code ByteBuffer}

                                      +
                                        +
                                      • +

                                        String -> ToByteBuffer() -> java.nio.ByteBuffer

                                        +
                                      • +
                                      • +

                                        java.nio.CharBuffer -> ToByteBuffer() -> java.nio.ByteBuffer

                                        +
                                      • +
                                      • +

                                        int -> ToByteBuffer() -> java.nio.ByteBuffer

                                        +
                                      • +
                                      • +

                                        long -> ToByteBuffer() -> java.nio.ByteBuffer

                                        +
                                      • +
                                      • +

                                        long -> ToByteBuffer(int: size) -> java.nio.ByteBuffer

                                        +
                                          +
                                        • example: ToByteBuffer(13)
                                        • +
                                        • Repeat the input long value to make a 13byte buffer
                                        • +
                                        +
                                      • +
                                      • +

                                        Float -> ToByteBuffer() -> java.nio.ByteBuffer

                                        +
                                      • +
                                      • +

                                        Short -> ToByteBuffer() -> java.nio.ByteBuffer

                                        +
                                      • +
                                      • +

                                        double -> ToByteBuffer() -> java.nio.ByteBuffer

                                        +
                                      • +
                                      +

                                      ToCharBuffer

                                      +

                                      Convert the input string to a character buffer

                                      +
                                        +
                                      • String -> ToCharBuffer() -> java.nio.CharBuffer
                                      • +
                                      +

                                      ToCqlDurationNanos

                                      +

                                      Convert the input value into a {@link CqlDuration} by reading the input as total nanoseconds, assuming 30-month days.

                                      +
                                        +
                                      • long -> ToCqlDurationNanos() -> com.datastax.oss.driver.api.core.data.CqlDuration
                                      • +
                                      +

                                      ToDouble

                                      +

                                      Convert the input value to a double.

                                      +
                                        +
                                      • long -> ToDouble() -> double
                                      • +
                                      +

                                      ToFloat

                                      +

                                      Convert the input value into a float.

                                      +
                                        +
                                      • +

                                        long -> ToFloat(long: scale) -> Float

                                        +
                                      • +
                                      • +

                                        long -> ToFloat() -> Float

                                        +
                                      • +
                                      • +

                                        double -> ToFloat(double: scale) -> Float

                                        +
                                      • +
                                      • +

                                        double -> ToFloat() -> Float

                                        +
                                      • +
                                      • +

                                        int -> ToFloat(int: scale) -> Float

                                        +
                                      • +
                                      • +

                                        int -> ToFloat() -> Float

                                        +
                                      • +
                                      • +

                                        String -> ToFloat() -> Float

                                        +
                                      • +
                                      • +

                                        Short -> ToFloat() -> Float

                                        +
                                      • +
                                      +

                                      ToHexString

                                      +

                                      Converts the input ByteBuffer to a hexadecimal String.

                                      +
                                        +
                                      • +

                                        long -> ToHexString() -> String

                                        +
                                      • +
                                      • +

                                        java.nio.ByteBuffer -> ToHexString() -> String

                                        +
                                          +
                                        • notes: Convert the ByteBuffer's contents to a hex string using upper case by default.
                                        • +
                                        +
                                      • +
                                      • +

                                        java.nio.ByteBuffer -> ToHexString(boolean: useUpperCase) -> String

                                        +
                                          +
                                        • notes: Convert the ByteBuffer's contents to a hex string upper or lower case.
                                        • +
                                        +
                                      • +
                                      +

                                      ToInetAddress

                                      +

                                      Convert the input value to a {@code InetAddress}

                                      +
                                        +
                                      • long -> ToInetAddress() -> InetAddress
                                      • +
                                      +

                                      ToInt

                                      +

                                      Convert the input value to an int with long modulus remainder. If the scale is chosen, then the value is wrapped at this value. Otherwise, {@link Integer#MAX_VALUE} is used.

                                      +
                                        +
                                      • +

                                        Object -> ToInt() -> Integer

                                        +
                                      • +
                                      • +

                                        Double -> ToInt(int: scale) -> Integer

                                        +
                                      • +
                                      • +

                                        Double -> ToInt() -> Integer

                                        +
                                      • +
                                      • +

                                        double -> ToInt(int: scale) -> int

                                        +
                                      • +
                                      • +

                                        double -> ToInt() -> int

                                        +
                                      • +
                                      • +

                                        long -> ToInt() -> int

                                        +
                                      • +
                                      • +

                                        String -> ToInt() -> Integer

                                        +
                                      • +
                                      • +

                                        long -> ToInt(int: scale) -> int

                                        +
                                          +
                                        • example: ToInt(1000)
                                        • +
                                        • converts a long input value to an int between 0 and 999, inclusive
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToInt() -> int

                                        +
                                          +
                                        • example: ToInt()
                                        • +
                                        • *converts a long input value to an int between 0 and 2147483647, inclusive *
                                        • +
                                        +
                                      • +
                                      +

                                      ToJSON

                                      +

                                      Convert the input object to a JSON string with Gson.

                                      +
                                        +
                                      • Object -> ToJSON() -> String
                                      • +
                                      +

                                      ToJSONPretty

                                      +

                                      Convert the input object to a JSON string with Gson, with pretty printing enabled.

                                      +
                                        +
                                      • Object -> ToJSONPretty() -> String
                                      • +
                                      +

                                      ToLong

                                      +

                                      Convert the input value to a long.

                                      +
                                        +
                                      • +

                                        Float -> ToLong(long: scale) -> Long

                                        +
                                      • +
                                      • +

                                        Float -> ToLong() -> Long

                                        +
                                      • +
                                      • +

                                        String -> ToLong() -> Long

                                        +
                                      • +
                                      • +

                                        double -> ToLong(long: scale) -> long

                                        +
                                      • +
                                      • +

                                        double -> ToLong() -> long

                                        +
                                      • +
                                      +

                                      ToMD5ByteBuffer

                                      +

                                      Converts the byte image of the input long to a MD5 digest in ByteBuffer form. Deprecated usage due to unsafe MD5 digest. Replaced with DigestToByteBuffer with MD5 when absolutely needed for existing NB tests. However, stronger encryption algorithms (e.g. SHA-256) are recommended due to MD5's limitations.

                                      +
                                        +
                                      • long -> ToMD5ByteBuffer() -> java.nio.ByteBuffer +
                                          +
                                        • +

                                          notes: Deprecated usage due to unsafe MD5 digest. +Use the DigestToByteBuffer with alternatives other than MD5.

                                          +
                                        • +
                                        • +

                                          example: MD5ByteBuffer()

                                          +
                                        • +
                                        • +

                                          convert the a input to an md5 digest of its bytes

                                          +
                                        • +
                                        +
                                      • +
                                      +

                                      ToShort

                                      +

                                      Convert the input value to a short.

                                      +
                                        +
                                      • +

                                        String -> ToShort() -> Short

                                        +
                                      • +
                                      • +

                                        Float -> ToShort() -> Short

                                        +
                                      • +
                                      • +

                                        Float -> ToShort(int: modulo) -> Short

                                        +
                                      • +
                                      • +

                                        long -> ToShort() -> Short

                                        +
                                      • +
                                      • +

                                        long -> ToShort(int: wrapat) -> Short

                                        +
                                          +
                                        • notes: This form allows for limiting the short values at a lower limit than Short.MAX_VALUE. +@param wrapat The maximum value to return.
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> ToShort() -> Short

                                        +
                                      • +
                                      • +

                                        int -> ToShort(int: scale) -> Short

                                        +
                                      • +
                                      • +

                                        double -> ToShort() -> Short

                                        +
                                      • +
                                      • +

                                        double -> ToShort(int: modulo) -> Short

                                        +
                                      • +
                                      +

                                      ToString

                                      +

                                      Converts the input to the most obvious string representation with String.valueOf(...). Forms which accept a function will evaluate that function first and then apply String.valueOf() to the result.

                                      +
                                        +
                                      • +

                                        Float -> ToString() -> String

                                        +
                                      • +
                                      • +

                                        long -> ToString() -> String

                                        +
                                      • +
                                      • +

                                        long -> ToString(function.LongUnaryOperator: f) -> String

                                        +
                                      • +
                                      • +

                                        long -> ToString(function.LongFunction<?>: f) -> String

                                        +
                                      • +
                                      • +

                                        long -> ToString(function.Function<Long,?>: f) -> String

                                        +
                                      • +
                                      • +

                                        long -> ToString(function.LongToIntFunction: f) -> String

                                        +
                                      • +
                                      • +

                                        long -> ToString(function.LongToDoubleFunction: f) -> String

                                        +
                                      • +
                                      • +

                                        long -> ToString(io.nosqlbench.virtdata.library.basics.shared.from_long.to_byte.LongToByte: f) -> String

                                        +
                                      • +
                                      • +

                                        long -> ToString(io.nosqlbench.virtdata.library.basics.shared.from_long.to_short.LongToShort: f) -> String

                                        +
                                      • +
                                      • +

                                        double -> ToString() -> String

                                        +
                                          +
                                        • example: ToString()
                                        • +
                                        • map the double input value to a String
                                        • +
                                        +
                                      • +
                                      • +

                                        double -> ToString(function.DoubleUnaryOperator: df) -> String

                                        +
                                          +
                                        • example: ToString(Add(5.7D))
                                        • +
                                        • map the double input value X to X+5.7D and then to a String
                                        • +
                                        +
                                      • +
                                      • +

                                        double -> ToString(function.DoubleFunction: df) -> String

                                        +
                                      • +
                                      • +

                                        double -> ToString(function.Function<Double,Double>: df) -> String

                                        +
                                      • +
                                      • +

                                        int -> ToString() -> String

                                        +
                                      • +
                                      • +

                                        Object -> ToString() -> String

                                        +
                                      • +
                                      +

                                      ToUUID

                                      +

                                      This function creates a non-random UUID in the type 4 version (Random). It always puts the same value in the MSB position of the UUID format. The input value is put in the LSB position. This function is suitable for deterministic testing of scenarios which depend on type 4 UUIDs, but without the mandated randomness that makes testing difficult. Just be aware that the MSB will always contain value 0x0123456789ABCDEFL unless you specify a different long value to pre-fill it with.

                                      +
                                        +
                                      • +

                                        long -> ToUUID() -> UUID

                                        +
                                      • +
                                      • +

                                        long -> ToUUID(long: msbs) -> UUID

                                        +
                                      • +
                                      +

                                      URLDecode

                                      +

                                      URLDecode string data

                                      +
                                        +
                                      • String -> URLDecode(String: charset) -> String +
                                          +
                                        • notes: URLDecode any incoming string using the specified charset.
                                        • +
                                        +
                                      • +
                                      +

                                      @param charset A valid character set name from {@link Charset}

                                      +
                                        +
                                      • +

                                        example: URLDecode('UTF-16')

                                        +
                                      • +
                                      • +

                                        URLDecode using the UTF-16 charset.

                                        +
                                      • +
                                      • +

                                        String -> URLDecode() -> String

                                        +
                                          +
                                        • example: URLDecode()
                                        • +
                                        • URLDecode using the default UTF-8 charset.
                                        • +
                                        +
                                      • +
                                      +

                                      URLEncode

                                      +

                                      URLEncode string data

                                      +
                                        +
                                      • String -> URLEncode(String: charset) -> String +
                                          +
                                        • notes: UrlEncode any incoming string using the specified charset.
                                        • +
                                        +
                                      • +
                                      +

                                      @param charset A valid character set name from {@link Charset}

                                      +
                                        +
                                      • +

                                        example: URLEncode('UTF-16')

                                        +
                                      • +
                                      • +

                                        URLEncode using the UTF-16 charset.

                                        +
                                      • +
                                      • +

                                        String -> URLEncode() -> String

                                        +
                                          +
                                        • example: URLEncode()
                                        • +
                                        • URLEncode using the default UTF-8 charset.
                                        • +
                                        +
                                      • +
                                      + +

                                      Back to top

                                      +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-datetime/index.html b/reference/bindings/funcref-datetime/index.html new file mode 100644 index 000000000..0d5664056 --- /dev/null +++ b/reference/bindings/funcref-datetime/index.html @@ -0,0 +1,1052 @@ + + + + + + + + + + + + + + + + datetime functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      Functions in this category know about times and dates, datetimes, seconds or millisecond epoch times, and so forth.

                                      +

                                      Some of the functions in this category are designed to allow testing of UUID types which are usually designed to avoid +determinism. This makes it possible to test systems which depend on UUIDs but which require determinism in test data. +This is strictly for testing use. Breaking the universally-unique properties of UUIDs in production systems is a bad +idea. Yet, in testing, this determinism is quite useful.

                                      +

                                      CqlDurationFunctions

                                      +

                                      Map a long value into a CQL Duration object based on a set of field functions.

                                      +
                                        +
                                      • +

                                        long -> CqlDurationFunctions(Object: monthsFunc, Object: daysFunc, Object: nanosFunc) -> com.datastax.oss.driver.api.core.data.CqlDuration

                                        +
                                          +
                                        • notes: Create a CQL Duration object from the two provided field functions. The months field is always set to +zero in this form. +@param monthsFunc A function that will yield the months value +@param daysFunc A function that will yield the days value +@param nanosFunc A function that will yeild the nanos value
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> CqlDurationFunctions(Object: daysFunc, Object: nanosFunc) -> com.datastax.oss.driver.api.core.data.CqlDuration

                                        +
                                          +
                                        • notes: Create a CQL Duration object from the two provided field functions. The months field is always set to +zero in this form. +@param daysFunc A function that will yield the days value +@param nanosFunc A function that will yeild the nanos value
                                        • +
                                        +
                                      • +
                                      +

                                      CurrentEpochMillis

                                      +

                                      Provide the millisecond epoch time as given by

                                      +
                                      {@code System.currentTimeMillis()}
                                      +
                                      +

                                      CAUTION: This does not produce deterministic test data.

                                      +
                                        +
                                      • long -> CurrentEpochMillis() -> long
                                      • +
                                      +

                                      DateRangeDuring

                                      +

                                      Takes an input as a reference point in epoch time, and converts it to a DateRange, with the bounds set to the lower and upper timestamps which align to the specified precision. You can use any of these precisions to control the bounds around the provided timestamp: millisecond, second, minute, hour, day, month, or year. If the zoneid is not specified, it defaults to "GMT". If the zoneid is set to "default", then the zoneid is set to the default for the JVM. Otherwise, the specified zone is used.

                                      +
                                        +
                                      • +

                                        long -> DateRangeDuring(String: precision) -> com.datastax.dse.driver.api.core.data.time.DateRange

                                        +
                                          +
                                        • example: DateRangeDuring('millisecond')}
                                        • +
                                        • Convert the incoming millisecond to an equivalent DateRange
                                        • +
                                        • example: DateRangeDuring('minute')}
                                        • +
                                        • Convert the incoming millisecond to a DateRange for the minute in which the millisecond falls
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> DateRangeDuring(String: precision, String: zoneid) -> com.datastax.dse.driver.api.core.data.time.DateRange

                                        +
                                      • +
                                      +

                                      DateRangeFunc

                                      +

                                      Uses the precision and the two functions provided to create a DateRange. You can use any of these precisions to control the bounds around the provided timestamp: millisecond, second, minute, hour, day, month, or year. If the zoneid is not specified, it defaults to "GMT". If the zoneid is set to "default", then the zoneid is set to the default for the JVM. Otherwise, the specified zone is used.

                                      +
                                        +
                                      • +

                                        long -> DateRangeFunc(String: precision, Object: lowerFunc, Object: upperFunc) -> com.datastax.dse.driver.api.core.data.time.DateRange

                                        +
                                          +
                                        • example: StartingEpochMillis('2017-01-01 23:59:59'); DateRangeFunc('second',Identity(),Add(3600000L)
                                        • +
                                        • Create 1-minute date ranges starting at 2017-01-01 23:59:59
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> DateRangeFunc(String: precision, Object: lowerFunc, Object: upperFunc, String: zoneid) -> com.datastax.dse.driver.api.core.data.time.DateRange

                                        +
                                      • +
                                      +

                                      DateRangeOnOrAfter

                                      +

                                      Takes an input as a reference point in epoch time, and converts it to a DateRange, with the lower bounds set to the lower bound of the precision and millisecond provided, and with no upper bound. You can use any of these precisions to control the bounds around the provided timestamp: millisecond, second, minute, hour, day, month, or year. If the zoneid is not specified, it defaults to "GMT". If the zoneid is set to "default", then the zoneid is set to the default for the JVM. Otherwise, the specified zone is used.

                                      +
                                        +
                                      • +

                                        long -> DateRangeOnOrAfter(String: precision, String: zoneid) -> com.datastax.dse.driver.api.core.data.time.DateRange

                                        +
                                      • +
                                      • +

                                        long -> DateRangeOnOrAfter(String: precision) -> com.datastax.dse.driver.api.core.data.time.DateRange

                                        +
                                          +
                                        • example: DateRangeOnOrAfter('millisecond')}
                                        • +
                                        • Convert the incoming millisecond to an match any time on or after
                                        • +
                                        • example: DateRangeOnOrAfter('minute')}
                                        • +
                                        • Convert the incoming millisecond to mach any time on or after the minute in which the millisecond falls
                                        • +
                                        +
                                      • +
                                      +

                                      DateRangeOnOrBefore

                                      +

                                      Takes an input as a reference point in epoch time, and converts it to a DateRange, with the upper bound set to the upper bound of the precision and millisecond provided, and with no lower bound. You can use any of these precisions to control the bounds around the provided timestamp: millisecond, second, minute, hour, day, month, or year. If the zoneid is not specified, it defaults to "GMT". If the zoneid is set to "default", then the zoneid is set to the default for the JVM. Otherwise, the specified zone is used.

                                      +
                                        +
                                      • +

                                        long -> DateRangeOnOrBefore(String: precision) -> com.datastax.dse.driver.api.core.data.time.DateRange

                                        +
                                          +
                                        • example: DateRangeOnOrBefore('millisecond')}
                                        • +
                                        • Convert the incoming millisecond to match anything on or before it.
                                        • +
                                        • example: DateRangeOnOrBefore('minute')}
                                        • +
                                        • Convert the incoming millisecond to match anything on or before the minute in which the millisecond falls
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> DateRangeOnOrBefore(String: precision, String: zoneid) -> com.datastax.dse.driver.api.core.data.time.DateRange

                                        +
                                      • +
                                      +

                                      DateRangeParser

                                      +

                                      Parses the DateRange format according to [Date Range Formatting](https://lucene.apache.org/solr/guide/6_6/working-with-dates +.html#WorkingwithDates-DateRangeFormatting). When possible it is more efficient to use the other DateRange methods since they do not require parsing.

                                      +
                                        +
                                      • String -> DateRangeParser(String: precision) -> com.datastax.dse.driver.api.core.data.time.DateRange +
                                          +
                                        • example: DateRangeParser()}
                                        • +
                                        • *Convert inputs like '[1970-01-01T00:00:00 TO 1970-01-01T00:00:00]' into DateRanges *
                                        • +
                                        +
                                      • +
                                      +

                                      DateTimeParser

                                      +

                                      This function will parse a String containing a formatted date time, yielding a DateTime object. If no arguments are provided, then the format is set to "yyyy-MM-dd HH:mm:ss.SSSZ". For details on formatting options, see @see DateTimeFormat

                                      +
                                        +
                                      • +

                                        String -> DateTimeParser() -> org.joda.time.DateTime

                                        +
                                          +
                                        • +

                                          notes: Initialize the parser with the default pattern of

                                          yyyy-MM-dd HH:mm:ss.SSSZ
                                          .

                                          +
                                        • +
                                        • +

                                          example: DateTimeParser()

                                          +
                                        • +
                                        • +

                                          parse any date in the yyyy-MM-dd HH:mm:ss.SSSZ format

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        String -> DateTimeParser(String: dateTimePattern) -> org.joda.time.DateTime

                                        +
                                          +
                                        • +

                                          notes: Initialize the parser with the given pattern. With this form, if any input fails to parse, +or is null or empty, then an exception is thrown. +@param dateTimePattern The pattern which represents the incoming format.

                                          +
                                        • +
                                        • +

                                          example: DateTimeParser('yyyy-MM-dd')

                                          +
                                        • +
                                        • +

                                          parse any date in the yyyy-MM-dd format

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        String -> DateTimeParser(String: dateTimePattern, String: defaultTime) -> org.joda.time.DateTime

                                        +
                                          +
                                        • +

                                          notes: Initialize the parser with the given pattern and default value. In this form, if any +input fails to parse, then exceptions are suppressed and the default is provided instead. +At initialization, the default is parsed as a sanity check. +@param dateTimePattern The pattern which represents the incoming format. +@param defaultTime An example of a formatted datetime string which is used as a default.

                                          +
                                        • +
                                        • +

                                          example: DateTimeParser('yyyy-MM-dd','1999-12-31')

                                          +
                                        • +
                                        • +

                                          parse any date in the yyyy-MM-dd format, or return the DateTime represented by 1999-12-31

                                          +
                                        • +
                                        +
                                      • +
                                      +

                                      EpochMillisToCqlLocalDate

                                      +

                                      Converts epoch millis to a java.time.LocalDate, which takes the place of the previous CQL-specific LocalDate. if a zoneid of 'default' is provided, then the time zone is set by the default for the JVM. If not, then a valid ZoneId is looked up. The no-args version uses GMT.

                                      +
                                        +
                                      • +

                                        long -> EpochMillisToCqlLocalDate(String: zoneid) -> java.time.LocalDate

                                        +
                                      • +
                                      • +

                                        long -> EpochMillisToCqlLocalDate() -> java.time.LocalDate

                                        +
                                          +
                                        • example: EpochMillisToJavaLocalDate()
                                        • +
                                        • Yields the LocalDate for the millis in GMT
                                        • +
                                        +
                                      • +
                                      +

                                      EpochMillisToJavaLocalDate

                                      +

                                      Converts epoch millis to a java.time.{@link LocalDate} object, using either the system default timezone or the timezone provided. If the specified ZoneId is not the same as the time base of the epoch millis instant, then conversion errors will occur. Short form ZoneId values like 'CST' can be used, although US Domestic names which specify the daylight savings hours are not supported. The full list of short Ids at @see JavaSE ZoneId Ids Any timezone specifier may be used which can be read by {@link ZoneId#of(String)}

                                      +
                                        +
                                      • +

                                        long -> EpochMillisToJavaLocalDate() -> java.time.LocalDate

                                        +
                                          +
                                        • example: EpochMillisToJavaLocalDate()
                                        • +
                                        • Yields the LocalDate for the system default ZoneId
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> EpochMillisToJavaLocalDate(String: zoneid) -> java.time.LocalDate

                                        +
                                          +
                                        • example: EpochMillisToJavaLocalDate('ECT')
                                        • +
                                        • Yields the LocalDate for the ZoneId entry for 'Europe/Paris'
                                        • +
                                        +
                                      • +
                                      +

                                      EpochMillisToJavaLocalDateTime

                                      +

                                      Converts epoch millis to a java.time.{@link LocalDateTime} object, using either the system default timezone or the timezone provided. If the specified ZoneId is not the same as the time base of the epoch millis instant, then conversion errors will occur. Short form ZoneId values like 'CST' can be used, although US Domestic names which specify the daylight savings hours are not supported. The full list of short Ids at @see JavaSE ZoneId Ids Any timezone specifier may be used which can be read by {@link ZoneId#of(String)}

                                      +
                                        +
                                      • +

                                        long -> EpochMillisToJavaLocalDateTime() -> java.time.LocalDateTime

                                        +
                                          +
                                        • example: EpochMillisToJavaLocalDateTime()
                                        • +
                                        • Yields the LocalDateTime for the system default ZoneId
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> EpochMillisToJavaLocalDateTime(String: zoneid) -> java.time.LocalDateTime

                                        +
                                          +
                                        • example: EpochMillisToJavaLocalDateTime('ECT')
                                        • +
                                        • Yields the LocalDateTime for the ZoneId entry for 'Europe/Paris'
                                        • +
                                        +
                                      • +
                                      +

                                      LongToLocalDateDays

                                      +

                                      Days since Jan 1st 1970

                                      +
                                        +
                                      • long -> LongToLocalDateDays() -> java.time.LocalDate +
                                          +
                                        • example: LongToLocalDateDays()
                                        • +
                                        • take the cycle number and turn it into a LocalDate based on days since 1970
                                        • +
                                        +
                                      • +
                                      +

                                      StartingEpochMillis

                                      +

                                      This function sets the minimum long value to the equivalent unix epoch time in milliseconds. It simply adds the input value to this base value as determined by the provided time specifier. It wraps any overflow within this range as well.

                                      +
                                        +
                                      • long -> StartingEpochMillis(String: baseTimeSpec) -> long +
                                          +
                                        • example: StartingEpochMillis('2017-01-01 23:59:59')
                                        • +
                                        • add the millisecond epoch time of 2017-01-01 23:59:59 to all input values
                                        • +
                                        +
                                      • +
                                      +

                                      StringDateWrapper

                                      +

                                      This function wraps an epoch time in milliseconds into a String as specified in the format. The valid formatters are documented at @see DateTimeFormat API Docs

                                      +
                                        +
                                      • long -> StringDateWrapper(String: format) -> String
                                      • +
                                      +

                                      ToCqlDuration

                                      +

                                      Convert the input double value into a CQL {@link CqlDuration} object, by setting months to zero, and using the fractional part as part of a day, assuming 24-hour days.

                                      +
                                        +
                                      • double -> ToCqlDuration() -> com.datastax.oss.driver.api.core.data.CqlDuration
                                      • +
                                      +

                                      ToCqlDurationNanos

                                      +

                                      Convert the input value into a {@link CqlDuration} by reading the input as total nanoseconds, assuming 30-month days.

                                      +
                                        +
                                      • long -> ToCqlDurationNanos() -> com.datastax.oss.driver.api.core.data.CqlDuration
                                      • +
                                      +

                                      ToDate

                                      +

                                      Convert the input value to a {@code Date}, by multiplying and then dividing the input by the provided parameters.

                                      +
                                        +
                                      • +

                                        long -> ToDate(int: millis_multiplier, int: millis_divisor) -> Date

                                        +
                                          +
                                        • example: ToDate(86400000,2)
                                        • +
                                        • produce two Date values per day
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToDate(int: spacing) -> Date

                                        +
                                          +
                                        • example: ToDate(86400000)
                                        • +
                                        • produce a single Date() per day
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToDate() -> Date

                                        +
                                      • +
                                      +

                                      ToDateTime

                                      +

                                      Convert the input value to a {@code org.joda.time.DateTime}

                                      +
                                        +
                                      • +

                                        long -> ToDateTime(int: spacing, int: repeat_count) -> org.joda.time.DateTime

                                        +
                                      • +
                                      • +

                                        long -> ToDateTime(String: spacing) -> org.joda.time.DateTime

                                        +
                                      • +
                                      • +

                                        long -> ToDateTime() -> org.joda.time.DateTime

                                        +
                                      • +
                                      +

                                      ToEpochTimeUUID

                                      +

                                      Converts a long UTC timestamp in epoch millis form into a Version 1 TimeUUID according to RFC 4122. This means that only one unique value for a timeuuid can be generated for each epoch milli value, even though version 1 TimeUUIDs can normally represent up to 10000 distinct values per millisecond. If you need to access this level of resolution for testing purposes, use {@link ToFinestTimeUUID} instead. This method is to support simple mapping to natural timestamps as we often find in the real world.

                                      +

                                      For the variants that have a String argument in the constructor, this is +a parsable datetime that is used as the base time for all produced values. +Setting this allows you to set the start of the time range for all timeuuid +values produced. All times are parsed for UTC. All time use ISO date ordering, +meaning that the most significant fields always go before the others.

                                      +

                                      The valid formats, in joda specifier form are:

                                      +
                                        +
                                      1. yyyy-MM-dd HH:mm:ss.SSSZ, for example: 2015-02-28 23:30:15.223
                                      2. +
                                      3. yyyy-MM-dd HH:mm:ss, for example 2015-02-28 23:30:15
                                      4. +
                                      5. yyyyMMdd'T'HHmmss.SSSZ, for example: 20150228T233015.223
                                      6. +
                                      7. yyyyMMdd'T'HHmmssZ, for example: 20150228T233015
                                      8. +
                                      9. yyyy-MM-dd, for example: 2015-02-28
                                      10. +
                                      11. yyyyMMdd, for example: 20150228
                                      12. +
                                      13. yyyyMM, for example: 201502
                                      14. +
                                      15. yyyy, for example: 2015
                                      16. +
                                      +
                                        +
                                      • +

                                        long -> ToEpochTimeUUID() -> UUID

                                        +
                                          +
                                        • +

                                          notes: Create version 1 timeuuids with a per-host node and empty clock data. +The node and clock components are seeded from network interface data. In this case, +the clock data is not seeded uniquely.

                                          +
                                        • +
                                        • +

                                          example: ToEpochTimeUUID()

                                          +
                                        • +
                                        • +

                                          basetime 0, computed node data, empty clock data

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToEpochTimeUUID(long: node) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a specific static node and empty clock data. +This is useful for testing so that you can know that values are verifiable, even though +in non-testing practice, you would rely on some form of entropy per-system to provide +more practical dispersion of values over reboots, etc.
                                        • +
                                        +
                                      • +
                                      +

                                      @param node a fixture value for testing that replaces node and clock bits

                                      +
                                        +
                                      • +

                                        example: ToEpochTimeUUID(5234)

                                        +
                                      • +
                                      • +

                                        basetime 0, specified node data (5234), empty clock data

                                        +
                                      • +
                                      • +

                                        long -> ToEpochTimeUUID(long: node, long: clock) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a specific static node and specific clock data. +This is useful for testing so that you can know that values are verifiable, even though +in non-testing practice, you would rely on some form of entropy per-system to provide +more practical dispersion of values over reboots, etc.
                                        • +
                                        +
                                      • +
                                      +

                                      @param node a fixture value for testing that replaces node bits +@param clock a fixture value for testing that replaces clock bits

                                      +
                                        +
                                      • +

                                        example: ToEpochTimeUUID(31,337)

                                        +
                                      • +
                                      • +

                                        basetime 0, specified node data (31) and clock data (337)

                                        +
                                      • +
                                      • +

                                        long -> ToEpochTimeUUID(String: baseSpec) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a per-host node and empty clock data. +The node and clock components are seeded from network interface data. In this case, +the clock data is not seeded uniquely.
                                        • +
                                        +
                                      • +
                                      +

                                      @param baseSpec - a string specification for the base time value

                                      +
                                        +
                                      • +

                                        example: ToEpochTimeUUID('2017-01-01T23:59:59')

                                        +
                                      • +
                                      • +

                                        specified basetime, computed node data, empty clock data

                                        +
                                      • +
                                      • +

                                        long -> ToEpochTimeUUID(String: baseSpec, long: node) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a specific static node and empty clock data. +This is useful for testing so that you can know that values are verifiable, even though +in non-testing practice, you would rely on some form of entropy per-system to provide +more practical dispersion of values over reboots, etc.
                                        • +
                                        +
                                      • +
                                      +

                                      @param baseSpec - a string specification for the base time value +@param node a fixture value for testing that replaces node and clock bits

                                      +
                                        +
                                      • +

                                        example: ToEpochTimeUUID('2012',12345)

                                        +
                                      • +
                                      • +

                                        basetime at start if 2012, with node data 12345, empty clock data

                                        +
                                      • +
                                      • +

                                        long -> ToEpochTimeUUID(String: baseSpec, long: node, long: clock) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a specific static node and specific clock data. +This is useful for testing so that you can know that values are verifiable, even though +in non-testing practice, you would rely on some form of entropy per-system to provide +more practical dispersion of values over reboots, etc.
                                        • +
                                        +
                                      • +
                                      +

                                      @param baseSpec - a string specification for the base time value +@param node a fixture value for testing that replaces node bits +@param clock a fixture value for testing that replaces clock bits

                                      +
                                        +
                                      • example: ToEpochTimeUUID('20171231T1015.243',123,456)
                                      • +
                                      • ms basetime, specified node and clock data
                                      • +
                                      +

                                      ToFinestTimeUUID

                                      +

                                      Converts a count of 100ns intervals from 1582 Julian to a Type1 TimeUUID according to RFC 4122. This allows you to access the finest unit of resolution for the purposes of simulating a large set of unique timeuuid values. This offers 10000 times more unique values per ms than {@link ToEpochTimeUUID}. For the variants that have a String argument in the constructor, this is a parsable datetime that is used as the base time for all produced values. Setting this allows you to set the start of the time range for all timeuuid values produced. All times are parsed for UTC. All time use ISO date ordering, meaning that the most significant fields always go before the others. The valid formats, in joda specifier form are:

                                      +
                                        +
                                      1. yyyy-MM-dd HH:mm:ss.SSSZ, for example: 2015-02-28 23:30:15.223
                                      2. +
                                      3. yyyy-MM-dd HH:mm:ss, for example 2015-02-28 23:30:15
                                      4. +
                                      5. yyyyMMdd'T'HHmmss.SSSZ, for example: 20150228T233015.223
                                      6. +
                                      7. yyyyMMdd'T'HHmmssZ, for example: 20150228T233015
                                      8. +
                                      9. yyyy-MM-dd, for example: 2015-02-28
                                      10. +
                                      11. yyyyMMdd, for example: 20150228
                                      12. +
                                      13. yyyyMM, for example: 201502
                                      14. +
                                      15. yyyy, for example: 2015
                                      16. +
                                      +
                                        +
                                      • +

                                        long -> ToFinestTimeUUID() -> UUID

                                        +
                                          +
                                        • +

                                          notes: Create version 1 timeuuids with a per-host node and empty clock data. +The node and clock components are seeded from network interface data. In this case, +the clock data is not seeded uniquely.

                                          +
                                        • +
                                        • +

                                          example: ToFinestTimeUUID()

                                          +
                                        • +
                                        • +

                                          basetime 0, computed node data, empty clock data

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToFinestTimeUUID(long: node) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a specific static node and empty clock data. +This is useful for testing so that you can know that values are verifiable, even though +in non-testing practice, you would rely on some form of entropy per-system to provide +more practical dispersion of values over reboots, etc.
                                        • +
                                        +
                                      • +
                                      +

                                      @param node a fixture value for testing that replaces node and clock bits

                                      +
                                        +
                                      • +

                                        example: ToFinestTimeUUID(5234)

                                        +
                                      • +
                                      • +

                                        basetime 0, specified node data (5234), empty clock data

                                        +
                                      • +
                                      • +

                                        long -> ToFinestTimeUUID(long: node, long: clock) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a specific static node and specific clock data. +This is useful for testing so that you can know that values are verifiable, even though +in non-testing practice, you would rely on some form of entropy per-system to provide +more practical dispersion of values over reboots, etc.
                                        • +
                                        +
                                      • +
                                      +

                                      @param node a fixture value for testing that replaces node bits +@param clock a fixture value for testing that replaces clock bits

                                      +
                                        +
                                      • +

                                        example: ToFinestTimeUUID(31,337)

                                        +
                                      • +
                                      • +

                                        basetime 0, specified node data (31) and clock data (337)

                                        +
                                      • +
                                      • +

                                        long -> ToFinestTimeUUID(String: baseTimeSpec) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a per-host node and empty clock data. +The node and clock components are seeded from network interface data. In this case, +the clock data is not seeded uniquely.
                                        • +
                                        +
                                      • +
                                      +

                                      @param baseTimeSpec - a string specification for the base time value

                                      +
                                        +
                                      • +

                                        example: ToFinestTimeUUID('2017-01-01T23:59:59')

                                        +
                                      • +
                                      • +

                                        specified basetime, computed node data, empty clock data

                                        +
                                      • +
                                      • +

                                        long -> ToFinestTimeUUID(String: baseTimeSpec, long: node) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a specific static node and empty clock data. +This is useful for testing so that you can know that values are verifiable, even though +in non-testing practice, you would rely on some form of entropy per-system to provide +more practical dispersion of values over reboots, etc.
                                        • +
                                        +
                                      • +
                                      +

                                      @param baseTimeSpec - a string specification for the base time value +@param node a fixture value for testing that replaces node and clock bits

                                      +
                                        +
                                      • +

                                        example: ToFinestTimeUUID('2012',12345)

                                        +
                                      • +
                                      • +

                                        basetime at start if 2012, with node data 12345, empty clock data

                                        +
                                      • +
                                      • +

                                        long -> ToFinestTimeUUID(String: baseTimeSpec, long: node, long: clock) -> UUID

                                        +
                                          +
                                        • notes: Create version 1 timeuuids with a specific static node and specific clock data. +This is useful for testing so that you can know that values are verifiable, even though +in non-testing practice, you would rely on some form of entropy per-system to provide +more practical dispersion of values over reboots, etc.
                                        • +
                                        +
                                      • +
                                      +

                                      @param node a fixture value for testing that replaces node bits +@param clock a fixture value for testing that replaces clock bits +@param baseTimeSpec - a string specification for the base time value

                                      +
                                        +
                                      • example: ToFinestTimeUUID('20171231T1015.243',123,456)
                                      • +
                                      • ms basetime, specified node and clock data
                                      • +
                                      +

                                      ToJavaInstant

                                      +

                                      Convert the input epoch millisecond to a {@code Java Instant}, by multiplying and then dividing by the provided parameters. This is in contrast to the ToJodaInstant function which does the same thing using the Joda API Type.

                                      +
                                        +
                                      • +

                                        long -> ToJavaInstant(int: millis_multiplier, int: millis_divisor) -> java.time.Instant

                                        +
                                          +
                                        • example: ToDate(86400000,2)
                                        • +
                                        • produce two Date values per day
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToJavaInstant(int: spacing) -> java.time.Instant

                                        +
                                          +
                                        • example: ToDate(86400000)
                                        • +
                                        • produce a single Date() per day
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToJavaInstant() -> java.time.Instant

                                        +
                                      • +
                                      +

                                      ToJodaDateTime

                                      +

                                      Convert the input value to a {@code org.joda.time.DateTime}

                                      +
                                        +
                                      • +

                                        long -> ToJodaDateTime(int: spacing, int: repeat_count) -> org.joda.time.DateTime

                                        +
                                      • +
                                      • +

                                        long -> ToJodaDateTime(String: spacing) -> org.joda.time.DateTime

                                        +
                                      • +
                                      • +

                                        long -> ToJodaDateTime() -> org.joda.time.DateTime

                                        +
                                      • +
                                      +

                                      ToJodaInstant

                                      +

                                      Convert the input epoch millisecond to a {@code JodaTime Instant}, by multiplying and then dividing by the provided parameters. This is in contrast to the ToJavaInstant function which does the same thing, only using the Java API type.

                                      +
                                        +
                                      • +

                                        long -> ToJodaInstant(int: millis_multiplier, int: millis_divisor) -> org.joda.time.Instant

                                        +
                                          +
                                        • example: ToDate(86400000,2)
                                        • +
                                        • produce two Date values per day
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToJodaInstant(int: spacing) -> org.joda.time.Instant

                                        +
                                          +
                                        • example: ToDate(86400000)
                                        • +
                                        • produce a single Date() per day
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToJodaInstant() -> org.joda.time.Instant

                                        +
                                      • +
                                      +

                                      ToLocalTime

                                      +

                                      Convert the input epoch millisecond to a {@code Java Instant}, by multiplying and then dividing by the provided parameters, then convert the result to a java {@link LocalTime}.

                                      +
                                        +
                                      • +

                                        long -> ToLocalTime(int: millis_multiplier, int: millis_divisor, String: zoneid) -> java.time.LocalTime

                                        +
                                      • +
                                      • +

                                        long -> ToLocalTime(int: millis_multiplier, int: millis_divisor) -> java.time.LocalTime

                                        +
                                          +
                                        • example: ToLocalTime(86400000,2)
                                        • +
                                        • produce two LocalTime values per day
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToLocalTime(int: spacing) -> java.time.LocalTime

                                        +
                                          +
                                        • example: ToLocalTime(86400000)
                                        • +
                                        • produce a single LocalTime per day
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToLocalTime() -> java.time.LocalTime

                                        +
                                      • +
                                      +

                                      ToMillisAtStartOfDay

                                      +

                                      Return the epoch milliseconds at the start of the day for the given epoch milliseconds.

                                      +
                                        +
                                      • +

                                        long -> ToMillisAtStartOfDay() -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfDay()
                                        • +
                                        • return millisecond epoch time of the start of the day of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfDay(String: timezoneId) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfDay('America/Chicago')
                                        • +
                                        • return millisecond epoch time of the start of the day of the provided millisecond epoch time, using timezone America/Chicago
                                        • +
                                        +
                                      • +
                                      +

                                      ToMillisAtStartOfHour

                                      +

                                      Return the epoch milliseconds at the start of the hour for the given epoch milliseconds.

                                      +
                                        +
                                      • +

                                        long -> ToMillisAtStartOfHour() -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfHour()
                                        • +
                                        • return millisecond epoch time of the start of the hour of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfHour(String: timezoneId) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfHour('America/Chicago')
                                        • +
                                        • return millisecond epoch time of the start of the hour of the provided millisecond epoch time, using timezone America/Chicago
                                        • +
                                        +
                                      • +
                                      +

                                      ToMillisAtStartOfMinute

                                      +

                                      Return the epoch milliseconds at the start of the minute for the given epoch milliseconds.

                                      +
                                        +
                                      • +

                                        long -> ToMillisAtStartOfMinute() -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfMinute()
                                        • +
                                        • return millisecond epoch time of the start of the minute of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfMinute(String: timezoneId) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfMinute('America/Chicago')
                                        • +
                                        • return millisecond epoch time of the start of the minute of the provided millisecond epoch time, using timezone America/Chicago
                                        • +
                                        +
                                      • +
                                      +

                                      ToMillisAtStartOfMonth

                                      +

                                      Return the epoch milliseconds at the start of the month for the given epoch milliseconds.

                                      +
                                        +
                                      • +

                                        long -> ToMillisAtStartOfMonth() -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfMonth()
                                        • +
                                        • return millisecond epoch time of the start of the month of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfMonth(String: timezoneId) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfMonth('America/Chicago')
                                        • +
                                        • return millisecond epoch time of the start of the month of the provided millisecond epoch time, using timezone America/Chicago
                                        • +
                                        +
                                      • +
                                      +

                                      ToMillisAtStartOfNamedWeekDay

                                      +

                                      Return the epoch milliseconds at the start of the most recent day that falls on the given weekday for the given epoch milliseconds, including the current day if valid.

                                      +
                                        +
                                      • +

                                        long -> ToMillisAtStartOfNamedWeekDay() -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfNamedWeekDay()
                                        • +
                                        • return millisecond epoch time of the start of the most recent Monday (possibly the day-of) of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfNamedWeekDay(String: weekday) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfNamedWeekDay('Wednesday')
                                        • +
                                        • return millisecond epoch time of the start of the most recent Wednesday (possibly the day-of) of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfNamedWeekDay(String: weekday, String: timezoneId) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfNamedWeekDay('Saturday','America/Chicago'')
                                        • +
                                        • return millisecond epoch time of the start of the most recent Saturday (possibly the day-of) of the provided millisecond epoch time, using timezone America/Chicago
                                        • +
                                        +
                                      • +
                                      +

                                      ToMillisAtStartOfNextDay

                                      +

                                      Return the epoch milliseconds at the start of the day after the day for the given epoch milliseconds.

                                      +
                                        +
                                      • +

                                        long -> ToMillisAtStartOfNextDay() -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfNextDay()
                                        • +
                                        • return millisecond epoch time of the start of next day (not including day-of) of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfNextDay(String: timezoneId) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfNextDay('America/Chicago')
                                        • +
                                        • return millisecond epoch time of the start of the next day (not including day-of) of the provided millisecond epoch time, using timezone America/Chicago
                                        • +
                                        +
                                      • +
                                      +

                                      ToMillisAtStartOfNextNamedWeekDay

                                      +

                                      Return the epoch milliseconds at the start of the next day that falls on the given weekday for the given epoch milliseconds, not including the current day.

                                      +
                                        +
                                      • +

                                        long -> ToMillisAtStartOfNextNamedWeekDay() -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfNextNamedWeekDay()
                                        • +
                                        • return millisecond epoch time of the start of the next Monday (not the day-of) of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfNextNamedWeekDay(String: weekday) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfNextNamedWeekDay('Wednesday')
                                        • +
                                        • return millisecond epoch time of the start of the next Wednesday (not the day-of) of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfNextNamedWeekDay(String: weekday, String: timezoneId) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfNextNamedWeekDay('Saturday','America/Chicago'')
                                        • +
                                        • return millisecond epoch time of the start of the next Saturday (not the day-of) of the provided millisecond epoch time, using timezone America/Chicago
                                        • +
                                        +
                                      • +
                                      +

                                      ToMillisAtStartOfSecond

                                      +

                                      Return the epoch milliseconds at the start of the second for the given epoch milliseconds.

                                      +
                                        +
                                      • +

                                        long -> ToMillisAtStartOfSecond() -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfSecond()
                                        • +
                                        • return millisecond epoch time of the start of the second of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfSecond(String: timezoneId) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfSecond('America/Chicago')
                                        • +
                                        • return millisecond epoch time of the start of the second of the provided millisecond epoch time, using timezone America/Chicago
                                        • +
                                        +
                                      • +
                                      +

                                      ToMillisAtStartOfYear

                                      +

                                      Return the epoch milliseconds at the start of the year for the given epoch milliseconds.

                                      +
                                        +
                                      • +

                                        long -> ToMillisAtStartOfYear() -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfYear()
                                        • +
                                        • return millisecond epoch time of the start of the year of the provided millisecond epoch time, assuming UTC
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ToMillisAtStartOfYear(String: timezoneId) -> long

                                        +
                                          +
                                        • example: ToMillisAtStartOfYear('America/Chicago')
                                        • +
                                        • return millisecond epoch time of the start of the year of the provided millisecond epoch time, using timezone America/Chicago
                                        • +
                                        +
                                      • +
                                      +

                                      ToTimeUUIDMax

                                      +

                                      Converts a long timestamp in epoch millis form into a Version 1 TimeUUID according to RFC 4122. This form uses {@link Uuids#endOf(long)} (long)}

                                      +
                                        +
                                      • long -> ToTimeUUIDMax() -> UUID
                                      • +
                                      +

                                      ToTimeUUIDMin

                                      +

                                      Converts a long timestamp in epoch millis form into a Version 1 TimeUUID according to RFC 4122. This form uses {@link Uuids#startOf(long)}

                                      +
                                        +
                                      • long -> ToTimeUUIDMin() -> UUID
                                      • +
                                      + +

                                      Back to top

                                      +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-diagnostics/index.html b/reference/bindings/funcref-diagnostics/index.html new file mode 100644 index 000000000..13727d24b --- /dev/null +++ b/reference/bindings/funcref-diagnostics/index.html @@ -0,0 +1,243 @@ + + + + + + + + + + + + + + + + diagnostic functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      Diagnostic functions can be used to help you construct the right VirtData recipe.

                                      +

                                      Show

                                      +

                                      Show diagnostic values for the thread-local variable map.

                                      +
                                        +
                                      • +

                                        long -> Show() -> String

                                        +
                                          +
                                        • example: Show()
                                        • +
                                        • Show all values in a json-like format
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Show(String[]...: names) -> String

                                        +
                                          +
                                        • example: Show('foo')
                                        • +
                                        • Show only the 'foo' value in a json-like format
                                        • +
                                        • example: Show('foo','bar')
                                        • +
                                        • Show the 'foo' and 'bar' values in a json-like format
                                        • +
                                        +
                                      • +
                                      • +

                                        Object -> Show() -> String

                                        +
                                          +
                                        • example: Show()
                                        • +
                                        • Show all values in a json-like format
                                        • +
                                        +
                                      • +
                                      • +

                                        Object -> Show(String[]...: names) -> String

                                        +
                                          +
                                        • example: Show('foo')
                                        • +
                                        • Show only the 'foo' value in a json-like format
                                        • +
                                        • example: Show('foo','bar')
                                        • +
                                        • Show the 'foo' and 'bar' values in a json-like format
                                        • +
                                        +
                                      • +
                                      +

                                      ToLongFunction

                                      +

                                      Adapts any compatible {@link FunctionalInterface} type to a LongFunction, for use with higher-order functions, when they require a LongFunction as an argument. Some of the higher-order functions within this library specifically require a LongFunction as an argument, while some of the other functions are provided in semantically equivalent forms with compatible types which can't be converted directly or automatically by Java. In such cases, those types of functions can be wrapped with the forms described here in order to allow the inner and outer functions to work together.

                                      +
                                        +
                                      • +

                                        long -> ToLongFunction(function.LongUnaryOperator: op) -> Object

                                        +
                                      • +
                                      • +

                                        long -> ToLongFunction(function.Function<Long,Long>: op) -> Object

                                        +
                                      • +
                                      • +

                                        long -> ToLongFunction(function.LongToIntFunction: op) -> Object

                                        +
                                      • +
                                      • +

                                        long -> ToLongFunction(function.LongToDoubleFunction: op) -> Object

                                        +
                                      • +
                                      • +

                                        long -> ToLongFunction(function.LongFunction<?>: func) -> Object

                                        +
                                      • +
                                      +

                                      ToLongUnaryOperator

                                      +

                                      Adapts any compatible {@link FunctionalInterface} type to a LongUnaryOperator, for use with higher-order functions, when they require a LongUnaryOperator as an argument. Some of the higher-order functions within this library specifically require a LongUnaryOperator as an argument, while some of the other functions are provided in semantically equivalent forms with compatible types which can't be converted directly or automatically by Java. In such cases, those types of functions can be wrapped with the forms described here in order to allow the inner and outer functions to work together.

                                      +
                                        +
                                      • +

                                        long -> ToLongUnaryOperator(function.LongFunction: f) -> long

                                        +
                                      • +
                                      • +

                                        long -> ToLongUnaryOperator(function.Function<Long,Long>: f) -> long

                                        +
                                      • +
                                      • +

                                        long -> ToLongUnaryOperator(function.LongUnaryOperator: f) -> long

                                        +
                                      • +
                                      +

                                      TypeOf

                                      +

                                      Yields the class of the resulting type in String form.

                                      +
                                        +
                                      • Object -> TypeOf() -> String
                                      • +
                                      + +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-distributions/index.html b/reference/bindings/funcref-distributions/index.html new file mode 100644 index 000000000..b99dadfcc --- /dev/null +++ b/reference/bindings/funcref-distributions/index.html @@ -0,0 +1,683 @@ + + + + + + + + + + + + + + + + distribution functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      All of the distributions that are provided in the Apache Commons Math +project are supported here, in multiple forms.

                                      +

                                      Continuous or Discrete

                                      +

                                      These distributions break down into two main categories:

                                      +

                                      Continuous Distributions

                                      +

                                      These are distributions over real numbers like 23.4323, with continuity across the values. Each of the continuous +distributions can provide samples that fall on an interval of the real number line. Continuous probability distributions +include the Normal distribution, and the Exponential distribution, among many others.

                                      +

                                      Discrete Distributions

                                      +

                                      Discrete distributions, also known as integer distributions have only whole-number valued samples. These distributions +include the Binomial distribution, the Zipf distribution, and the Poisson distribution, among others.

                                      +

                                      Hashed or Mapped

                                      +

                                      hashed samples

                                      +

                                      Generally, you will want to "randomly sample" from a probability distribution. This is handled automatically by the +functions below if you do not override the defaults. The hash mode is the default sampling mode for probability +distributions. This is accomplished by hashing the input before using the resulting value with the sampling curve. +This is called the hash sampling mode by VirtData. You can put hash into the modifiers as explained below if you +want to document it explicitly.

                                      +

                                      mapped samples

                                      +

                                      The method used to sample from these distributions depends on a mathematical function called the cumulative probability +density function, or more specifically the inverse of it. Having this function computed over some interval allows one to +sample the shape of a distribution progressively if desired. In other words, it allows for some percentile-like view +of values within a given probability distribution. This mode of using the inverse cumulative density function is known +as the map mode in VirtData, as it allows one to map a unit interval variate in a deterministic way to a density +sampling curve. To enable this mode, simply pass map as one of the function modifiers for any function in this +category.

                                      +

                                      Interpolated or Computed Samples

                                      +

                                      When sampling from mathematical models of probability densities, +performance between different densities can vary drastically. This means +that you may end up perturbing the results of your test in an unexpected +way simply by changing parameters of your testing distributions. Even +worse, some densities have painful corner cases in performance, like +'Zipf', which can make tests unbearably slow and flawed as they chew up +CPU resources.

                                      +

                                      NOTE: +Functions like 'Zipf' can still take a long time to initialize for certain +parameters. If you are seeing a workload that seems to hang while +initializing, it might be computing complex integrals for large parameters +of Zipf. We hope to pre-compute and cache these at a future time to avoid +this type of impact. For now, just be aware that some parameters on some +density curves can be expensive to compute even during initialization.

                                      +

                                      Interpolated Samples

                                      +

                                      For this reason, interpolation is built-in to these sampling functions. The default mode is interpolate. This +means that the sampling function is pre-computed over 1000 equidistant points in the unit interval (0.0,1.0), and the +result is shared among all threads as a look-up-table for interpolation. This makes all statistical sampling functions +perform nearly identically at runtime (after initialization, a one time cost). This does have the minor side effect of a +little loss in accuracy, but the difference is generally negligible for nearly all performance testing cases.

                                      +

                                      Infinite or Finite

                                      +

                                      For interpolated samples from continuous distributions, you also have the option of including or +excluding infinite values which may occur in some distributions. If you want to include them, +use infinite, or finite to explicitly avoid them (the default). Specifying 'infinite' +doesn't guarantee that you will see +Infinity or -Infinity, only that they are allowed. The +Normal distribution often contains -Infinity and +Infinity, for example, due to the function +used to estimate its cumulative distribution. These values can often be valuable in finding +corner cases which should be treated uniformly according to +IEEE 754.

                                      +

                                      Clamp or Noclamp

                                      +

                                      For interpolated samples from continuous distributions, you also have the option of clamping the +allowed values to the valid range for the integral data type used as input. To clamp the output +values to the range (Long.MIN_VALUE,Long.MAX_VALUE) for long->double functions, or to (Integer. +MIN_VALUE,Integer.MAX_VALUE) for int-double functions, specify clamp, which is also the default. +To explicitly disable this, use noclamp. This is useful when you know the downstream functions +will only work with a certain range of values without truncating conversions. When you are using +double values natively on the downstream functions, use noclamp to avoid limiting the domain of +values in your test data. (In this case, you might also consider infinite).

                                      +

                                      Computed Samples

                                      +

                                      Conversely, compute mode sampling calls the sampling function every time a sample is needed. This affords a little +more accuracy, but is generally not preferable to the default interpolated mode. You'll know if you need computed +samples. Otherwise, it's best to stick with interpolation so that you spend more time testing your target system and +less time testing your data generation functions.

                                      +

                                      Input Range

                                      +

                                      All of these functions take a long as the input value for sampling. This is similar to how the unit interval (0.0,1.0) +is used in mathematics and statistics, but more tailored to modern system capabilities. Instead of using the unit +interval, we simply use the interval of all positive longs. This provides more compatibility with other functions in +VirtData, including hashing functions. Internally, this value is automatically converted to a unit interval variate as +needed to work well with the distributions from Apache Math.

                                      +

                                      Beta

                                      +

                                      @see Wikipedia: Beta distribution @see Commons JavaDoc: BetaDistribution

                                      +
                                        +
                                      • +

                                        long -> Beta(double: alpha, double: beta, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> Beta(double: alpha, double: beta, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Binomial

                                      +

                                      @see Wikipedia: Binomial distribution @see Commons JavaDoc: BinomialDistribution

                                      +
                                        +
                                      • +

                                        int -> Binomial(int: trials, double: p, String[]...: modslist) -> int

                                        +
                                      • +
                                      • +

                                        long -> Binomial(int: trials, double: p, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        int -> Binomial(int: trials, double: p, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        long -> Binomial(int: trials, double: p, String[]...: modslist) -> int

                                        +
                                      • +
                                      +

                                      Cauchy

                                      +

                                      @see Wikipedia: Cauchy_distribution @see Commons Javadoc: CauchyDistribution

                                      +
                                        +
                                      • +

                                        long -> Cauchy(double: median, double: scale, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> Cauchy(double: median, double: scale, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      ChiSquared

                                      +

                                      @see Wikipedia: Chi-squared distribution @see Commons JavaDoc: ChiSquaredDistribution

                                      +
                                        +
                                      • +

                                        long -> ChiSquared(double: degreesOfFreedom, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> ChiSquared(double: degreesOfFreedom, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      CoinFunc

                                      +

                                      This is a higher-order function which takes an input value, and flips a coin. The first parameter is used as the threshold for choosing a function. If the sample values derived from the input is lower than the threshold value, then the first following function is used, and otherwise the second is used. For example, if the threshold is 0.23, and the input value is hashed and sampled in the unit interval to 0.43, then the second of the two provided functions will be used. The input value does not need to be hashed beforehand, since the user may need to use the full input value before hashing as the input to one or both of the functions. This function will accept either a LongFunction or a {@link Function} or a LongUnaryOperator in either position. If necessary, use {@link function.ToLongFunction} to adapt other function forms to be compatible with these signatures.

                                      +
                                        +
                                      • Long -> CoinFunc(double: threshold, Object: first, Object: second) -> Object +
                                          +
                                        • example: CoinFunc(0.15,NumberNameToString(),Combinations('A:1:B:23'))
                                        • +
                                        • use the first function 15% of the time
                                        • +
                                        +
                                      • +
                                      +

                                      ConstantContinuous

                                      +

                                      Always yields the same value. @see Commons JavaDoc: ConstantContinuousDistribution

                                      +
                                        +
                                      • +

                                        long -> ConstantContinuous(double: value, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> ConstantContinuous(double: value, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Enumerated

                                      +

                                      Creates a probability density given the values and optional weights provided, in "value:weight value:weight ..." form. The weight can be elided for any value to use the default weight of 1.0d. @see Commons JavaDoc: EnumeratedRealDistribution

                                      +
                                        +
                                      • +

                                        int -> Enumerated(String: data, String[]...: mods) -> double

                                        +
                                          +
                                        • example: Enumerated('1 2 3 4 5 6')
                                        • +
                                        • a fair six-sided die roll
                                        • +
                                        • example: Enumerated('1:2.0 2 3 4 5 6')
                                        • +
                                        • an unfair six-sided die roll, where 1 has probability mass 2.0, and everything else has only 1.0
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Enumerated(String: data, String[]...: mods) -> double

                                        +
                                          +
                                        • example: Enumerated('1 2 3 4 5 6')
                                        • +
                                        • a fair 6-sided die
                                        • +
                                        • example: Enumerated('1:2.0 2 3 4 5:0.5 6:0.5')
                                        • +
                                        • an unfair fair 6-sided die, where ones are twice as likely, and fives and sixes are half as likely
                                        • +
                                        +
                                      • +
                                      +

                                      Exponential

                                      +

                                      @see Wikipedia: Exponential distribution @see Commons JavaDoc: ExponentialDistribution

                                      +
                                        +
                                      • +

                                        long -> Exponential(double: mean, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> Exponential(double: mean, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      F

                                      +

                                      @see Wikipedia: F-distribution @see Commons JavaDoc: FDistribution @see Mathworld: F-Distribution

                                      +
                                        +
                                      • +

                                        int -> F(double: numeratorDegreesOfFreedom, double: denominatorDegreesOfFreedom, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        long -> F(double: numeratorDegreesOfFreedom, double: denominatorDegreesOfFreedom, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Gamma

                                      +

                                      @see Wikipedia: Gamma distribution @see Commons JavaDoc: GammaDistribution

                                      +
                                        +
                                      • +

                                        long -> Gamma(double: shape, double: scale, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> Gamma(double: shape, double: scale, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Geometric

                                      +

                                      @see Wikipedia: Geometric distribution @see Commons JavaDoc: GeometricDistribution

                                      +
                                        +
                                      • +

                                        int -> Geometric(double: p, String[]...: modslist) -> int

                                        +
                                      • +
                                      • +

                                        long -> Geometric(double: p, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        int -> Geometric(double: p, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        long -> Geometric(double: p, String[]...: modslist) -> int

                                        +
                                      • +
                                      +

                                      Gumbel

                                      +

                                      @see Wikipedia: Gumbel distribution @see Commons JavaDoc: GumbelDistribution

                                      +
                                        +
                                      • +

                                        long -> Gumbel(double: mu, double: beta, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> Gumbel(double: mu, double: beta, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Hypergeometric

                                      +

                                      @see Wikipedia: Hypergeometric distribution @see Commons JavaDoc: HypergeometricDistribution

                                      +
                                        +
                                      • +

                                        int -> Hypergeometric(int: populationSize, int: numberOfSuccesses, int: sampleSize, String[]...: modslist) -> int

                                        +
                                      • +
                                      • +

                                        int -> Hypergeometric(int: populationSize, int: numberOfSuccesses, int: sampleSize, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        long -> Hypergeometric(int: populationSize, int: numberOfSuccesses, int: sampleSize, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        long -> Hypergeometric(int: populationSize, int: numberOfSuccesses, int: sampleSize, String[]...: modslist) -> int

                                        +
                                      • +
                                      +

                                      Laplace

                                      +

                                      @see Wikipedia: Laplace distribution @see Commons JavaDoc: LaplaceDistribution

                                      +
                                        +
                                      • +

                                        long -> Laplace(double: mu, double: beta, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> Laplace(double: mu, double: beta, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Levy

                                      +

                                      @see Wikipedia: Lévy distribution @see Commons JavaDoc: LevyDistribution

                                      +
                                        +
                                      • +

                                        int -> Levy(double: mu, double: c, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        long -> Levy(double: mu, double: c, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      LogNormal

                                      +

                                      @see Wikipedia: Log-normal distribution @see Commons JavaDoc: LogNormalDistribution

                                      +
                                        +
                                      • +

                                        long -> LogNormal(double: scale, double: shape, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> LogNormal(double: scale, double: shape, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Logistic

                                      +

                                      @see Wikipedia: Logistic distribution @see Commons JavaDoc: LogisticDistribution

                                      +
                                        +
                                      • +

                                        int -> Logistic(double: mu, double: scale, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        long -> Logistic(double: mu, double: scale, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Nakagami

                                      +

                                      @see Wikipedia: Nakagami distribution @see Commons JavaDoc: NakagamiDistribution

                                      +
                                        +
                                      • +

                                        long -> Nakagami(double: mu, double: omega, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> Nakagami(double: mu, double: omega, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Normal

                                      +

                                      @see Wikipedia: Normal distribution @see Commons JavaDoc: NormalDistribution

                                      +
                                        +
                                      • +

                                        long -> Normal(double: mean, double: sd, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> Normal(double: mean, double: sd, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Pareto

                                      +

                                      @see Wikipedia: Pareto distribution @see Commons JavaDoc: ParetoDistribution

                                      +
                                        +
                                      • +

                                        int -> Pareto(double: scale, double: shape, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        long -> Pareto(double: scale, double: shape, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Pascal

                                      +

                                      @see Commons JavaDoc: PascalDistribution @see Wikipedia: Negative binomial distribution

                                      +
                                        +
                                      • +

                                        long -> Pascal(int: r, double: p, String[]...: modslist) -> int

                                        +
                                      • +
                                      • +

                                        int -> Pascal(int: r, double: p, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        long -> Pascal(int: r, double: p, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        int -> Pascal(int: r, double: p, String[]...: modslist) -> int

                                        +
                                      • +
                                      +

                                      Poisson

                                      +

                                      @see Wikipedia: Poisson distribution @see Commons JavaDoc: PoissonDistribution

                                      +
                                        +
                                      • +

                                        long -> Poisson(double: p, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        int -> Poisson(double: p, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        int -> Poisson(double: p, String[]...: modslist) -> int

                                        +
                                      • +
                                      • +

                                        long -> Poisson(double: p, String[]...: modslist) -> int

                                        +
                                      • +
                                      +

                                      T

                                      +

                                      @see Wikipedia: Student's t-distribution @see Commons JavaDoc: TDistribution

                                      +
                                        +
                                      • +

                                        int -> T(double: degreesOfFreedom, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        long -> T(double: degreesOfFreedom, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Triangular

                                      +

                                      @see Wikipedia: Triangular distribution @see Commons JavaDoc: TriangularDistribution

                                      +
                                        +
                                      • +

                                        long -> Triangular(double: a, double: c, double: b, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        int -> Triangular(double: a, double: c, double: b, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Uniform

                                      +

                                      @see Wikipedia: Uniform distribution (continuous) @see Commons JavaDoc: UniformContinuousDistribution

                                      +
                                        +
                                      • +

                                        int -> Uniform(double: lower, double: upper, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        long -> Uniform(int: lower, int: upper, String[]...: modslist) -> int

                                        +
                                      • +
                                      • +

                                        int -> Uniform(int: lower, int: upper, String[]...: modslist) -> int

                                        +
                                      • +
                                      • +

                                        int -> Uniform(int: lower, int: upper, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        long -> Uniform(int: lower, int: upper, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        long -> Uniform(double: lower, double: upper, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      Weibull

                                      +

                                      @see Wikipedia: Weibull distribution @see Wolfram Mathworld: Weibull Distribution @see Commons Javadoc: WeibullDistribution

                                      +
                                        +
                                      • +

                                        int -> Weibull(double: alpha, double: beta, String[]...: mods) -> double

                                        +
                                      • +
                                      • +

                                        long -> Weibull(double: alpha, double: beta, String[]...: mods) -> double

                                        +
                                      • +
                                      +

                                      WeightedFuncs

                                      +

                                      Allows for easy branching over multiple functions with specific weights.

                                      +
                                        +
                                      • long -> WeightedFuncs(Object[]...: weightsAndFuncs) -> Object
                                      • +
                                      +

                                      Zipf

                                      +

                                      @see Wikipedia: Zipf's Law @see Commons JavaDoc: ZipfDistribution

                                      +
                                        +
                                      • +

                                        long -> Zipf(int: numberOfElements, double: exponent, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        int -> Zipf(int: numberOfElements, double: exponent, String[]...: modslist) -> long

                                        +
                                      • +
                                      • +

                                        long -> Zipf(int: numberOfElements, double: exponent, String[]...: modslist) -> int

                                        +
                                      • +
                                      • +

                                        int -> Zipf(int: numberOfElements, double: exponent, String[]...: modslist) -> int

                                        +
                                      • +
                                      + +

                                      Back to top

                                      +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-experimental/index.html b/reference/bindings/funcref-experimental/index.html new file mode 100644 index 000000000..0393155a5 --- /dev/null +++ b/reference/bindings/funcref-experimental/index.html @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + TokenMapFileCycle | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      TokenMapFileCycle

                                      +

                                      Utility function used for advanced data generation experiments.

                                      +
                                        +
                                      • int -> TokenMapFileCycle(String: filename, boolean: loopdata, boolean: ascending) -> long
                                      • +
                                      +

                                      TokenMapFileNextCycle

                                      +

                                      Utility function used for advanced data generation experiments.

                                      +
                                        +
                                      • int -> TokenMapFileNextCycle(String: filename, boolean: loopdata, boolean: ascending) -> long
                                      • +
                                      +

                                      TokenMapFileNextToken

                                      +

                                      Utility function used for advanced data generation experiments.

                                      +
                                        +
                                      • int -> TokenMapFileNextToken(String: filename, boolean: loopdata, boolean: ascending) -> long
                                      • +
                                      +

                                      TokenMapFileToken

                                      +

                                      Utility function used for advanced data generation experiments.

                                      +
                                        +
                                      • int -> TokenMapFileToken(String: filename, boolean: loopdata, boolean: ascending) -> long
                                      • +
                                      +

                                      TriangularStep

                                      +

                                      Compute a value which increases monotonically with respect to the cycle value. +All values for f(X+(m>=0)) will be equal or greater than f(X). In effect, this +means that with a sequence of monotonic inputs, the results will be monotonic as +well as clustered. The values will approximate input/average, but will vary in frequency +around a simple binomial distribution.

                                      +

                                      The practical effect of this is to be able to compute a sequence of values +over inputs which can act as foreign keys, but which are effectively ordered.

                                      +

                                      Call for Ideas

                                      +

                                      Due to the complexity of generalizing this as a pure function over other distributions, +this is the only function of this type for now. If you are interested in this problem +domain and have some suggestions for how to extend it to other distributions, please +join the project or let us know.

                                      +
                                        +
                                      • +

                                        long -> TriangularStep(long: average, long: variance) -> long

                                        +
                                          +
                                        • example: TriangularStep(100,20)
                                        • +
                                        • Create a sequence of values where the average is 100, but the range of values is between 80 and 120.
                                        • +
                                        • example: TriangularStep(80,10)
                                        • +
                                        • Create a sequence of values where the average is 80, but the range of values is between 70 and 90.
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> TriangularStep(long: average) -> long

                                        +
                                      • +
                                      + +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-functional/index.html b/reference/bindings/funcref-functional/index.html new file mode 100644 index 000000000..57376356f --- /dev/null +++ b/reference/bindings/funcref-functional/index.html @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + flow functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      These functions help combine other functions into higher-order functions when needed.

                                      +

                                      Expr

                                      +

                                      Allow for the use of arbitrary expressions according to the MVEL expression language. Variables that have been set by a Save function are available to be used in this function. The variable name cycle is reserved, and is always equal to the current input value. This is not the same in every case as the current cycle of an operation. It could be different if there are preceding functions which modify the input value.

                                      +
                                        +
                                      • +

                                        long -> Expr(String: expr) -> int

                                        +
                                      • +
                                      • +

                                        long -> Expr(String: expr) -> long

                                        +
                                      • +
                                      • +

                                        long -> Expr(String: expr) -> String

                                        +
                                      • +
                                      • +

                                        long -> Expr(String: expr) -> UUID

                                        +
                                      • +
                                      • +

                                        int -> Expr(String: expr) -> int

                                        +
                                      • +
                                      • +

                                        double -> Expr(String: expr) -> double

                                        +
                                      • +
                                      • +

                                        long -> Expr(String: expr) -> Object

                                        +
                                      • +
                                      +

                                      IntFlow

                                      +

                                      Combine multiple IntUnaryOperators into a single function.

                                      +
                                        +
                                      • int -> IntFlow(function.IntUnaryOperator[]...: ops) -> int
                                      • +
                                      +

                                      LongFlow

                                      +

                                      Combine multiple LongUnaryOperators into a single function.

                                      +
                                        +
                                      • long -> LongFlow(function.LongUnaryOperator[]...: ops) -> long +
                                          +
                                        • example: LongFlow(Add(3),Mul(6))
                                        • +
                                        • Create an integer operator which adds 3 and multiplies the result by 6
                                        • +
                                        +
                                      • +
                                      +

                                      StringFlow

                                      +

                                      Combine multiple String functions together into one function.

                                      +
                                        +
                                      • String -> StringFlow(function.Function<String,String>[]...: funcs) -> String
                                      • +
                                      + +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-general/index.html b/reference/bindings/funcref-general/index.html new file mode 100644 index 000000000..618096ebc --- /dev/null +++ b/reference/bindings/funcref-general/index.html @@ -0,0 +1,1419 @@ + + + + + + + + + + + + + + + + general functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      These functions have no particular category, so they ended up here by default.

                                      +

                                      Add

                                      +

                                      Adds a value to the input.

                                      +
                                        +
                                      • +

                                        double -> Add(double: addend) -> double

                                        +
                                      • +
                                      • +

                                        long -> Add(int: addend) -> int

                                        +
                                      • +
                                      • +

                                        long -> Add(long: addend) -> long

                                        +
                                      • +
                                      • +

                                        int -> Add(int: addend) -> int

                                        +
                                          +
                                        • example: Add(23)
                                        • +
                                        • adds integer 23 to the input integer value
                                        • +
                                        +
                                      • +
                                      +

                                      AddCycleRange

                                      +

                                      Adds a cycle range to the input, producing an increasing sawtooth-like output.

                                      +
                                        +
                                      • +

                                        long -> AddCycleRange(int: maxValue) -> int

                                        +
                                      • +
                                      • +

                                        long -> AddCycleRange(int: minValue, int: maxValue) -> int

                                        +
                                      • +
                                      • +

                                        long -> AddCycleRange(long: maxValue) -> long

                                        +
                                      • +
                                      • +

                                        long -> AddCycleRange(long: minValue, long: maxValue) -> long

                                        +
                                      • +
                                      • +

                                        int -> AddCycleRange(int: maxValue) -> int

                                        +
                                      • +
                                      • +

                                        int -> AddCycleRange(int: minValue, int: maxValue) -> int

                                        +
                                      • +
                                      +

                                      AddHashRange

                                      +

                                      Adds a pseudo-random value within the specified range to the input.

                                      +
                                        +
                                      • +

                                        long -> AddHashRange(long: maxValue) -> long

                                        +
                                      • +
                                      • +

                                        long -> AddHashRange(long: minValue, long: maxValue) -> long

                                        +
                                      • +
                                      • +

                                        long -> AddHashRange(int: maxValue) -> int

                                        +
                                      • +
                                      • +

                                        long -> AddHashRange(int: minValue, int: maxValue) -> int

                                        +
                                      • +
                                      • +

                                        int -> AddHashRange(int: maxValue) -> int

                                        +
                                      • +
                                      • +

                                        int -> AddHashRange(int: minValue, int: maxValue) -> int

                                        +
                                      • +
                                      +

                                      AlphaNumericString

                                      +

                                      Create an alpha-numeric string of the specified length, character-by-character.

                                      +
                                        +
                                      • long -> AlphaNumericString(int: length) -> String
                                      • +
                                      +

                                      ByteBufferSizedHashed

                                      +

                                      Create a ByteBuffer from a long input based on a provided size function. As a 'Sized' function, the first argument is a function which determines the size of the resulting ByteBuffer. As a 'Hashed' function, the input value is hashed again before being used as value.

                                      +
                                        +
                                      • +

                                        long -> ByteBufferSizedHashed(int: size) -> java.nio.ByteBuffer

                                        +
                                          +
                                        • example: ByteBufferSizedHashed(16)
                                        • +
                                        • Functionally identical to HashedToByteBuffer(16) but using dynamic sizing implementation
                                        • +
                                        • example: ByteBufferSizedHashed(HashRange(10, 14))
                                        • +
                                        • Create a ByteBuffer with variable limit (10 to 14)
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> ByteBufferSizedHashed(Object: sizeFunc) -> java.nio.ByteBuffer

                                        +
                                      • +
                                      +

                                      CSVFrequencySampler

                                      +

                                      Takes a CSV with sample data and generates random values based on the relative frequencies of the values in the file. The CSV file must have headers which can be used to find the named columns. I.E. take the following imaginary `animals.csv` file: animal,count,country puppy,1,usa puppy,2,colombia puppy,3,senegal kitten,2,colombia `CSVFrequencySampler('animals.csv', animal)` will return `puppy` or `kitten` randomly. `puppy` will be 3x more frequent than `kitten`. `CSVFrequencySampler('animals.csv', country)` will return `usa`, `colombia`, or `senegal` randomly. `colombia` will be 2x more frequent than `usa` or `senegal`. Use this function to infer frequencies of categorical values from CSVs.

                                      +
                                        +
                                      • long -> CSVFrequencySampler(String: filename, String: columnName) -> String +
                                          +
                                        • +

                                          notes: Create a sampler of strings from the given CSV file. The CSV file must have plain CSV headers +as its first line. +@param filename The name of the file to be read into the sampler buffer +@param columnName The name of the column to be sampled

                                          +
                                        • +
                                        • +

                                          example: CSVFrequencySampler('values.csv','modelno')

                                          +
                                        • +
                                        • +

                                          Read values.csv, count the frequency of values in 'modelno' column, and sample from this column proportionally

                                          +
                                        • +
                                        +
                                      • +
                                      +

                                      CSVSampler

                                      +

                                      This function is a toolkit version of the {@link WeightedStringsFromCSV} function. It is more capable and should be the preferred function for alias sampling over any CSV data. This sampler uses a named column in the CSV data as the value. This is also referred to as the labelColumn . The frequency of this label depends on the weight assigned to it in another named CSV column, known as the weightColumn .

                                      +

                                      Combining duplicate labels

                                      +

                                      When you have CSV data which is not organized around the specific identifier that you want to sample by, you can use some combining functions to tabulate these prior to sampling. In that case, you can use any of "sum", "avg", "count", "min", or "max" as the reducing function on the value in the weight column. If none are specified, then "sum" is used by default. All modes except "count" and "name" require a valid weight column to be specified.

                                      +
                                        +
                                      • sum, avg, min, max - takes the given stat for the weight of each distinct label
                                      • +
                                      • count - takes the number of occurrences of a given label as the weight
                                      • +
                                      • name - sets the weight of all distinct labels to 1.0d
                                      • +
                                      +

                                      Map vs Hash mode

                                      +

                                      As with some of the other statistical functions, you can use this one to pick through the sample values by using the map mode. This is distinct from the default hash mode. When map mode is used, the values will appear monotonically as you scan through the unit interval of all long values. Specifically, 0L represents 0.0d in the unit interval on input, and Long.MAX_VALUE represents 1.0 on the unit interval.) This mode is only recommended for advanced scenarios and should otherwise be avoided. You will know if you need this mode.

                                      +
                                        +
                                      • long -> CSVSampler(String: labelColumn, String: weightColumn, String[]...: data) -> String +
                                          +
                                        • notes: Build an efficient O(1) sampler for the given column values with respect to the weights, +combining equal values by summing the weights.
                                        • +
                                        +
                                      • +
                                      +

                                      @param labelColumn The CSV column name containing the value +@param weightColumn The CSV column name containing a double weight +@param data Sampling modes or file names. Any of map, hash, sum, avg, count are taken +as configuration modes, and all others are taken as CSV filenames.

                                      +
                                        +
                                      • example: CSVSampler('USPS','n/a','name','census_state_abbrev')
                                      • +
                                      • **
                                      • +
                                      +

                                      CharBufImage

                                      +

                                      Builds a shared text image in memory and samples from it pseudo-randomly with hashing. The characters provided can be listed like a string (abc123), or can include range specifiers like a hyphen (a-zA-Z0-9). These characters are used to build an image of the specified size in memory that is sampled from according to the size function. The extracted value is sized according to either a provided function, a size range, or otherwise the whole image. The image can be varied between tests if you want by specifying a seed value. If no seed value is specified, then the image length is used also as a seed.

                                      +
                                        +
                                      • +

                                        long -> CharBufImage(int: size) -> java.nio.CharBuffer

                                        +
                                          +
                                        • notes: Shortcut constructor for building a simple text image +from A-Z, a-z, 0-9 and a space, of the specified size. +When this function is used, it always returns the full image +if constructed in this way. +@param size length in characters of the image.
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> CharBufImage(Object: charsFunc, int: imgsize) -> java.nio.CharBuffer

                                        +
                                          +
                                        • notes: This is the same as {@link CharBufImage(Object,int,Object)} except that the +extracted sample length is fixed to the buffer size, thus the function will +always return the full buffer. +@param charsFunc The function which produces objects, which toString() is used to collect their input +@param imgsize The size of the CharBuffer to build at startup
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> CharBufImage(Object: charsFunc, int: imgsize, Object: sizespec) -> java.nio.CharBuffer

                                        +
                                          +
                                        • notes: This is the same as {@link CharBufImage(Object, int, Object, long)} excep that +the seed is defaulted to 0L +@param charsFunc The function which produces objects, which toString() is used to collect their input +@param imgsize The size of the CharBuffer to build at startup +@param sizespec The specifier for how long samples should be. If this is a number, then it is static. If +it is a function, then the size is determined for each call.
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> CharBufImage(Object: charsFunc, int: imgsize, Object: sizespec, long: seed) -> java.nio.CharBuffer

                                        +
                                          +
                                        • notes: Create a CharBuffer full of the contents of the results of calling a source +function until it is full. Then allow it to be sampled with random extracts +as determined by the sizespec. +@param charsFunc The function which produces objects, which toString() is used to collect their input +@param imgsize The size of the CharBuffer to build at startup +@param sizespec The specifier for how long samples should be. If this is a number, then it is static. If +it is a function, then the size is determined for each call. +@param seed A seed that can be used to change up the rendered content.
                                        • +
                                        +
                                      • +
                                      +

                                      CharBufferExtract

                                      +

                                      Create a CharBuffer from the first function, and then sample data from that buffer according to the size function. The initFunction can be given as simply a size, in which case ByteBufferSizedHash is used with Hex String conversion. If the size function yields a size larger than the available buffer size, then it is lowered to that size automatically. If it is lower, then a random offset is used within the buffer image. This function behaves slightly differently than most in that it creates and caches as source byte buffer during initialization.

                                      +
                                        +
                                      • long -> CharBufferExtract(Object: initFunc, Object: sizeFunc) -> java.nio.CharBuffer
                                      • +
                                      +

                                      Clamp

                                      +

                                      Clamp the output values to be at least the minimum value and at most the maximum value.

                                      +
                                        +
                                      • +

                                        double -> Clamp(double: min, double: max) -> double

                                        +
                                          +
                                        • example: Clamp(1.0D,9.0D)
                                        • +
                                        • clamp output values between the range [1.0D, 9.0D], inclusive
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Clamp(long: min, long: max) -> long

                                        +
                                          +
                                        • example: Clamp(4L,400L)
                                        • +
                                        • clamp the output values in the range [4L,400L], inclusive
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> Clamp(int: min, int: max) -> int

                                        +
                                          +
                                        • example: Clamp(1,100)
                                        • +
                                        • clamp the output values in the range [1,100], inclusive
                                        • +
                                        +
                                      • +
                                      +

                                      Combinations

                                      +

                                      Convert a numeric value into a code according to ASCII printable characters. This is useful for creating various encodings using different character ranges, etc. This mapper can map over the sequences of character ranges providing every unique combination and then wrapping around to the beginning again. It can convert between character bases with independent radix in each position. Each position in the final string takes its values from a position-specific character set, described by the shorthand in the examples below. The constructor will throw an error if the number of combinations exceeds that which can be represented in a long value. (This is a very high number).

                                      +
                                        +
                                      • long -> Combinations(String: spec) -> String +
                                          +
                                        • example: Combinations('A-Z;A-Z')
                                        • +
                                        • a two digit alphanumeric code. Wraps at 26^2
                                        • +
                                        • example: Combinations('0-9A-F')
                                        • +
                                        • a single hexadecimal digit
                                        • +
                                        • example: Combinations('0123456789ABCDEF')
                                        • +
                                        • a single hexadecimal digit
                                        • +
                                        • example: Combinations('0-9A-F;0-9A-F;0-9A-F;0-9A-F;')
                                        • +
                                        • two bytes of hexadecimal
                                        • +
                                        • example: Combinations('A-9')
                                        • +
                                        • upper case alphanumeric
                                        • +
                                        +
                                      • +
                                      +

                                      CycleRange

                                      +

                                      Yields a value within a specified range, which rolls over continuously.

                                      +
                                        +
                                      • +

                                        long -> CycleRange(long: maxValue) -> long

                                        +
                                      • +
                                      • +

                                        long -> CycleRange(long: minValue, long: maxValue) -> long

                                        +
                                      • +
                                      • +

                                        long -> CycleRange(int: maxValue) -> int

                                        +
                                      • +
                                      • +

                                        long -> CycleRange(int: minValue, int: maxValue) -> int

                                        +
                                      • +
                                      • +

                                        int -> CycleRange(int: maxValue) -> int

                                        +
                                          +
                                        • +

                                          notes: Sets the maximum value of the cycle range. The minimum is default to 0. +@param maxValue The maximum value in the cycle to be added.

                                          +
                                        • +
                                        • +

                                          example: CycleRange(34)

                                          +
                                        • +
                                        • +

                                          add a rotating value between 0 and 34 to the input

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> CycleRange(int: minValue, int: maxValue) -> int

                                        +
                                          +
                                        • notes: Sets the minimum and maximum value of the cycle range. +@param minValue minimum value of the cycle to be added. +@param maxValue maximum value of the cycle to be added.
                                        • +
                                        +
                                      • +
                                      +

                                      DelimFrequencySampler

                                      +

                                      Takes a CSV with sample data and generates random values based on the relative frequencies of the values in the file. The CSV file must have headers which can be used to find the named columns. I.E. take the following imaginary `animals.csv` file: animal,count,country puppy,1,usa puppy,2,colombia puppy,3,senegal kitten,2,colombia `CSVFrequencySampler('animals.csv', animal)` will return `puppy` or `kitten` randomly. `puppy` will be 3x more frequent than `kitten`. `CSVFrequencySampler('animals.csv', country)` will return `usa`, `colombia`, or `senegal` randomly. `colombia` will be 2x more frequent than `usa` or `senegal`. Use this function to infer frequencies of categorical values from CSVs.

                                      +
                                        +
                                      • long -> DelimFrequencySampler(String: filename, String: columnName, char: delimiter) -> String +
                                          +
                                        • +

                                          notes: Create a sampler of strings from the given delimited file. The delimited file must have plain headers +as its first line. +@param filename The name of the file to be read into the sampler buffer +@param columnName The name of the column to be sampled +@param delimiter delimmiter

                                          +
                                        • +
                                        • +

                                          example: DelimFrequencySampler('values.csv','modelno', '|')

                                          +
                                        • +
                                        • +

                                          Read values.csv, count the frequency of values in 'modelno' column, and sample from this column proportionally

                                          +
                                        • +
                                        +
                                      • +
                                      +

                                      DirectoryLines

                                      +

                                      Read each line in each matching file in a directory structure, providing one line for each time this function is called. The files are sorted at the time the function is initialized, and each line is read in order. This function does not produce the same result per cycle value. It is possible that different cycle inputs will return different inputs if the cycles are not applied in strict order. Still, this function is useful for consuming input from a set of files as input to a test or simulation.

                                      +
                                        +
                                      • long -> DirectoryLines(String: basepath, String: namePattern) -> String +
                                          +
                                        • example: DirectoryLines('/var/tmp/bardata', '.*')
                                        • +
                                        • load every line from every file in /var/tmp/bardata
                                        • +
                                        +
                                      • +
                                      +

                                      Discard

                                      +

                                      This function takes a long input and ignores it. It returns a generic object which is meant to be used as input to other function which don't need a specific input.

                                      +
                                        +
                                      • long -> Discard() -> Object
                                      • +
                                      +

                                      Div

                                      +

                                      Divide the operand by a fixed value and return the result.

                                      +
                                        +
                                      • +

                                        double -> Div(double: divisor) -> double

                                        +
                                      • +
                                      • +

                                        long -> Div(int: divisor) -> int

                                        +
                                      • +
                                      • +

                                        long -> Div(long: divisor) -> long

                                        +
                                          +
                                        • example: Div(42L)
                                        • +
                                        • divide all inputs by 42L
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> Div(int: divisor) -> int

                                        +
                                      • +
                                      +

                                      DivideToLongToString

                                      +

                                      This is equivalent to Div(...), but returns the result after String.valueOf(...). This function is also deprecated, as it is easily replaced by other functions.

                                      +
                                        +
                                      • long -> DivideToLongToString(long: divisor) -> String
                                      • +
                                      +

                                      ElapsedNanoTime

                                      +

                                      Provide the elapsed nano time since the process started. CAUTION: This does not produce deterministic test data.

                                      +
                                        +
                                      • long -> ElapsedNanoTime() -> long
                                      • +
                                      +

                                      EscapeJSON

                                      +

                                      Escape all special characters which are required to be escaped when found within JSON content according to the JSON spec

                                      +
                                      {@code
                                      +\b  Backspace (ascii code 08)
                                      +\f  Form feed (ascii code 0C)
                                      +\n  New line
                                      +\r  Carriage return
                                      +\t  Tab
                                      +\"  Double quote
                                      +\\  Backslash character
                                      +\/  Forward slash
                                      +}
                                      +
                                      +
                                        +
                                      • String -> EscapeJSON() -> String
                                      • +
                                      +

                                      FieldExtractor

                                      +

                                      Extracts out a set of fields from a delimited string, returning a string with the same delimiter containing only the specified fields.

                                      +
                                        +
                                      • String -> FieldExtractor(String: fields) -> String +
                                          +
                                        • example: FieldExtractor('|,2,16')
                                        • +
                                        • extract fields 2 and 16 from the input data with '|' as the delimiter
                                        • +
                                        +
                                      • +
                                      +

                                      FirstLines

                                      +
                                        +
                                      • +

                                        Object -> FirstLines(String: filePath) -> String

                                        +
                                      • +
                                      • +

                                        Object -> FirstLines(String: filePath, Integer: numberOfLines) -> String

                                        +
                                      • +
                                      +

                                      FixedValue

                                      +

                                      Yield a fixed value.

                                      +
                                        +
                                      • +

                                        long -> FixedValue(String: value) -> String

                                        +
                                      • +
                                      • +

                                        long -> FixedValue(int: value) -> int

                                        +
                                          +
                                        • example: FixedValue(42)
                                        • +
                                        • always return 42
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> FixedValue(long: fixedValue) -> long

                                        +
                                      • +
                                      +

                                      FixedValues

                                      +

                                      Yield one of the specified values, rotating through them as the input value increases.

                                      +
                                        +
                                      • +

                                        long -> FixedValues(int[]...: values) -> int

                                        +
                                      • +
                                      • +

                                        long -> FixedValues(long[]...: values) -> double

                                        +
                                          +
                                        • example: FixedValues(3D,53D,73d)
                                        • +
                                        • Yield 3D, 53D, 73D, 3D, 53D, 73D, 3D, ...
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> FixedValues(long[]...: values) -> long

                                        +
                                          +
                                        • example: FixedValues(3L,53L,73L)
                                        • +
                                        • Yield 3L, 53L, 73L, 3L, 53L, 73L, 3L, ...
                                        • +
                                        +
                                      • +
                                      +

                                      FullHash

                                      +

                                      This uses the Murmur3F (64-bit optimized) version of Murmur3, not as a checksum, but as a simple hash. It doesn't bother pushing the high-64 bits of input, since it only uses the lower 64 bits of output. This version returns the value regardless of this sign bit. It does not return the absolute value, as {@link Hash} does.

                                      +
                                        +
                                      • long -> FullHash() -> long
                                      • +
                                      +

                                      Hash

                                      +

                                      This uses the Murmur3F (64-bit optimized) version of Murmur3, not as a checksum, but as a simple hash. It doesn't bother pushing the high-64 bits of input, since it only uses the lower 64 bits of output. It does, however, return the absolute value. This is to make it play nice with users and other libraries.

                                      +
                                        +
                                      • +

                                        long -> Hash() -> long

                                        +
                                      • +
                                      • +

                                        int -> Hash() -> int

                                        +
                                      • +
                                      • +

                                        long -> Hash() -> int

                                        +
                                      • +
                                      +

                                      HashInterval

                                      +

                                      Return a value within a range, pseudo-randomly, using interval semantics, where the range of values return does not include the last value. This function behaves exactly like HashRange except for the exclusion of the last value. This allows you to stack intervals using known reference points without duplicating or skipping any given value. You can specify hash intervals as small as a single-element range, like (5,6), or as wide as the relevant data type allows.

                                      +
                                        +
                                      • +

                                        int -> HashInterval(int: width) -> int

                                        +
                                          +
                                        • +

                                          notes: Create a hash interval based on a minimum value of 0 and a specified width. +@param width The maximum value, which is excluded.

                                          +
                                        • +
                                        • +

                                          example: HashInterval(4)

                                          +
                                        • +
                                        • +

                                          return values which could include 0, 1, 2, 3, but not 4

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> HashInterval(int: minIncl, int: maxExcl) -> int

                                        +
                                          +
                                        • +

                                          notes: Create a hash interval +@param minIncl The minimum value, which is included +@param maxExcl The maximum value, which is excluded

                                          +
                                        • +
                                        • +

                                          example: HashInterval(2,5)

                                          +
                                        • +
                                        • +

                                          return values which could include 2, 3, 4, but not 5

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> HashInterval(int: width) -> int

                                        +
                                          +
                                        • +

                                          notes: Create a hash interval based on a minimum value of 0 and a specified width. +@param width The maximum value, which is excluded.

                                          +
                                        • +
                                        • +

                                          example: HashInterval(4)

                                          +
                                        • +
                                        • +

                                          return values which could include 0, 1, 2, 3, but not 4

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> HashInterval(int: minIncl, int: maxExcl) -> int

                                        +
                                          +
                                        • +

                                          notes: Create a hash interval +@param minIncl The minimum value, which is included +@param maxExcl The maximum value, which is excluded

                                          +
                                        • +
                                        • +

                                          example: HashInterval(2,5)

                                          +
                                        • +
                                        • +

                                          return values which could include 2, 3, 4, but not 5

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> HashInterval(long: width) -> long

                                        +
                                          +
                                        • +

                                          notes: Create a hash interval based on a minimum value of 0 and a specified width. +@param width The maximum value, which is excluded.

                                          +
                                        • +
                                        • +

                                          example: HashInterval(4L)

                                          +
                                        • +
                                        • +

                                          return values which could include 0L, 1L, 2L, 3L, but not 4L

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> HashInterval(long: minIncl, long: maxExcl) -> long

                                        +
                                          +
                                        • +

                                          notes: Create a hash interval +@param minIncl The minimum value, which is included +@param maxExcl The maximum value, which is excluded

                                          +
                                        • +
                                        • +

                                          example: HashInterval(2L,5L)

                                          +
                                        • +
                                        • +

                                          return values which could include 2L, 3L, 4L, but not 5L

                                          +
                                        • +
                                        +
                                      • +
                                      +

                                      HashRange

                                      +

                                      Return a value within a range, pseudo-randomly. This is equivalent to returning a value with in range between 0 and some maximum value, but with a minimum value added. You can specify hash ranges as small as a single-element range, like (5,5), or as wide as the relevant data type allows.

                                      +
                                        +
                                      • +

                                        int -> HashRange(int: width) -> int

                                        +
                                      • +
                                      • +

                                        int -> HashRange(int: minValue, int: maxValue) -> int

                                        +
                                      • +
                                      • +

                                        long -> HashRange(long: width) -> long

                                        +
                                      • +
                                      • +

                                        long -> HashRange(long: minValue, long: maxValue) -> long

                                        +
                                      • +
                                      • +

                                        long -> HashRange(int: width) -> int

                                        +
                                          +
                                        • example: HashRange(32L)
                                        • +
                                        • map the input to a number in the range 0-31, inclusive, of type int
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> HashRange(int: minValue, int: maxValue) -> int

                                        +
                                          +
                                        • example: HashRange(35L,39L)
                                        • +
                                        • map the input to a number in the range 35-38, inclusive, of type int
                                        • +
                                        +
                                      • +
                                      +

                                      HashRangeScaled

                                      +

                                      Return a pseudo-random value which can only be as large as the input times a scale factor, with a default scale factor of 1.0d

                                      +
                                        +
                                      • +

                                        int -> HashRangeScaled(double: scalefactor) -> int

                                        +
                                      • +
                                      • +

                                        int -> HashRangeScaled() -> int

                                        +
                                      • +
                                      • +

                                        long -> HashRangeScaled(double: scalefactor) -> long

                                        +
                                      • +
                                      • +

                                        long -> HashRangeScaled() -> long

                                        +
                                      • +
                                      • +

                                        long -> HashRangeScaled(double: scalefactor) -> int

                                        +
                                      • +
                                      • +

                                        long -> HashRangeScaled() -> int

                                        +
                                      • +
                                      +

                                      HashedByteBufferExtract

                                      +

                                      Create a ByteBuffer from the first function, and then sample data from that bytebuffer according to the size function. The initFunction can be given as simply a size, in which case ByteBufferSizedHash is used. If the size function yields a size larger than the available buffer size, then it is lowered to that size automatically. If it is lower, then a random offset is used within the buffer image. This function behaves slightly differently than most in that it creates and caches as source byte buffer during initialization.

                                      +
                                        +
                                      • long -> HashedByteBufferExtract(Object: initFunc, Object: sizeFunc) -> java.nio.ByteBuffer
                                      • +
                                      +

                                      HashedDoubleRange

                                      +

                                      Return a double value within the specified range. This function uses an intermediate long to arrive at the sampled value before conversion to double, thus providing a more linear sample at the expense of some precision at extremely large values.

                                      +
                                        +
                                      • long -> HashedDoubleRange(double: min, double: max) -> double
                                      • +
                                      +

                                      HashedFileExtractToString

                                      +

                                      Pseudo-randomly extract a section of a text file and return it according to some minimum and maximum extract size. The file is loaded into memory as a shared text image. It is then indexed into as a character buffer to find a pseudo-randomly sized fragment.

                                      +
                                        +
                                      • +

                                        long -> HashedFileExtractToString(String: filename, int: minsize, int: maxsize) -> String

                                        +
                                          +
                                        • example: HashedFileExtractToString('data/adventures.txt',100,200)
                                        • +
                                        • return a fragment from adventures.txt between 100 and 200 characters long
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> HashedFileExtractToString(String: filename, Object: sizefunc) -> String

                                        +
                                          +
                                        • notes: Provide a size function for the fragment to be extracted. In this form, if the size function specifies a string +size which is larger than the text image, it is truncated via modulo to fall within the text image size.
                                        • +
                                        +
                                      • +
                                      +

                                      @param filename The file name to be loaded +@param sizefunc A function which determines the size of the data to be loaded.

                                      +
                                        +
                                      • example: HashedFileExtractToString('data/adventures.txt',Uniform())
                                      • +
                                      • return a fragment from adventures.txt from a random offset, based on the size function provided.
                                      • +
                                      +

                                      HashedLineToInt

                                      +

                                      Return a pseudo-randomly selected integer value from a file of numeric values. Each line in the file must contain one parsable integer value.

                                      +
                                        +
                                      • long -> HashedLineToInt(String: filename) -> int
                                      • +
                                      +

                                      HashedLineToString

                                      +

                                      Return a pseudo-randomly selected String value from a single line of the specified file.

                                      +
                                        +
                                      • long -> HashedLineToString(String: filename) -> String
                                      • +
                                      +

                                      HashedLinesToKeyValueString

                                      +

                                      Generate a string in the format key1:value1;key2:value2;... from the words in the specified file, ranging in size between zero and the specified maximum.

                                      +
                                        +
                                      • long -> HashedLinesToKeyValueString(String: paramFile, int: maxsize) -> String
                                      • +
                                      +

                                      HashedLoremExtractToString

                                      +

                                      Provide a text extract from the full lorem ipsum text, between the specified minimum and maximum size.

                                      +
                                        +
                                      • long -> HashedLoremExtractToString(int: minsize, int: maxsize) -> String
                                      • +
                                      +

                                      HashedRangedToNonuniformDouble

                                      +

                                      This provides a random sample of a double in a range, without accounting for the non-uniform distribution of IEEE double representation. This means that values closer to high-precision areas of the IEEE spec will be weighted higher in the output. However, NaN and positive and negative infinity are filtered out via oversampling. Results are still stable for a given input value.

                                      +
                                        +
                                      • long -> HashedRangedToNonuniformDouble(long: min, long: max) -> double
                                      • +
                                      +

                                      HashedToByteBuffer

                                      +

                                      Hash a long input value into a byte buffer, at least length bytes long, but aligned on 8-byte boundary;

                                      +
                                        +
                                      • long -> HashedToByteBuffer(int: lengthInBytes) -> java.nio.ByteBuffer
                                      • +
                                      +

                                      Identity

                                      +

                                      Simply returns the input value. This function intentionally does nothing.

                                      +
                                        +
                                      • long -> Identity() -> long
                                      • +
                                      +

                                      Interpolate

                                      +

                                      Return a value along an interpolation curve. This allows you to sketch a basic density curve and describe it simply with just a few values. The number of values provided determines the resolution of the internal lookup table that is used for interpolation. The first value is always the 0.0 anchoring point on the unit interval. The last value is always the 1.0 anchoring point on the unit interval. This means that in order to subdivide the density curve in an interesting way, you need to provide a few more values in between them. Providing two values simply provides a uniform sample between a minimum and maximum value. The input range of this function is, as many of the other functions in this library, based on the valid range of positive long values, between 0L and Long.MAX_VALUE inclusive. This means that if you want to combine interpolation on this curve with the effect of pseudo-random sampling, you need to put a hash function ahead of it in the flow. Developer Note: This is the canonical implementation of LERPing in NoSQLBench, so is heavily documented. Any other LERP implementations should borrow directly from this, embedding by default.

                                      +
                                        +
                                      • +

                                        long -> Interpolate(double[]...: values) -> double

                                        +
                                          +
                                        • example: Interpolate(0.0d,100.0d)
                                        • +
                                        • return a uniform double value between 0.0d and 100.0d
                                        • +
                                        • example: Interpolate(0.0d,90.0d,95.0d,98.0d,100.0d)
                                        • +
                                        • return a weighted double value where the first second and third quartiles are 90.0D, 95.0D, and 98.0D
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Interpolate(double[]...: values) -> long

                                        +
                                          +
                                        • example: Interpolate(0.0d,100.0d)
                                        • +
                                        • return a uniform long value between 0L and 100L
                                        • +
                                        • example: Interpolate(0.0d,90.0d,95.0d,98.0d,100.0d)
                                        • +
                                        • return a weighted long value where the first second and third quartiles are 90.0D, 95.0D, and 98.0D
                                        • +
                                        +
                                      • +
                                      +

                                      Join

                                      +

                                      This takes any collection and concatenates the String representation with a specified delimiter.

                                      +
                                        +
                                      • Collection -> Join(String: delim) -> String +
                                          +
                                        • example: Join(',')
                                        • +
                                        • Concatenate the incoming collection with ','
                                        • +
                                        +
                                      • +
                                      +

                                      JoinTemplate

                                      +

                                      Combine the result of the specified functions together with the specified delimiter and optional prefix and suffix.

                                      +
                                        +
                                      • +

                                        long -> JoinTemplate(String: delimiter, function.LongFunction<?>[]...: funcs) -> String

                                        +
                                          +
                                        • example: JoinTemplate('--',NumberNameToString(),NumberNameToString())
                                        • +
                                        • create values like one--one, two-two, ...
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> JoinTemplate(String: prefix, String: delimiter, String: suffix, function.LongFunction<?>[]...: funcs) -> String

                                        +
                                          +
                                        • example: JoinTemplate('{',',','}',NumberNameToString(),LastNames())
                                        • +
                                        • create values like '{one,Farrel}', '{two,Haskell}', ...
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> JoinTemplate(function.LongUnaryOperator: iterop, String: prefix, String: delimiter, String: suffix, function.LongFunction<?>[]...: funcs) -> String

                                        +
                                          +
                                        • example: JoinTemplate(Add(3),'<',';','>',NumberNameToString(),NumberNameToString(),NumberNameToString())
                                        • +
                                        • create values like '<zero;three,six>', '<one;four,seven>', ...
                                        • +
                                        +
                                      • +
                                      +

                                      ListTemplate

                                      +

                                      Create a {@code List} based on two functions, the first to determine the list size, and the second to populate the list with string values. The input fed to the second function is incremented between elements.

                                      +
                                        +
                                      • long -> ListTemplate(function.LongToIntFunction: sizeFunc, function.LongFunction: valueFunc) -> List +
                                          +
                                        • example: ListTemplate(HashRange(3,7),NumberNameToString())
                                        • +
                                        • create a list between 3 and 7 elements, with number names as the values
                                        • +
                                        +
                                      • +
                                      +

                                      LoadElement

                                      +

                                      Load a value from a map, based on the injected configuration. The map which is used must be named by the mapname. If the injected configuration contains a variable of this name which is also a Map, then this map is referenced and read by the provided variable name.

                                      +
                                        +
                                      • Object -> LoadElement(String: varname, String: mapname, Object: defaultValue) -> Object +
                                          +
                                        • example: LoadElement('varname','vars','defaultvalue')
                                        • +
                                        • Load the varable 'varname' from a map named 'vars', or provide 'defaultvalue' if neither is provided
                                        • +
                                        +
                                      • +
                                      +

                                      LongToString

                                      +

                                      Return the string representation of the provided long. @deprecated use ToString() instead

                                      +
                                        +
                                      • long -> LongToString() -> String
                                      • +
                                      +

                                      MatchFunc

                                      +

                                      Match any input with a regular expression, and apply the associated function to it, yielding the value. If no matches occur, then the original value is passed through unchanged. Patterns and functions are passed as even,odd pairs indexed from the 0th position. Instead of a function, a String value may be provided as the associated output value.

                                      +
                                        +
                                      • String -> MatchFunc(Object[]...: funcs) -> String +
                                          +
                                        • example: MatchFunc('.*','onevalue')
                                        • +
                                        • Match all String inputs, simply returning 'onevalue' as the output value.
                                        • +
                                        • example: MatchFunc('[0-9]+',Suffix('-is-a-number'))
                                        • +
                                        • Append '-is-a-number' to every input which is a sequence of digits
                                        • +
                                        +
                                      • +
                                      +

                                      MatchRegex

                                      +

                                      Match any input with a regular expression, and apply the associated regex replacement to it, yielding the value. If no matches occur, then the original value is passed through unchanged. Patterns and replacements are passed as even,odd pairs indexed from the 0th position. Back-references to matching groups are supported.

                                      +
                                        +
                                      • String -> MatchRegex(String[]...: specs) -> String +
                                          +
                                        • example: MatchRegex('.*(25|6to4).*','$1')
                                        • +
                                        • Match 25 or 6 to 4 and set the output to only that
                                        • +
                                        • example: MatchRegex('([0-9]+)-([0-9]+)-([0-9]+)','$1 $2 $3'
                                        • +
                                        • replaced dashes with spaces in a 10 digit US phone number.
                                        • +
                                        +
                                      • +
                                      +

                                      Max

                                      +

                                      Return the maximum of either the input value or the specified max.

                                      +
                                        +
                                      • +

                                        double -> Max(double: max) -> double

                                        +
                                      • +
                                      • +

                                        long -> Max(long: max) -> long

                                        +
                                          +
                                        • example: Max(42L)
                                        • +
                                        • take the value of 42L or the input, which ever is greater
                                        • +
                                        • example: Max(-42L)
                                        • +
                                        • take the value of -42L or the input, which ever is greater
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> Max(int: max) -> int

                                        +
                                      • +
                                      +

                                      Min

                                      +

                                      Return the minimum of either the input value or the specified minimum.

                                      +
                                        +
                                      • +

                                        double -> Min(double: min) -> double

                                        +
                                      • +
                                      • +

                                        long -> Min(long: min) -> long

                                        +
                                      • +
                                      • +

                                        int -> Min(int: min) -> int

                                        +
                                      • +
                                      +

                                      Mod

                                      +

                                      Return the result of modulo division by the specified divisor.

                                      +
                                        +
                                      • +

                                        long -> Mod(long: modulo) -> long

                                        +
                                      • +
                                      • +

                                        int -> Mod(int: modulo) -> int

                                        +
                                      • +
                                      • +

                                        long -> Mod(int: modulo) -> int

                                        +
                                      • +
                                      +

                                      ModuloCSVLineToString

                                      +

                                      Select a value from a CSV file line by modulo division against the number of lines in the file. The second parameter is the field name, and this must be provided in the CSV header line as written.

                                      +
                                        +
                                      • long -> ModuloCSVLineToString(String: filename, String: fieldname) -> String +
                                          +
                                        • example: ModuloCSVLineToString('data/myfile.csv','lat')
                                        • +
                                        • load values for 'lat' from the CSV file myfile.csv.
                                        • +
                                        +
                                      • +
                                      +

                                      ModuloLineToString

                                      +

                                      Select a value from a text file line by modulo division against the number of lines in the file.

                                      +
                                        +
                                      • long -> ModuloLineToString(String: filename) -> String
                                      • +
                                      +

                                      ModuloToInteger

                                      +

                                      Return an integer value as the result of modulo division with the specified divisor.

                                      +
                                        +
                                      • long -> ModuloToInteger(int: modulo) -> Integer
                                      • +
                                      +

                                      ModuloToLong

                                      +

                                      Return a long value as the result of modulo division with the specified divisor.

                                      +
                                        +
                                      • long -> ModuloToLong(long: modulo) -> long
                                      • +
                                      +

                                      Mul

                                      +

                                      Return the result of multiplying the specified value with the input.

                                      +
                                        +
                                      • +

                                        double -> Mul(double: factor) -> double

                                        +
                                      • +
                                      • +

                                        long -> Mul(long: multiplicand) -> long

                                        +
                                      • +
                                      • +

                                        int -> Mul(int: addend) -> int

                                        +
                                      • +
                                      • +

                                        long -> Mul(int: multiplicand) -> int

                                        +
                                      • +
                                      +

                                      Murmur3DivToLong

                                      +

                                      Yield a long value which is the result of hashing and modulo division with the specified divisor.

                                      +
                                        +
                                      • long -> Murmur3DivToLong(long: divisor) -> long
                                      • +
                                      +

                                      Murmur3DivToString

                                      +

                                      Yield a String value which is the result of hashing and modulo division with the specified divisor to long and then converting the value to String.

                                      +
                                        +
                                      • long -> Murmur3DivToString(long: divisor) -> String
                                      • +
                                      +

                                      NumberNameToString

                                      +

                                      Provides the spelled-out name of a number. For example, an input of 7 would yield "seven". An input of 4234 yields the value "four thousand thirty four". The maximum value is limited at 999,999,999.

                                      +
                                        +
                                      • long -> NumberNameToString() -> String
                                      • +
                                      +

                                      PartitionLongs

                                      +

                                      Split the value range of Java longs into a number of offsets, starting with Long.MIN_VALUE. This method makes it easy to construct a set of offsets for testing, or to limit the values used a subset. The outputs will range from Long.MIN_VALUE (-2^63) up. This is not an exactly emulation of token range splits in Apache Cassandra.

                                      +
                                        +
                                      • long -> PartitionLongs(int: partitions) -> long
                                      • +
                                      +

                                      Prefix

                                      +

                                      Add the specified prefix String to the input value and return the result.

                                      +
                                        +
                                      • String -> Prefix(String: prefix) -> String +
                                          +
                                        • example: Prefix('PREFIX:')
                                        • +
                                        • Prepend 'PREFIX:' to every input value
                                        • +
                                        +
                                      • +
                                      +

                                      ReplaceAll

                                      +

                                      Replace all occurrences of the extant string with the replacement string.

                                      +
                                        +
                                      • String -> ReplaceAll(String: extant, String: replacement) -> String +
                                          +
                                        • example: ReplaceAll('one','two')
                                        • +
                                        • Replace all occurrences of 'one' with 'two'
                                        • +
                                        +
                                      • +
                                      +

                                      ReplaceRegex

                                      +

                                      Replace all occurrences of the regular expression with the replacement string. Note, this is much less efficient than using the simple ReplaceAll for most cases.

                                      +
                                        +
                                      • String -> ReplaceRegex(String: regex, String: replacement) -> String +
                                          +
                                        • example: ReplaceRegex('[one]','two')
                                        • +
                                        • Replace all occurrences of 'o' or 'n' or 'e' with 'two'
                                        • +
                                        +
                                      • +
                                      +

                                      Shuffle

                                      +

                                      This function provides a low-overhead shuffling effect without loading elements into memory. It uses a bundled dataset of pre-computed Galois LFSR shift register configurations, along with a down-sampling method to provide amortized virtual shuffling with minimal memory usage. Essentially, this guarantees that every value in the specified range will be seen at least once before the cycle repeats. However, since the order of traversal of these values is dependent on the LFSR configuration, some orders will appear much more random than others depending on where you are in the traversal cycle. This function *does* yield values that are deterministic.

                                      +
                                        +
                                      • +

                                        long -> Shuffle(long: min, long: maxPlusOne) -> long

                                        +
                                          +
                                        • example: Shuffle(11,99)
                                        • +
                                        • Provide all values between 11 and 98 inclusive, in some order, then repeat
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Shuffle(long: min, long: maxPlusOne, int: bankSelector) -> long

                                        +
                                          +
                                        • example: Shuffle(11,99,3)
                                        • +
                                        • Provide all values between 11 and 98 inclusive, in some different (and repeatable) order, then repeat
                                        • +
                                        +
                                      • +
                                      +

                                      SignedHash

                                      +

                                      This uses the Murmur3F (64-bit optimized) version of Murmur3, not as a checksum, but as a simple hash. It doesn't bother pushing the high-64 bits of input, since it only uses the lower 64 bits of output. Unlike the other hash functions, this one may return positive as well as negative values.

                                      +
                                        +
                                      • +

                                        long -> SignedHash() -> long

                                        +
                                      • +
                                      • +

                                        int -> SignedHash() -> int

                                        +
                                      • +
                                      • +

                                        long -> SignedHash() -> int

                                        +
                                      • +
                                      +

                                      StaticStringMapper

                                      +

                                      Return a static String value.

                                      +
                                        +
                                      • long -> StaticStringMapper(String: string) -> String
                                      • +
                                      +

                                      Suffix

                                      +

                                      Add the specified prefix String to the input value and return the result.

                                      +
                                        +
                                      • String -> Suffix(String: suffix) -> String +
                                          +
                                        • example: Suffix('--Fin')
                                        • +
                                        • Append '--Fin' to every input value
                                        • +
                                        +
                                      • +
                                      +

                                      Template

                                      +

                                      Creates a template function which will yield a string which fits the template provided, with all occurrences of {} substituted pair-wise with the result of the provided functions. The number of {} entries in the template must strictly match the number of functions or an error will be thrown. If you need to include single quotes or other special characters, you may use a backslash "\" in your template. The objects passed must be functions of any of the following types:

                                      +
                                        +
                                      • LongUnaryOperator
                                      • +
                                      • IntUnaryOperator
                                      • +
                                      • DoubleUnaryOperator
                                      • +
                                      • LongFunction
                                      • +
                                      • IntFunction
                                      • +
                                      • DoubleFunction
                                      • +
                                      • Function<Long,?>
                                      • +
                                      +

                                      The result of applying the input value to any of these functions is converted to a String +and then stitched together according to the template provided.

                                      +
                                        +
                                      • +

                                        long -> Template(String: template, Object[]...: funcs) -> String

                                        +
                                          +
                                        • example: Template('{}-{}',Add(10),Hash())
                                        • +
                                        • concatenate input+10, '-', and a pseudo-random long
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Template(boolean: truncate, String: template, Object[]...: funcs) -> String

                                        +
                                          +
                                        • example: Template(true, '{}-{}', Add(10),Hash())
                                        • +
                                        • throws an error, as the Add(10) function causes a narrowing conversion for a long input
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Template(function.LongUnaryOperator: iterOp, String: template, function.LongFunction<?>[]...: funcs) -> String

                                        +
                                          +
                                        • notes: If an operator is provided, it is used to change the function input value in an additional way before each function.
                                        • +
                                        +
                                      • +
                                      +

                                      @param iterOp A pre-generation value mapping function +@param template A string template containing

                                      {}
                                      anchors +@param funcs A varargs length of LongFunctions of any output type

                                      +

                                      ThreadNumToInteger

                                      +

                                      Matches a digit sequence in the current thread name and caches it in a thread local. This allows you to use any intentionally indexed thread factories to provide an analogue for concurrency. Note that once the thread number is cached, it will not be refreshed. This means you can't change the thread name and get an updated value.

                                      +
                                        +
                                      • long -> ThreadNumToInteger() -> Integer
                                      • +
                                      +

                                      ThreadNumToLong

                                      +

                                      Matches a digit sequence in the current thread name and caches it in a thread local. This allows you to use any intentionally indexed thread factories to provide an analogue for concurrency. Note that once the thread number is cached, it will not be refreshed. This means you can't change the thread name and get an updated value.

                                      +
                                        +
                                      • long -> ThreadNumToLong() -> long
                                      • +
                                      +

                                      ToBase64

                                      +

                                      Takes a bytebuffer and turns it into a base64 string

                                      +
                                        +
                                      • java.nio.ByteBuffer -> ToBase64() -> String
                                      • +
                                      +

                                      ToHashedUUID

                                      +

                                      This function provides a stable hashing of the input value to a version 4 (Random) UUID.

                                      +
                                        +
                                      • long -> ToHashedUUID() -> UUID
                                      • +
                                      +

                                      Trim

                                      +

                                      Trim the input value and return the result.

                                      +
                                        +
                                      • String -> Trim() -> String
                                      • +
                                      +

                                      WeightedLongs

                                      +

                                      Provides a long value from a list of weighted values. The total likelihood of any value to be produced is proportional to its relative weight in the total weight of all elements. This function automatically hashes the input, so the result is already pseudo-random.

                                      +
                                        +
                                      • long -> WeightedLongs(String: valuesAndWeights) -> Long +
                                          +
                                        • example: WeightedLongs('1:10;3;5;12345;1
                                        • +
                                        • Yield 1 62.5% of the time, 3 31.25% of the time, and 12345 6.2% of the time
                                        • +
                                        • example: WeightedLongs('1,6,7
                                        • +
                                        • Yield 1 33.3% of the time, 6 33.3% of the time, and 7 33.3% of the time
                                        • +
                                        +
                                      • +
                                      +

                                      WeightedStrings

                                      +

                                      Allows for weighted elements to be used, such as a:0.25;b:0.25;c:0.5 or a:1;b:1.0;c:2.0 The unit weights are normalized to the cumulative sum internally, so it is not necessary for them to add up to any particular value.

                                      +
                                        +
                                      • long -> WeightedStrings(String: valuesAndWeights) -> String
                                      • +
                                      +

                                      WeightedStringsFromCSV

                                      +

                                      Provides sampling of a given field in a CSV file according to discrete probabilities. The CSV file must have headers which can be used to find the named columns for value and weight. The value column contains the string result to be returned by the function. The weight column contains the floating-point weight or mass associated with the value on the same line. All the weights are normalized automatically.

                                      +

                                      If there are multiple file names containing the same format, then they +will all be read in the same way.

                                      +

                                      If the first word in the filenames list is 'map', then the values will not +be pseudo-randomly selected. Instead, they will be mapped over in some +other unsorted and stable order as input values vary from 0L to Long.MAX_VALUE.

                                      +

                                      Generally, you want to leave out the 'map' directive to get "random sampling" +of these values.

                                      +

                                      This function works the same as the three-parametered form of WeightedStrings, +which is deprecated in lieu of this one. Use this one instead.

                                      +
                                        +
                                      • long -> WeightedStringsFromCSV(String: valueColumn, String: weightColumn, String[]...: filenames) -> String +
                                          +
                                        • notes: Create a sampler of strings from the given CSV file. The CSV file must have plain CSV headers +as its first line. +@param valueColumn The name of the value column to be sampled +@param weightColumn The name of the weight column, which must be parsable as a double +@param filenames One or more file names which will be read in to the sampler buffer
                                        • +
                                        +
                                      • +
                                      + +

                                      Back to top

                                      +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-nulls/index.html b/reference/bindings/funcref-nulls/index.html new file mode 100644 index 000000000..6dc80a9a5 --- /dev/null +++ b/reference/bindings/funcref-nulls/index.html @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + null functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      These functions can generate null values. When using nulls in your binding recipes, ensure that you don't generate them +in-line as inputs to other functions. This will lead to errors which interrupt your test. If you must use functions that +generate null values, ensure that they are the only or last function in a chain.

                                      +

                                      If you need to mark a field to be undefined, but not set to null, then use the functions which know how to yield a +VALUE.UNSET, which is a sigil constant within the VirtData runtime. These functions are correctly interpreted by +conformant drivers like the SQL driver so that they will avoid inject the named field into an operation if it has this +special value.

                                      +

                                      NullIfCloseTo

                                      +

                                      Returns null if the input value is within range of the specified value.

                                      +
                                        +
                                      • double -> NullIfCloseTo(double: compareto, double: sigma) -> Double
                                      • +
                                      +

                                      NullIfEmpty

                                      +

                                      Yields a null if the input String is empty. Throws an error if the input String is null.

                                      +
                                        +
                                      • String -> NullIfEmpty() -> String
                                      • +
                                      +

                                      NullIfEq

                                      +

                                      Yeilds a null if the input value is equal to the specified value.

                                      +
                                        +
                                      • +

                                        long -> NullIfEq(long: compareto) -> Long

                                        +
                                      • +
                                      • +

                                        double -> NullIfEq(double: compareto) -> Double

                                        +
                                      • +
                                      +

                                      NullIfGe

                                      +

                                      Yields a null if the input value is greater tha or equal to the specified value.

                                      +
                                        +
                                      • +

                                        long -> NullIfGe(long: compareto) -> Long

                                        +
                                      • +
                                      • +

                                        double -> NullIfGe(double: compareto) -> Double

                                        +
                                      • +
                                      +

                                      NullIfGt

                                      +

                                      Yields a null if the input value is greater than the specified value.

                                      +
                                        +
                                      • +

                                        long -> NullIfGt(long: compareto) -> Long

                                        +
                                      • +
                                      • +

                                        double -> NullIfGt(double: compareto) -> Double

                                        +
                                      • +
                                      +

                                      NullIfLe

                                      +

                                      Yields a null if the input value is less than or equal to the specified value.

                                      +
                                        +
                                      • +

                                        long -> NullIfLe(long: compareto) -> Long

                                        +
                                      • +
                                      • +

                                        double -> NullIfLe(double: compareto) -> Double

                                        +
                                      • +
                                      +

                                      NullIfLt

                                      +

                                      Yields a null if the input value is equal to the specified value.

                                      +
                                        +
                                      • +

                                        double -> NullIfLt(double: compareto) -> Double

                                        +
                                      • +
                                      • +

                                        long -> NullIfLt(long: compareto) -> Long

                                        +
                                      • +
                                      +

                                      NullIfNullOrEmpty

                                      +

                                      Yield a null value if the input String is either null or empty.

                                      +
                                        +
                                      • String -> NullIfNullOrEmpty() -> String
                                      • +
                                      +

                                      NullIfWithin

                                      +

                                      Yields a null if the input value is within the specified range, inclusive.

                                      +
                                        +
                                      • double -> NullIfWithin(double: min, double: max) -> Double
                                      • +
                                      +

                                      NullOrLoad

                                      +

                                      Reads a long variable from the input, hashes and scales it to the unit interval 0.0d - 1.0d, then uses the result to determine whether to return null object or a loaded value.

                                      +
                                        +
                                      • long -> NullOrLoad(double: ratio, String: varname) -> Object
                                      • +
                                      +

                                      NullOrPass

                                      +

                                      Reads a long variable from the thread local variable map, hashes and scales it to the unit interval 0.0d - 1.0d, then uses the result to determine whether to return a null object or the input value.

                                      +
                                        +
                                      • Object -> NullOrPass(double: ratio, String: varname) -> Object
                                      • +
                                      +

                                      Unset

                                      +

                                      Always yields the VALUE.unset value, which signals to any consumers that the value provided should be considered undefined for any operation. This is distinct from functions which return a null, which is considered an actual value to be acted upon. It is deemed an error for any downstream user of this library to do anything with VALUE.unset besides explicitly acting like it wasn't provided. That is the point of VALUE.unset. The purpose of having such a value in this library is to provide a value type to help bridge between functional flows and imperative run-times. Without such a value, it would be difficult to simulate value streams in which some of the time values are set and other times they are not.

                                      +
                                        +
                                      • long -> Unset() -> Object
                                      • +
                                      +

                                      UnsetIfCloseTo

                                      +

                                      Yield VALUE.unset if the input value is close to the specified value by the sigma threshold. Otherwise, pass the input value along.

                                      +
                                        +
                                      • double -> UnsetIfCloseTo(double: compareto, double: sigma) -> Object
                                      • +
                                      +

                                      UnsetIfEmpty

                                      +

                                      Yield VALUE.unset if the input String is empty. Throws an error if the input value is null. Otherwise, passes the original value along.

                                      +
                                        +
                                      • String -> UnsetIfEmpty() -> Object
                                      • +
                                      +

                                      UnsetIfEq

                                      +

                                      Yield UNSET.vale if the input value is equal to the specified value. Otherwise, pass the input value along.

                                      +
                                        +
                                      • +

                                        double -> UnsetIfEq(double: compareto) -> Double

                                        +
                                      • +
                                      • +

                                        long -> UnsetIfEq(long: compareto) -> Object

                                        +
                                      • +
                                      +

                                      UnsetIfGe

                                      +

                                      Yield VALUE.unset if the input value is greater than or equal to the specified value. Otherwise, pass the input value along.

                                      +
                                        +
                                      • +

                                        long -> UnsetIfGe(long: compareto) -> Object

                                        +
                                      • +
                                      • +

                                        double -> UnsetIfGe(double: compareto) -> Object

                                        +
                                      • +
                                      +

                                      UnsetIfGt

                                      +

                                      Yield UNSET.value if the input value is greater than the specified value. Otherwise, pass the input value along.

                                      +
                                        +
                                      • +

                                        long -> UnsetIfGt(long: compareto) -> Object

                                        +
                                      • +
                                      • +

                                        double -> UnsetIfGt(double: compareto) -> Object

                                        +
                                      • +
                                      +

                                      UnsetIfLe

                                      +

                                      Yield VALUE.unset if the input value is less than or equal to the specified value. Otherwise, pass the value along.

                                      +
                                        +
                                      • +

                                        long -> UnsetIfLe(long: compareto) -> Object

                                        +
                                      • +
                                      • +

                                        double -> UnsetIfLe(double: compareto) -> Object

                                        +
                                      • +
                                      +

                                      UnsetIfLt

                                      +

                                      Yield VALUE.unset if the provided value is less than the specified value, otherwise, pass the original value;

                                      +
                                        +
                                      • +

                                        long -> UnsetIfLt(long: compareto) -> Object

                                        +
                                      • +
                                      • +

                                        double -> UnsetIfLt(double: compareto) -> Object

                                        +
                                      • +
                                      +

                                      UnsetIfNullOrEmpty

                                      +

                                      Yields UNSET.value if the input value is null or empty. Otherwise, passes the original value along.

                                      +
                                        +
                                      • String -> UnsetIfNullOrEmpty() -> Object
                                      • +
                                      +

                                      UnsetIfStringEq

                                      +

                                      Yields UNSET.value if the input value is equal to the specified value. Throws an error if the input value is null. Otherwise, passes the original value along.

                                      +
                                        +
                                      • String -> UnsetIfStringEq(String: compareto) -> Object
                                      • +
                                      +

                                      UnsetIfStringNe

                                      +

                                      Yields UNSET.value if the input String is not equal to the specified String value. Throws an error if the input value is null. Otherwise, passes the original value along.

                                      +
                                        +
                                      • String -> UnsetIfStringNe(String: compareto) -> Object
                                      • +
                                      +

                                      UnsetIfWithin

                                      +

                                      Yields UNSET.value if the input value is within the specified range, inclusive. Otherwise, passes the original value along.

                                      +
                                        +
                                      • double -> UnsetIfWithin(double: min, double: max) -> Object
                                      • +
                                      +

                                      UnsetOrLoad

                                      +

                                      Reads a long variable from the input, hashes and scales it to the unit interval 0.0d - 1.0d, then uses the result to determine whether to return UNSET.value or a loaded value.

                                      +
                                        +
                                      • long -> UnsetOrLoad(double: ratio, String: varname) -> Object
                                      • +
                                      +

                                      UnsetOrPass

                                      +

                                      Reads a long variable from the thread local variable map, hashes and scales it to the unit interval 0.0d - 1.0d, then uses the result to determine whether to return UNSET.value or the input value.

                                      +
                                        +
                                      • Object -> UnsetOrPass(double: ratio, String: varname) -> Object
                                      • +
                                      + +

                                      Back to top

                                      +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-objects/index.html b/reference/bindings/funcref-objects/index.html new file mode 100644 index 000000000..4a66ad841 --- /dev/null +++ b/reference/bindings/funcref-objects/index.html @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + + Distance | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      Distance

                                      +

                                      Create a Distance generator which produces com.datastax.driver.dse.geometry.Distance objects.

                                      +
                                        +
                                      • +

                                        long -> Distance(function.LongToDoubleFunction: xfunc, function.LongToDoubleFunction: yfunc, function.LongToDoubleFunction: rfunc) -> com.datastax.dse.driver.internal.core.data.geometry.Distance

                                        +
                                      • +
                                      • +

                                        long -> Distance(double: x, function.LongToDoubleFunction: yfunc, function.LongToDoubleFunction: rfunc) -> com.datastax.dse.driver.internal.core.data.geometry.Distance

                                        +
                                      • +
                                      • +

                                        long -> Distance(function.LongToDoubleFunction: xfunc, double: y, function.LongToDoubleFunction: rfunc) -> com.datastax.dse.driver.internal.core.data.geometry.Distance

                                        +
                                      • +
                                      • +

                                        long -> Distance(double: x, double: y, function.LongToDoubleFunction: rfunc) -> com.datastax.dse.driver.internal.core.data.geometry.Distance

                                        +
                                      • +
                                      • +

                                        long -> Distance(function.LongToDoubleFunction: xfunc, function.LongToDoubleFunction: yfunc, double: r) -> com.datastax.dse.driver.internal.core.data.geometry.Distance

                                        +
                                      • +
                                      • +

                                        long -> Distance(double: x, function.LongToDoubleFunction: yfunc, double: r) -> com.datastax.dse.driver.internal.core.data.geometry.Distance

                                        +
                                      • +
                                      • +

                                        long -> Distance(function.LongToDoubleFunction: xfunc, double: y, double: r) -> com.datastax.dse.driver.internal.core.data.geometry.Distance

                                        +
                                      • +
                                      • +

                                        long -> Distance(double: x, double: y, double: r) -> com.datastax.dse.driver.internal.core.data.geometry.Distance

                                        +
                                      • +
                                      +

                                      LineString

                                      +

                                      Create a com.datastax.driver.dse.geometry.LineString

                                      +
                                        +
                                      • +

                                        long -> LineString(function.LongToIntFunction: lenfunc, function.LongFunction<com.datastax.dse.driver.api.core.data.geometry.Point>: pointfunc) -> com.datastax.dse.driver.api.core.data.geometry.LineString

                                        +
                                      • +
                                      • +

                                        long -> LineString(function.LongToIntFunction: lenfunc, function.LongToDoubleFunction: xfunc, function.LongToDoubleFunction: yfunc) -> com.datastax.dse.driver.api.core.data.geometry.LineString

                                        +
                                      • +
                                      • +

                                        long -> LineString(int: len, function.LongFunction<com.datastax.dse.driver.api.core.data.geometry.Point>: pointfunc) -> com.datastax.dse.driver.api.core.data.geometry.LineString

                                        +
                                      • +
                                      +

                                      Point

                                      +

                                      Create a Point generator which generates com.datastax.driver.dse.geometry.Point objects.

                                      +
                                        +
                                      • +

                                        long -> Point(double: x, double: y) -> com.datastax.dse.driver.api.core.data.geometry.Point

                                        +
                                      • +
                                      • +

                                        long -> Point(double: x, function.LongToDoubleFunction: yfunc) -> com.datastax.dse.driver.api.core.data.geometry.Point

                                        +
                                      • +
                                      • +

                                        long -> Point(function.LongToDoubleFunction: xfunc, double: y) -> com.datastax.dse.driver.api.core.data.geometry.Point

                                        +
                                      • +
                                      • +

                                        long -> Point(function.LongToDoubleFunction: xfunc, function.LongToDoubleFunction: yfunc) -> com.datastax.dse.driver.api.core.data.geometry.Point

                                        +
                                      • +
                                      +

                                      Polygon

                                      +

                                      Create a com.datastax.driver.dse.geometry.Polygon

                                      +
                                        +
                                      • +

                                        long -> Polygon(function.LongToIntFunction: lenfunc, function.LongFunction<com.datastax.dse.driver.api.core.data.geometry.Point>: pointfunc) -> com.datastax.dse.driver.api.core.data.geometry.Polygon

                                        +
                                      • +
                                      • +

                                        long -> Polygon(function.LongToIntFunction: lenfunc, function.LongToDoubleFunction: xfunc, function.LongToDoubleFunction: yfunc) -> com.datastax.dse.driver.api.core.data.geometry.Polygon

                                        +
                                      • +
                                      • +

                                        long -> Polygon(int: len, function.LongFunction<com.datastax.dse.driver.api.core.data.geometry.Point>: pointfunc) -> com.datastax.dse.driver.api.core.data.geometry.Polygon

                                        +
                                      • +
                                      +

                                      PolygonOnGrid

                                      +

                                      This function will return a polygon in the form of a rectangle from the specified grid system. The coordinates define the top left and bottom right coordinates in (x1,y1),(x2,y2) order, while the number of rows and columns divides these ranges into the unit-length for each square. x1 must be greater than x2. y1 must be less than y2. This grid system can be used to construct a set of overlapping grids such that the likelyhood of overlap is somewhat easy to reason about. For example, if you create one grid system as a refernce grid, then attempt to map another grid system which half overlaps the original grid, you can easily determine that half the time, a random rectangle selected from the second grid will overlap a rectangle from the first, for simple even-numbered grids and the expected uniform sampling on the internal coordinate selector functions.

                                      +
                                        +
                                      • long -> PolygonOnGrid(double: x_topleft, double: y_topleft, double: x_bottomright, double: y_bottomright, int: rows, int: columns) -> com.datastax.dse.driver.api.core.data.geometry.Polygon +
                                          +
                                        • example: PolygonOnGrid(1, 11, 11, 1, 10, 10)
                                        • +
                                        • Create a 10x10 grid with cells 1x1, spaced one off the y=0 and x=0 axes
                                        • +
                                        +
                                      • +
                                      + +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-premade/index.html b/reference/bindings/funcref-premade/index.html new file mode 100644 index 000000000..09cfd87a8 --- /dev/null +++ b/reference/bindings/funcref-premade/index.html @@ -0,0 +1,481 @@ + + + + + + + + + + + + + + + + pre-made functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      Functions in this category are meant to provide easy grab-and-go functions that are tailored for real-world simulation. +This library will grow over time. These functions are often built directly on top of other functions in the core +libraries. However, they are provided here for simplicity in workload construction. They perform exactly the same as +their longer-form equivalents.

                                      +

                                      Cities

                                      +

                                      Return a valid city name.

                                      +
                                        +
                                      • long -> Cities() -> String +
                                          +
                                        • example: Cities()
                                        • +
                                        +
                                      • +
                                      +

                                      CitiesByDensity

                                      +

                                      Return a city name, weighted by population density.

                                      +
                                        +
                                      • long -> CitiesByDensity() -> String +
                                          +
                                        • example: CitiesByDensity()
                                        • +
                                        +
                                      • +
                                      +

                                      CitiesByPopulation

                                      +

                                      Return a city name, weighted by total population.

                                      +
                                        +
                                      • long -> CitiesByPopulation() -> String +
                                          +
                                        • example: CitiesByPopulation()
                                        • +
                                        +
                                      • +
                                      +

                                      Counties

                                      +

                                      Return a valid county name.

                                      +
                                        +
                                      • long -> Counties() -> String +
                                          +
                                        • example: Counties()
                                        • +
                                        +
                                      • +
                                      +

                                      CountiesByDensity

                                      +

                                      Return a county name weighted by population density.

                                      +
                                        +
                                      • long -> CountiesByDensity() -> String +
                                          +
                                        • example: CountiesByDensity()
                                        • +
                                        +
                                      • +
                                      +

                                      CountiesByPopulation

                                      +

                                      Return a county name weighted by total population.

                                      +
                                        +
                                      • long -> CountiesByPopulation() -> String +
                                          +
                                        • example: CountiesByPopulation()
                                        • +
                                        +
                                      • +
                                      +

                                      CountryCodes

                                      +

                                      Return a valid country code.

                                      +
                                        +
                                      • long -> CountryCodes() -> String +
                                          +
                                        • example: CountryCodes()
                                        • +
                                        +
                                      • +
                                      +

                                      CountryNames

                                      +

                                      Return a valid country name.

                                      +
                                        +
                                      • long -> CountryNames() -> String +
                                          +
                                        • example: CountryNames()
                                        • +
                                        +
                                      • +
                                      +

                                      FirstNames

                                      +

                                      Return a pseudo-randomly sampled first name from the last US census data on first names occurring more than 100 times. Both male and female names are combined in this function.

                                      +
                                        +
                                      • +

                                        long -> FirstNames() -> String

                                        +
                                          +
                                        • example: FirstNames()
                                        • +
                                        • select a random first name based on the chance of seeing it in the census data
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> FirstNames(String: modifier) -> String

                                        +
                                          +
                                        • example: FirstNames('map')
                                        • +
                                        • select over the first names by probability as input varies from 1L to Long.MAX_VALUE
                                        • +
                                        +
                                      • +
                                      +

                                      FullNames

                                      +

                                      Combines the FirstNames and LastNames functions into one that simply concatenates them with a space between. This function is a shorthand equivalent of {@code Template('{} {}', FirstNames(), LastNames())}

                                      +
                                        +
                                      • long -> FullNames() -> String
                                      • +
                                      +

                                      LastNames

                                      +

                                      Return a pseudo-randomly sampled last name from the last US census data on last names occurring more than 100 times.

                                      +
                                        +
                                      • +

                                        long -> LastNames() -> String

                                        +
                                          +
                                        • example: LastNames()
                                        • +
                                        • select a random last name based on the chance of seeing it in the census data
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> LastNames(String: modifier) -> String

                                        +
                                          +
                                        • example: LastNames('map')
                                        • +
                                        • select over the last names by probability as input varies from 1L to Long.MAX_VALUE
                                        • +
                                        +
                                      • +
                                      +

                                      NumberNameToString

                                      +

                                      Provides the spelled-out name of a number. For example, an input of 7 would yield "seven". An input of 4234 yields the value "four thousand thirty four". The maximum value is limited at 999,999,999.

                                      +
                                        +
                                      • long -> NumberNameToString() -> String
                                      • +
                                      +

                                      StateCodes

                                      +

                                      Return a valid state code. (abbreviation)

                                      +
                                        +
                                      • long -> StateCodes() -> String +
                                          +
                                        • example: StateCodes()
                                        • +
                                        +
                                      • +
                                      +

                                      StateCodesByDensity

                                      +

                                      Return a state code (abbreviation), weighted by population density.

                                      +
                                        +
                                      • long -> StateCodesByDensity() -> String +
                                          +
                                        • example: StateCodesByDensity()
                                        • +
                                        +
                                      • +
                                      +

                                      StateCodesByPopulation

                                      +

                                      Return a state code (abbreviation), weighted by population.

                                      +
                                        +
                                      • long -> StateCodesByPopulation() -> String +
                                          +
                                        • example: StateCodesByPopulation()
                                        • +
                                        +
                                      • +
                                      +

                                      StateNames

                                      +

                                      Return a valid state name.

                                      +
                                        +
                                      • long -> StateNames() -> String +
                                          +
                                        • example: StateNames()
                                        • +
                                        +
                                      • +
                                      +

                                      StateNamesByDensity

                                      +

                                      Return a state name, weighted by population density.

                                      +
                                        +
                                      • long -> StateNamesByDensity() -> String +
                                          +
                                        • example: StateNamesByDensity()
                                        • +
                                        +
                                      • +
                                      +

                                      StateNamesByPopulation

                                      +

                                      Return a state name, weighted by total population.

                                      +
                                        +
                                      • long -> StateNamesByPopulation() -> String +
                                          +
                                        • example: StateNamesByPopulation()
                                        • +
                                        +
                                      • +
                                      +

                                      TimeZones

                                      +

                                      Return a state name, weighted by population density.

                                      +
                                        +
                                      • long -> TimeZones() -> String +
                                          +
                                        • example: Timezones()
                                        • +
                                        +
                                      • +
                                      +

                                      TimeZonesByDensity

                                      +

                                      Return a state name, weighted by population density.

                                      +
                                        +
                                      • long -> TimeZonesByDensity() -> String +
                                          +
                                        • example: TimezonesByDensity
                                        • +
                                        +
                                      • +
                                      +

                                      TimeZonesByPopulation

                                      +

                                      Return a state name, weighted by population.

                                      +
                                        +
                                      • long -> TimeZonesByPopulation() -> String +
                                          +
                                        • example: TimezonesByPopulation()
                                        • +
                                        +
                                      • +
                                      +

                                      ToMD5ByteBuffer

                                      +

                                      Converts the byte image of the input long to a MD5 digest in ByteBuffer form. Deprecated usage due to unsafe MD5 digest. Replaced with DigestToByteBuffer with MD5 when absolutely needed for existing NB tests. However, stronger encryption algorithms (e.g. SHA-256) are recommended due to MD5's limitations.

                                      +
                                        +
                                      • long -> ToMD5ByteBuffer() -> java.nio.ByteBuffer +
                                          +
                                        • +

                                          notes: Deprecated usage due to unsafe MD5 digest. +Use the DigestToByteBuffer with alternatives other than MD5.

                                          +
                                        • +
                                        • +

                                          example: MD5ByteBuffer()

                                          +
                                        • +
                                        • +

                                          convert the a input to an md5 digest of its bytes

                                          +
                                        • +
                                        +
                                      • +
                                      +

                                      ZipCodes

                                      +

                                      Return a valid zip code.

                                      +
                                        +
                                      • long -> ZipCodes() -> String +
                                          +
                                        • example: ZipCodes()
                                        • +
                                        +
                                      • +
                                      +

                                      ZipCodesByDensity

                                      +

                                      Return a zip code, weighted by population density.

                                      +
                                        +
                                      • long -> ZipCodesByDensity() -> String +
                                          +
                                        • example: ZipCodesByDensity
                                        • +
                                        +
                                      • +
                                      +

                                      ZipCodesByPopulation

                                      +

                                      Return a zip code, weighted by population.

                                      +
                                        +
                                      • long -> ZipCodesByPopulation() -> String +
                                          +
                                        • example: ZipCodesByPopulation()
                                        • +
                                        +
                                      • +
                                      + +

                                      Back to top

                                      +
                                      + +
                                      +
                                      +
                                      +
                                      + +

                                      Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                      +
                                      +
                                      + + diff --git a/reference/bindings/funcref-state/index.html b/reference/bindings/funcref-state/index.html new file mode 100644 index 000000000..c58d2958e --- /dev/null +++ b/reference/bindings/funcref-state/index.html @@ -0,0 +1,1174 @@ + + + + + + + + + + + + + + + + state functions | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      +
                                      + + + + + + + + +
                                      + +

                                      Functions in the state category allow you to do things with side-effects in the function flow. Specifically, they allow +you to save or load values of named variables to thread-local registers. These work best when used with non-async +activities, since the normal statement grouping allows you to share data between statements in the sequence. It is not +advised to use these with async activities.

                                      +

                                      When using these functions, be careful that you call them when needed. For example, if you have a named binding which +will save a value, that action only occurs if some statement with this named binding is used.

                                      +

                                      For example, if you have an account records and transaction records, where you want to save the account identifier to +use within the transaction inserts, you must ensure that each account binding is used within the thread first.

                                      +

                                      Clear

                                      +

                                      Clears the per-thread map which is used by the Expr function.

                                      +
                                        +
                                      • +

                                        Object -> Clear() -> Object

                                        +
                                          +
                                        • +

                                          notes: Clear all named entries from the per-thread map.

                                          +
                                        • +
                                        • +

                                          example: Clear()

                                          +
                                        • +
                                        • +

                                          clear all thread-local variables

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        Object -> Clear(String[]...: names) -> Object

                                        +
                                          +
                                        • +

                                          notes: Clear the specified names from the per-thread map. +@param names The names to be removed from the map.

                                          +
                                        • +
                                        • +

                                          example: Clear('foo')

                                          +
                                        • +
                                        • +

                                          clear the thread-local variable 'foo'

                                          +
                                        • +
                                        • +

                                          example: Clear('foo','bar')

                                          +
                                        • +
                                        • +

                                          clear the thread-local variables 'foo' and 'bar'

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Clear() -> long

                                        +
                                          +
                                        • +

                                          notes: Clear all named entries from the per-thread map.

                                          +
                                        • +
                                        • +

                                          example: Clear()

                                          +
                                        • +
                                        • +

                                          clear all thread-local variables

                                          +
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Clear(String[]...: names) -> long

                                        +
                                          +
                                        • +

                                          notes: Clear the specified names from the per-thread map. +@param names The names to be removed from the map.

                                          +
                                        • +
                                        • +

                                          example: Clear('foo')

                                          +
                                        • +
                                        • +

                                          clear the thread-local variable 'foo'

                                          +
                                        • +
                                        • +

                                          example: Clear('foo','bar')

                                          +
                                        • +
                                        • +

                                          clear the thread-local variables 'foo' and 'bar'

                                          +
                                        • +
                                        +
                                      • +
                                      +

                                      Load

                                      +

                                      Load a named value from the per-thread state map. The previous input value will be forgotten, and the named value will replace it before the next function in the chain.

                                      +
                                        +
                                      • +

                                        String -> Load(String: name) -> String

                                        +
                                          +
                                        • example: Load('foo')
                                        • +
                                        • for the current thread, load a String value from the named variable
                                        • +
                                        +
                                      • +
                                      • +

                                        String -> Load(String: name, String: defaultvalue) -> String

                                        +
                                          +
                                        • example: Load('foo','track05')
                                        • +
                                        • for the current thread, load a String value from the named variable, or teh default value if the variable is not yet defined.
                                        • +
                                        +
                                      • +
                                      • +

                                        String -> Load(function.Function<Object,Object>: nameFunc) -> String

                                        +
                                          +
                                        • example: Load(NumberNameToString())
                                        • +
                                        • for the current thread, load a String value from the named variable, where the variable name is provided by a function
                                        • +
                                        +
                                      • +
                                      • +

                                        String -> Load(function.Function<Object,Object>: nameFunc, String: defaultValue) -> String

                                        +
                                          +
                                        • example: Load(NumberNameToString(),'track05')
                                        • +
                                        • for the current thread, load a String value from the named variable, where the variable name is provided by a function, or the default value if the variable is not yet defined.
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> Load(String: name) -> int

                                        +
                                          +
                                        • example: Load('foo')
                                        • +
                                        • for the current thread, load an int value from the named variable
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> Load(String: name, int: defaultValue) -> int

                                        +
                                          +
                                        • example: Load('foo',42)
                                        • +
                                        • for the current thread, load an int value from the named variable, or return the default value if it is undefined.
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> Load(function.Function<Object,Object>: nameFunc) -> int

                                        +
                                          +
                                        • example: Load(NumberNameToString())
                                        • +
                                        • for the current thread, load an int value from the named variable, where the variable name is provided by a function.
                                        • +
                                        +
                                      • +
                                      • +

                                        int -> Load(function.Function<Object,Object>: nameFunc, int: defaultValue) -> int

                                        +
                                          +
                                        • example: Load(NumberNameToString(),42)
                                        • +
                                        • for the current thread, load an int value from the named variable, where the variable name is provided by a function, or the default value if the named variable is undefined.
                                        • +
                                        +
                                      • +
                                      • +

                                        double -> Load(String: name) -> double

                                        +
                                          +
                                        • example: Load('foo')
                                        • +
                                        • for the current thread, load a double value from the named variable
                                        • +
                                        +
                                      • +
                                      • +

                                        double -> Load(String: name, double: defaultValue) -> double

                                        +
                                          +
                                        • example: Load('foo',432.0D)
                                        • +
                                        • for the current thread, load a double value from the named variable, or the defaultvalue if it is not yet defined.
                                        • +
                                        +
                                      • +
                                      • +

                                        double -> Load(function.Function<Object,Object>: nameFunc) -> double

                                        +
                                          +
                                        • example: Load(NumberNameToString())
                                        • +
                                        • for the current thread, load a double value from the named variable, where the variablename is provided by a function.
                                        • +
                                        +
                                      • +
                                      • +

                                        double -> Load(function.Function<Object,Object>: nameFunc, double: defaultValue) -> double

                                        +
                                          +
                                        • example: Load(NumberNameToString(),1234.5D)
                                        • +
                                        • for the current thread, load a double value from the named variable, where the variablename is provided by a function, or the default value if the named value is not yet defined.
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Load(String: name) -> long

                                        +
                                          +
                                        • example: Load('foo')
                                        • +
                                        • for the current thread, load a long value from the named variable
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Load(String: name, long: defaultValue) -> long

                                        +
                                          +
                                        • example: Load('foo', 423L)
                                        • +
                                        • for the current thread, load a long value from the named variable, or the default value if the variable is not yet defined
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Load(function.Function<Object,Object>: nameFunc) -> long

                                        +
                                          +
                                        • example: Load(NumberNameToString())
                                        • +
                                        • for the current thread, load a long value from the named variable, where the variable name is provided by the provided by a function.
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Load(function.Function<Object,Object>: nameFunc, long: defaultvalue) -> long

                                        +
                                          +
                                        • example: Load(NumberNameToString(),22L)
                                        • +
                                        • for the current thread, load a long value from the named variable, where the variable name is provided by the provided by a function, or the default value if the variable is not yet defined
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Load(String: name) -> Object

                                        +
                                          +
                                        • example: Load('foo')
                                        • +
                                        • for the current thread, load an Object value from the named variable
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Load(function.LongFunction: nameFunc) -> Object

                                        +
                                          +
                                        • example: Load(NumberNameToString())
                                        • +
                                        • for the current thread, load an Object value from the named variable, where the variable name is returned by the provided function
                                        • +
                                        + +
                                      • +

                                        long -> Load(String: name, Object: defaultValue) -> Object

                                        +
                                          +
                                        • example: Load('foo','testvalue')
                                        • +
                                        • for the current thread, load an Object value from the named variable, or the default value if the variable is not yet defined.
                                        • +
                                        +
                                      • +
                                      • +

                                        long -> Load(function.LongFunction: nameFunc, Object: defaultValue) -> Object

                                        +
                                          +
                                        • example: Load(NumberNameToString(),'testvalue')
                                        • +
                                        • for the current thread, load an Object value from the named variable, where the variable name is returned by the provided function, or thedefault value if the variable is not yet defined.
                                        • +
                                        + +
                                      • +

                                        Object -> Load(String: name) -> Object

                                        +
                                          +
                                        • example: Load('foo')
                                        • +
                                        • for the current thread, load an Object value from the named variable
                                        • +
                                        +
                                      • +
                                      • +

                                        Object -> Load(function.Function<Object,Object>: nameFunc) -> Object

                                        +
                                          +
                                        • example: Load(NumberNameToString())
                                        • +
                                        • for the current thread, load an Object value from the named variable, where the variable name is returned by the provided function
                                        • +
                                        +
                                      • +
                                      • +

                                        Object -> Load(String: name, Object: defaultValue) -> Object

                                        +
                                          +
                                        • example: Load('foo','testvalue')
                                        • +
                                        • for the current thread, load an Object value from the named variable, or the default value if the variable is not yet defined.
                                        • +
                                        +
                                      • +
                                      • +

                                        Object -> Load(function.Function<Object,Object>: nameFunc, Object: defaultValue) -> Object

                                        +
                                          +
                                        • example: Load(NumberNameToString(),'testvalue')
                                        • +
                                        • for the current thread, load an Object value from the named variable, where the variable name is returned by the provided function, or thedefault value if the variable is not yet defined.
                                        • +
                                        +
                                      • + +

                                        LoadDouble

                                        +

                                        Load a value from a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. If the named variable is not defined, then the default value is returned.

                                        +
                                          +
                                        • +

                                          long -> LoadDouble(String: name) -> double

                                          +
                                            +
                                          • example: LoadDouble('foo')
                                          • +
                                          • for the current thread, load a double value from the named variable.
                                          • +
                                          +
                                        • +
                                        • +

                                          long -> LoadDouble(String: name, double: defaultValue) -> double

                                          +
                                            +
                                          • example: LoadDouble('foo',23D)
                                          • +
                                          • for the current thread, load a double value from the named variable,or the default value if the named variable is not defined.
                                          • +
                                          +
                                        • +
                                        • +

                                          long -> LoadDouble(function.LongFunction: nameFunc) -> double

                                          +
                                            +
                                          • example: LoadDouble(NumberNameToString())
                                          • +
                                          • for the current thread, load a double value from the named variable, where the variable name is provided by a function.
                                          • +
                                          + +
                                        • +

                                          long -> LoadDouble(function.LongFunction: nameFunc, double: defaultValue) -> double

                                          +
                                            +
                                          • example: LoadDouble(NumberNameToString(),23D)
                                          • +
                                          • for the current thread, load a double value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                          • +
                                          + +
                                        • +

                                          Object -> LoadDouble(String: name) -> Double

                                          +
                                            +
                                          • example: LoadDouble('foo')
                                          • +
                                          • for the current thread, load a double value from the named variable.
                                          • +
                                          +
                                        • +
                                        • +

                                          Object -> LoadDouble(String: name, double: defaultValue) -> Double

                                          +
                                            +
                                          • example: LoadDouble('foo',23D)
                                          • +
                                          • for the current thread, load a double value from the named variable,or the default value if the named variable is not defined.
                                          • +
                                          +
                                        • +
                                        • +

                                          Object -> LoadDouble(function.Function<Object,Object>: nameFunc) -> Double

                                          +
                                            +
                                          • example: LoadDouble(NumberNameToString())
                                          • +
                                          • for the current thread, load a double value from the named variable, where the variable name is provided by a function.
                                          • +
                                          +
                                        • +
                                        • +

                                          Object -> LoadDouble(function.Function<Object,Object>: nameFunc, double: defaultValue) -> Double

                                          +
                                            +
                                          • example: LoadDouble(NumberNameToString(),23D)
                                          • +
                                          • for the current thread, load a double value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                          • +
                                          +
                                        • + +

                                          LoadFloat

                                          +

                                          Load a value from a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. If the named variable is not defined, then the default value is returned.

                                          +
                                            +
                                          • +

                                            Object -> LoadFloat(String: name) -> Float

                                            +
                                              +
                                            • example: LoadFloat('foo')
                                            • +
                                            • for the current thread, load a float value from the named variable.
                                            • +
                                            +
                                          • +
                                          • +

                                            Object -> LoadFloat(String: name, float: defaultValue) -> Float

                                            +
                                              +
                                            • example: LoadFloat('foo',23F)
                                            • +
                                            • for the current thread, load a float value from the named variable,or the default value if the named variable is not defined.
                                            • +
                                            +
                                          • +
                                          • +

                                            Object -> LoadFloat(function.Function<Object,Object>: nameFunc) -> Float

                                            +
                                              +
                                            • example: LoadFloat(NumberNameToString())
                                            • +
                                            • for the current thread, load a float value from the named variable,where the variable name is provided by a function.
                                            • +
                                            +
                                          • +
                                          • +

                                            Object -> LoadFloat(function.Function<Object,Object>: nameFunc, float: defaultValue) -> Float

                                            +
                                              +
                                            • example: LoadFloat(NumberNameToString(),23F)
                                            • +
                                            • for the current thread, load a float value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                            • +
                                            +
                                          • +
                                          • +

                                            long -> LoadFloat(String: name) -> Float

                                            +
                                              +
                                            • example: LoadFloat('foo')
                                            • +
                                            • for the current thread, load a float value from the named variable.
                                            • +
                                            +
                                          • +
                                          • +

                                            long -> LoadFloat(String: name, float: defaultValue) -> Float

                                            +
                                              +
                                            • example: LoadFloat('foo',23F)
                                            • +
                                            • for the current thread, load a float value from the named variable,or the default value if the named variable is not defined.
                                            • +
                                            +
                                          • +
                                          • +

                                            long -> LoadFloat(function.LongFunction: nameFunc) -> Float

                                            +
                                              +
                                            • example: LoadFloat(NumberNameToString())
                                            • +
                                            • for the current thread, load a float value from the named variable,where the variable name is provided by a function.
                                            • +
                                            + +
                                          • +

                                            long -> LoadFloat(function.LongFunction: nameFunc, float: defaultValue) -> Float

                                            +
                                              +
                                            • example: LoadFloat(NumberNameToString(),23F)
                                            • +
                                            • for the current thread, load a float value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                            • +
                                            + + +

                                            LoadInteger

                                            +

                                            Load a value from a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. If the named variable is not defined, then the default value is returned.

                                            +
                                              +
                                            • +

                                              Object -> LoadInteger(String: name) -> Integer

                                              +
                                                +
                                              • example: LoadInteger('foo')
                                              • +
                                              • for the current thread, load an integer value from the named variable.
                                              • +
                                              +
                                            • +
                                            • +

                                              Object -> LoadInteger(String: name, int: defaultValue) -> Integer

                                              +
                                                +
                                              • example: LoadInteger('foo',42)
                                              • +
                                              • for the current thread, load an integer value from the named variable, or the default value if the named variable is not defined.
                                              • +
                                              +
                                            • +
                                            • +

                                              Object -> LoadInteger(function.Function<Object,Object>: nameFunc) -> Integer

                                              +
                                                +
                                              • example: LoadInteger(NumberNameToString())
                                              • +
                                              • for the current thread, load an integer value from the named variable,where the variable name is provided by a function.
                                              • +
                                              +
                                            • +
                                            • +

                                              Object -> LoadInteger(function.Function<Object,Object>: nameFunc, int: defaultValue) -> Integer

                                              +
                                                +
                                              • example: LoadInteger(NumberNameToString(),42)
                                              • +
                                              • for the current thread, load an integer value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                              • +
                                              +
                                            • +
                                            • +

                                              long -> LoadInteger(String: name) -> int

                                              +
                                                +
                                              • example: LoadInteger('foo')
                                              • +
                                              • for the current thread, load an integer value from the named variable.
                                              • +
                                              +
                                            • +
                                            • +

                                              long -> LoadInteger(String: name, int: defaultValue) -> int

                                              +
                                                +
                                              • example: LoadInteger('foo',42)
                                              • +
                                              • for the current thread, load an integer value from the named variable, or the default value if the named variable is not defined.
                                              • +
                                              +
                                            • +
                                            • +

                                              long -> LoadInteger(function.LongFunction: nameFunc) -> int

                                              +
                                                +
                                              • example: LoadInteger(NumberNameToString())
                                              • +
                                              • for the current thread, load an integer value from the named variable,where the variable name is provided by a function.
                                              • +
                                              + +
                                            • +

                                              long -> LoadInteger(function.LongFunction: nameFunc, int: defaultValue) -> int

                                              +
                                                +
                                              • example: LoadInteger(NumberNameToString(),42)
                                              • +
                                              • for the current thread, load an integer value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                              • +
                                              + + +

                                              LoadLong

                                              +

                                              Load a value from a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. If the named variable is not defined, then the default value is returned.

                                              +
                                                +
                                              • +

                                                long -> LoadLong(String: name) -> long

                                                +
                                                  +
                                                • example: LoadLong('foo',42L)
                                                • +
                                                • for the current thread, load a long value from the named variable.
                                                • +
                                                +
                                              • +
                                              • +

                                                long -> LoadLong(String: name, long: defaultValue) -> long

                                                +
                                                  +
                                                • example: LoadLong('foo',42L)
                                                • +
                                                • for the current thread, load a long value from the named variable, or the default value if the named variable is not defined.
                                                • +
                                                +
                                              • +
                                              • +

                                                long -> LoadLong(function.LongFunction: nameFunc) -> long

                                                +
                                                  +
                                                • example: LoadLong(NumberNameToString(),42L)
                                                • +
                                                • for the current thread, load a long value from the named variable,where the variable name is provided by a function.
                                                • +
                                                + +
                                              • +

                                                long -> LoadLong(function.LongFunction: nameFunc, long: defaultValue) -> long

                                                +
                                                  +
                                                • example: LoadLong(NumberNameToString(),42L)
                                                • +
                                                • for the current thread, load a long value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                                • +
                                                + +
                                              • +

                                                Object -> LoadLong(String: name) -> Long

                                                +
                                                  +
                                                • example: LoadLong('foo',42L)
                                                • +
                                                • for the current thread, load a long value from the named variable.
                                                • +
                                                +
                                              • +
                                              • +

                                                Object -> LoadLong(String: name, long: defaultValue) -> Long

                                                +
                                                  +
                                                • example: LoadLong('foo',42L)
                                                • +
                                                • for the current thread, load a long value from the named variable, or the default value if the named variable is not defined.
                                                • +
                                                +
                                              • +
                                              • +

                                                Object -> LoadLong(function.Function<Object,Object>: nameFunc) -> Long

                                                +
                                                  +
                                                • example: LoadLong(NumberNameToString(),42L)
                                                • +
                                                • for the current thread, load a long value from the named variable,where the variable name is provided by a function.
                                                • +
                                                +
                                              • +
                                              • +

                                                Object -> LoadLong(function.Function<Object,Object>: nameFunc, long: defaultValue) -> Long

                                                +
                                                  +
                                                • example: LoadLong(NumberNameToString(),42L)
                                                • +
                                                • for the current thread, load a long value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                                • +
                                                +
                                              • + +

                                                LoadString

                                                +

                                                Load a value from a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. If the named variable is not defined, then the default value is returned.

                                                +
                                                  +
                                                • +

                                                  Object -> LoadString(String: name) -> String

                                                  +
                                                    +
                                                  • example: LoadString('foo','examplevalue')
                                                  • +
                                                  • for the current thread, load a String value from the named variable.
                                                  • +
                                                  +
                                                • +
                                                • +

                                                  Object -> LoadString(String: name, String: defaultValue) -> String

                                                  +
                                                    +
                                                  • example: LoadString('foo','examplevalue')
                                                  • +
                                                  • for the current thread, load a String value from the named variable, or the default value if the named variable is not defined.
                                                  • +
                                                  +
                                                • +
                                                • +

                                                  Object -> LoadString(function.Function<Object,Object>: nameFunc) -> String

                                                  +
                                                    +
                                                  • example: LoadString(NumberNameToString(),'examplevalue')
                                                  • +
                                                  • for the current thread, load a String value from the named variable, or the default value if the named variable is not defined.
                                                  • +
                                                  +
                                                • +
                                                • +

                                                  Object -> LoadString(function.Function<Object,Object>: nameFunc, String: defaultValue) -> String

                                                  +
                                                    +
                                                  • example: LoadString(NumberNameToString(),'examplevalue')
                                                  • +
                                                  • for the current thread, load a String value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                                  • +
                                                  +
                                                • +
                                                • +

                                                  long -> LoadString(String: name) -> String

                                                  +
                                                    +
                                                  • example: LoadString('foo','examplevalue')
                                                  • +
                                                  • for the current thread, load a String value from the named variable.
                                                  • +
                                                  +
                                                • +
                                                • +

                                                  long -> LoadString(String: name, String: defaultValue) -> String

                                                  +
                                                    +
                                                  • example: LoadString('foo','examplevalue')
                                                  • +
                                                  • for the current thread, load a String value from the named variable, or the default value if the named variable is not defined.
                                                  • +
                                                  +
                                                • +
                                                • +

                                                  long -> LoadString(function.LongFunction: nameFunc) -> String

                                                  +
                                                    +
                                                  • example: LoadString(NumberNameToString(),'examplevalue')
                                                  • +
                                                  • for the current thread, load a String value from the named variable, or the default value if the named variable is not defined.
                                                  • +
                                                  + +
                                                • +

                                                  long -> LoadString(function.LongFunction: nameFunc, String: defaultValue) -> String

                                                  +
                                                    +
                                                  • example: LoadString(NumberNameToString(),'examplevalue')
                                                  • +
                                                  • for the current thread, load a String value from the named variable,where the variable name is provided by a function, or the default value if the namedvariable is not defined.
                                                  • +
                                                  + + +

                                                  NullOrLoad

                                                  +

                                                  Reads a long variable from the input, hashes and scales it to the unit interval 0.0d - 1.0d, then uses the result to determine whether to return null object or a loaded value.

                                                  +
                                                    +
                                                  • long -> NullOrLoad(double: ratio, String: varname) -> Object
                                                  • +
                                                  +

                                                  NullOrPass

                                                  +

                                                  Reads a long variable from the thread local variable map, hashes and scales it to the unit interval 0.0d - 1.0d, then uses the result to determine whether to return a null object or the input value.

                                                  +
                                                    +
                                                  • Object -> NullOrPass(double: ratio, String: varname) -> Object
                                                  • +
                                                  +

                                                  Save

                                                  +

                                                  Save the current input value at this point in the function chain to a thread-local variable name. The input value is unchanged, and available for the next function in the chain to use as-is.

                                                  +
                                                    +
                                                  • +

                                                    long -> Save(String: name) -> long

                                                    +
                                                      +
                                                    • example: Save('foo')
                                                    • +
                                                    • for the current thread, save the input object value to the named variable
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    long -> Save(function.LongFunction: nameFunc) -> long

                                                    +
                                                      +
                                                    • example: Save(NumberNameToString())
                                                    • +
                                                    • for the current thread, save the current input object value to the named variable,where the variable name is provided by a function.
                                                    • +
                                                    + +
                                                  • +

                                                    long -> Save(String: name) -> long

                                                    +
                                                      +
                                                    • example: Save('foo')
                                                    • +
                                                    • save the current long value to the name 'foo' in this thread
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    long -> Save(function.Function<Object,Object>: nameFunc) -> long

                                                    +
                                                      +
                                                    • example: Save(NumberNameToString())
                                                    • +
                                                    • save the current long value to the name generated by the function given.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    String -> Save(String: name) -> String

                                                    +
                                                      +
                                                    • example: Save('foo')
                                                    • +
                                                    • save the current String value to the name 'foo' in this thread
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    String -> Save(function.Function<Object,Object>: nameFunc) -> String

                                                    +
                                                      +
                                                    • example: Save(NumberNameToString())
                                                    • +
                                                    • save the current String value to a named variable in this thread, where the variable name is provided by a function
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    Object -> Save(String: name) -> Object

                                                    +
                                                      +
                                                    • example: Save('foo')
                                                    • +
                                                    • for the current thread, save the input object value to the named variable
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    Object -> Save(function.Function<Object,Object>: nameFunc) -> Object

                                                    +
                                                      +
                                                    • example: Save(NumberNameToString())
                                                    • +
                                                    • for the current thread, save the current input object value to the named variable,where the variable name is provided by a function.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    double -> Save(String: name) -> double

                                                    +
                                                      +
                                                    • example: Save('foo')
                                                    • +
                                                    • for the current thread, save the current double value to the named variable.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    double -> Save(function.Function<Object,Object>: nameFunc) -> double

                                                    +
                                                      +
                                                    • example: Save(NumberNameToString())
                                                    • +
                                                    • for the current thread, save the current double value to the name 'foo' in this thread, where the variable name is provided by a function.
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    int -> Save(String: name) -> int

                                                    +
                                                      +
                                                    • example: Save('foo')
                                                    • +
                                                    • save the current int value to the name 'foo' in this thread
                                                    • +
                                                    +
                                                  • +
                                                  • +

                                                    int -> Save(function.Function<Object,Object>: nameFunc) -> int

                                                    +
                                                      +
                                                    • example: Save(NumberNameToString())
                                                    • +
                                                    • save the current int value to a named variable in this thread,where the variable name is provided by a function.
                                                    • +
                                                    +
                                                  • + +

                                                    SaveDouble

                                                    +

                                                    Save a value to a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. Note that the input type is not that suitable for constructing names, so this is more likely to be used in an indirect naming pattern like SaveDouble(Load('id'))

                                                    +
                                                      +
                                                    • +

                                                      double -> SaveDouble(String: name) -> double

                                                      +
                                                        +
                                                      • example: Save('foo')
                                                      • +
                                                      • save the current double value to the name 'foo' in this thread
                                                      • +
                                                      +
                                                    • +
                                                    • +

                                                      double -> SaveDouble(function.Function<Object,Object>: nameFunc) -> double

                                                      +
                                                        +
                                                      • example: Save(NumberNameToString())
                                                      • +
                                                      • save a double value to a named variable in the current thread, where the variable name is provided by a function.
                                                      • +
                                                      +
                                                    • +
                                                    • +

                                                      long -> SaveDouble(String: name) -> double

                                                      +
                                                        +
                                                      • example: Save('foo')
                                                      • +
                                                      • save the current double value to the name 'foo' in this thread
                                                      • +
                                                      +
                                                    • +
                                                    • +

                                                      long -> SaveDouble(function.LongFunction: nameFunc) -> double

                                                      +
                                                        +
                                                      • example: Save(NumberNameToString())
                                                      • +
                                                      • save a double value to a named variable in the current thread, where the variable name is provided by a function.
                                                      • +
                                                      + + +

                                                      SaveFloat

                                                      +

                                                      Save a value to a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. Note that the input type is not that suitable for constructing names, so this is more likely to be used in an indirect naming pattern like SaveFloat(Load('id'))

                                                      +
                                                        +
                                                      • +

                                                        long -> SaveFloat(String: name) -> Float

                                                        +
                                                          +
                                                        • example: SaveFloat('foo')
                                                        • +
                                                        • save the current float value to a named variable in this thread.
                                                        • +
                                                        +
                                                      • +
                                                      • +

                                                        long -> SaveFloat(function.LongFunction: nameFunc) -> Float

                                                        +
                                                          +
                                                        • example: SaveFloat(NumberNameToString())
                                                        • +
                                                        • save the current float value to a named variable in this thread, where the variable name is provided by a function.
                                                        • +
                                                        + +
                                                      • +

                                                        Float -> SaveFloat(String: name) -> Float

                                                        +
                                                          +
                                                        • example: SaveFloat('foo')
                                                        • +
                                                        • save the current float value to a named variable in this thread.
                                                        • +
                                                        +
                                                      • +
                                                      • +

                                                        Float -> SaveFloat(function.Function<Object,Object>: nameFunc) -> Float

                                                        +
                                                          +
                                                        • example: SaveFloat(NumberNameToString())
                                                        • +
                                                        • save the current float value to a named variable in this thread, where the variable name is provided by a function.
                                                        • +
                                                        +
                                                      • + +

                                                        SaveInteger

                                                        +

                                                        Save a value to a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. Note that the input type is not that suitable for constructing names, so this is more likely to be used in an indirect naming pattern like SaveInteger(Load('id'))

                                                        +
                                                          +
                                                        • +

                                                          int -> SaveInteger(String: name) -> int

                                                          +
                                                            +
                                                          • example: SaveInteger('foo')
                                                          • +
                                                          • save the current integer value to a named variable in this thread.
                                                          • +
                                                          +
                                                        • +
                                                        • +

                                                          int -> SaveInteger(function.Function<Object,Object>: nameFunc) -> int

                                                          +
                                                            +
                                                          • example: SaveInteger(NumberNameToString())
                                                          • +
                                                          • save the current integer value to a named variable in this thread, where the variable name is provided by a function.
                                                          • +
                                                          +
                                                        • +
                                                        • +

                                                          long -> SaveInteger(String: name) -> int

                                                          +
                                                            +
                                                          • example: SaveInteger('foo')
                                                          • +
                                                          • save the current integer value to a named variable in this thread.
                                                          • +
                                                          +
                                                        • +
                                                        • +

                                                          long -> SaveInteger(function.LongFunction: nameFunc) -> int

                                                          +
                                                            +
                                                          • example: SaveInteger(NumberNameToString())
                                                          • +
                                                          • save the current integer value to a named variable in this thread, where the variable name is provided by a function.
                                                          • +
                                                          + + +

                                                          SaveLong

                                                          +

                                                          Save a value to a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. Note that the input type is not that suitable for constructing names, so this is more likely to be used in an indirect naming pattern like SaveLong(Load('id'))

                                                          +
                                                            +
                                                          • +

                                                            long -> SaveLong(String: name) -> long

                                                            +
                                                              +
                                                            • example: SaveLong('foo')
                                                            • +
                                                            • save the current long value to a named variable in this thread.
                                                            • +
                                                            +
                                                          • +
                                                          • +

                                                            long -> SaveLong(function.Function<Object,Object>: nameFunc) -> long

                                                            +
                                                              +
                                                            • example: SaveLong(NumberNameToString())
                                                            • +
                                                            • save the current long value to a named variable in this thread, where the variable name is provided by a function.
                                                            • +
                                                            +
                                                          • +
                                                          • +

                                                            long -> SaveLong(String: name) -> long

                                                            +
                                                              +
                                                            • example: SaveLong('foo')
                                                            • +
                                                            • save the current long value to a named variable in this thread.
                                                            • +
                                                            +
                                                          • +
                                                          • +

                                                            long -> SaveLong(function.Function<Object,Object>: nameFunc) -> long

                                                            +
                                                              +
                                                            • example: SaveLong(NumberNameToString())
                                                            • +
                                                            • save the current long value to a named variable in this thread, where the variable name is provided by a function.
                                                            • +
                                                            +
                                                          • +
                                                          +

                                                          SaveString

                                                          +

                                                          Save a value to a named thread-local variable, where the variable name is fixed or a generated variable name from a provided function. Note that the input type is not that suitable for constructing names, so this is more likely to be used in an indirect naming pattern like SaveString(Load('id'))

                                                          +
                                                            +
                                                          • +

                                                            long -> SaveString(String: name) -> String

                                                            +
                                                              +
                                                            • example: SaveString('foo')
                                                            • +
                                                            • save the current String value to a named variable in this thread.
                                                            • +
                                                            +
                                                          • +
                                                          • +

                                                            long -> SaveString(function.LongFunction: nameFunc) -> String

                                                            +
                                                              +
                                                            • example: SaveString(NumberNameToString())
                                                            • +
                                                            • save the current String value to a named variable in this thread, where the variable name is provided by a function.
                                                            • +
                                                            + +
                                                          • +

                                                            String -> SaveString(String: name) -> String

                                                            +
                                                              +
                                                            • example: SaveString('foo')
                                                            • +
                                                            • save the current String value to a named variable in this thread.
                                                            • +
                                                            +
                                                          • +
                                                          • +

                                                            String -> SaveString(function.Function<Object,Object>: nameFunc) -> String

                                                            +
                                                              +
                                                            • example: SaveString(NumberNameToString())
                                                            • +
                                                            • save the current String value to a named variable in this thread, where the variable name is provided by a function.
                                                            • +
                                                            +
                                                          • + +

                                                            Show

                                                            +

                                                            Show diagnostic values for the thread-local variable map.

                                                            +
                                                              +
                                                            • +

                                                              long -> Show() -> String

                                                              +
                                                                +
                                                              • example: Show()
                                                              • +
                                                              • Show all values in a json-like format
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              long -> Show(String[]...: names) -> String

                                                              +
                                                                +
                                                              • example: Show('foo')
                                                              • +
                                                              • Show only the 'foo' value in a json-like format
                                                              • +
                                                              • example: Show('foo','bar')
                                                              • +
                                                              • Show the 'foo' and 'bar' values in a json-like format
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              Object -> Show() -> String

                                                              +
                                                                +
                                                              • example: Show()
                                                              • +
                                                              • Show all values in a json-like format
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              Object -> Show(String[]...: names) -> String

                                                              +
                                                                +
                                                              • example: Show('foo')
                                                              • +
                                                              • Show only the 'foo' value in a json-like format
                                                              • +
                                                              • example: Show('foo','bar')
                                                              • +
                                                              • Show the 'foo' and 'bar' values in a json-like format
                                                              • +
                                                              +
                                                            • +
                                                            +

                                                            Swap

                                                            +

                                                            Load a named value from the per-thread state map. The previous input value will be stored in the named value, and the previously stored value will be returned. A default value to return may be provided in case there was no previously stored value under the given name.

                                                            +
                                                              +
                                                            • +

                                                              Object -> Swap(String: name) -> Object

                                                              +
                                                                +
                                                              • example: Swap('foo')
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              Object -> Swap(String: name, Object: defaultValue) -> Object

                                                              +
                                                                +
                                                              • example: Swap('foo','examplevalue')
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable, or return the default value if the named value is not defined.
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              Object -> Swap(function.Function<Object,Object>: nameFunc) -> Object

                                                              +
                                                                +
                                                              • example: Swap(NumberNameToString())
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable, where the variable name is generated by the provided function.
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              Object -> Swap(function.Function<Object,Object>: nameFunc, Object: defaultValue) -> Object

                                                              +
                                                                +
                                                              • example: Swap(NumberNameToString(),'examplevalue')
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable, where the variable name is generated by the provided function, or the default value if the named value is not defined.
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              long -> Swap(String: name) -> Object

                                                              +
                                                                +
                                                              • example: Swap('foo')
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              long -> Swap(String: name, Object: defaultValue) -> Object

                                                              +
                                                                +
                                                              • example: Swap('foo','examplevalue')
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable, or return the default value if the named value is not defined.
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              long -> Swap(function.LongFunction: nameFunc) -> Object

                                                              +
                                                                +
                                                              • example: Swap(NumberNameToString())
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable, where the variable name is generated by the provided function.
                                                              • +
                                                              + +
                                                            • +

                                                              long -> Swap(function.LongFunction: nameFunc, Object: defaultValue) -> Object

                                                              +
                                                                +
                                                              • example: Swap(NumberNameToString(),'examplevalue')
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable, where the variable name is generated by the provided function, or the default value if the named value is not defined.
                                                              • +
                                                              + +
                                                            • +

                                                              long -> Swap(String: name) -> long

                                                              +
                                                                +
                                                              • example: Swap('foo')
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable.
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              long -> Swap(String: name, long: defaultValue) -> long

                                                              +
                                                                +
                                                              • example: Swap('foo',234L)
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable,or the default value if the named variable is not defined.
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              long -> Swap(function.LongFunction: nameFunc) -> long

                                                              +
                                                                +
                                                              • example: Swap(NumberNameToString())
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable, where the variable name is generated by the provided function.
                                                              • +
                                                              +
                                                            • +
                                                            • +

                                                              long -> Swap(function.LongFunction: nameFunc, long: defaultValue) -> long

                                                              +
                                                                +
                                                              • example: Swap(NumberNameToString(), 234L)
                                                              • +
                                                              • for the current thread, swap the input value with the named variable and returned the named variable, where the variable name is generated by the provided function, or the default value if the named variable is not defined.
                                                              • +
                                                              +
                                                            • + +

                                                              ThreadNum

                                                              +

                                                              Matches a digit sequence in the current thread name and caches it in a thread local. This allows you to use any intentionally indexed thread factories to provide an analogue for concurrency. Note that once the thread number is cached, it will not be refreshed. This means you can't change the thread name and get an updated value.

                                                              +
                                                                +
                                                              • +

                                                                long -> ThreadNum() -> int

                                                                +
                                                              • +
                                                              • +

                                                                long -> ThreadNum() -> long

                                                                +
                                                              • +
                                                              +

                                                              UnsetOrLoad

                                                              +

                                                              Reads a long variable from the input, hashes and scales it to the unit interval 0.0d - 1.0d, then uses the result to determine whether to return UNSET.value or a loaded value.

                                                              +
                                                                +
                                                              • long -> UnsetOrLoad(double: ratio, String: varname) -> Object
                                                              • +
                                                              +

                                                              UnsetOrPass

                                                              +

                                                              Reads a long variable from the thread local variable map, hashes and scales it to the unit interval 0.0d - 1.0d, then uses the result to determine whether to return UNSET.value or the input value.

                                                              +
                                                                +
                                                              • Object -> UnsetOrPass(double: ratio, String: varname) -> Object
                                                              • +
                                                              + +

                                                              Back to top

                                                              + + + +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/bindings/funcref-statistics/index.html b/reference/bindings/funcref-statistics/index.html new file mode 100644 index 000000000..0ad9a88eb --- /dev/null +++ b/reference/bindings/funcref-statistics/index.html @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + LongStats | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              LongStats

                                                              +

                                                              Provide a moving aggregate (min,max,avg,sum,count) of long values presented. This allows for sanity checks on values during prototyping, primarily. Using it for other purposes in actual workloads is not generally desirable, as this does not produce purely functional (deterministic) values.

                                                              +
                                                                +
                                                              • +

                                                                double -> LongStats(String: spec) -> double

                                                                +
                                                                  +
                                                                • notes: Given the specified statistic, provide an +updated result for all the values presented to this function's input. +@param spec One of 'min', 'max', 'count', 'avg', or 'sum'
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                double -> LongStats(String: spec, Object: func, boolean: truncate) -> double

                                                                +
                                                                  +
                                                                • notes: Given the specified statistic, a function, and whether to allow truncating conversions, +provide an updated result for all the values produced by the provided function when +given the input. +@param spec One of 'min', 'max', 'count', 'avg', or 'sum' +@param func Any function which can take a long or compatible input and produce a numeric value +@param truncate Whether or not to allow truncating conversions (long to int for example)
                                                                • +
                                                                +
                                                              • +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/bindings/index.html b/reference/bindings/index.html new file mode 100644 index 000000000..36610beb4 --- /dev/null +++ b/reference/bindings/index.html @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + TokenMapFileCycle | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              TokenMapFileCycle

                                                              +

                                                              Utility function used for advanced data generation experiments.

                                                              +
                                                                +
                                                              • int -> TokenMapFileCycle(String: filename, boolean: loopdata, boolean: ascending) -> long
                                                              • +
                                                              +

                                                              TokenMapFileNextCycle

                                                              +

                                                              Utility function used for advanced data generation experiments.

                                                              +
                                                                +
                                                              • int -> TokenMapFileNextCycle(String: filename, boolean: loopdata, boolean: ascending) -> long
                                                              • +
                                                              +

                                                              TokenMapFileNextToken

                                                              +

                                                              Utility function used for advanced data generation experiments.

                                                              +
                                                                +
                                                              • int -> TokenMapFileNextToken(String: filename, boolean: loopdata, boolean: ascending) -> long
                                                              • +
                                                              +

                                                              TokenMapFileToken

                                                              +

                                                              Utility function used for advanced data generation experiments.

                                                              +
                                                                +
                                                              • int -> TokenMapFileToken(String: filename, boolean: loopdata, boolean: ascending) -> long
                                                              • +
                                                              +

                                                              TriangularStep

                                                              +

                                                              Compute a value which increases monotonically with respect to the cycle value. +All values for f(X+(m>=0)) will be equal or greater than f(X). In effect, this +means that with a sequence of monotonic inputs, the results will be monotonic as +well as clustered. The values will approximate input/average, but will vary in frequency +around a simple binomial distribution.

                                                              +

                                                              The practical effect of this is to be able to compute a sequence of values +over inputs which can act as foreign keys, but which are effectively ordered.

                                                              +

                                                              Call for Ideas

                                                              +

                                                              Due to the complexity of generalizing this as a pure function over other distributions, +this is the only function of this type for now. If you are interested in this problem +domain and have some suggestions for how to extend it to other distributions, please +join the project or let us know.

                                                              +
                                                                +
                                                              • +

                                                                long -> TriangularStep(long: average, long: variance) -> long

                                                                +
                                                                  +
                                                                • example: TriangularStep(100,20)
                                                                • +
                                                                • Create a sequence of values where the average is 100, but the range of values is between 80 and 120.
                                                                • +
                                                                • example: TriangularStep(80,10)
                                                                • +
                                                                • Create a sequence of values where the average is 80, but the range of values is between 70 and 90.
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                long -> TriangularStep(long: average) -> long

                                                                +
                                                              • +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/cqld4/index.html b/reference/drivers/cqld4/index.html new file mode 100644 index 000000000..c6809ec85 --- /dev/null +++ b/reference/drivers/cqld4/index.html @@ -0,0 +1,422 @@ + + + + + + + + + + + + + + + + cqld4 | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              cqld4

                                                              +

                                                              This is the newly revamped driver for CQL which uses the DataStax OSS Driver version 4. As +there was a significant restructuring of the APIs between CQL driver 4.x and previous versions, this +driver is a clean and separate implementation which aims to use the features of version 4.x of the +native driver directly as well as new internal NoSQLBench APIs.

                                                              +

                                                              This means that many features that advanced testers may have been used to (the syntactical sugar, +the surfacing of advanced configuration properties in simple ways, and so on) will have to be +redesigned to fit with version 4 of the driver. Most users who do basic testing with direct CQL +syntax should see few issues, but advanced testers will need to consult this documentation +specifically to understand the differences between cqld4 driver features and cql driver +features.

                                                              +

                                                              Notably, these features need to be re-built on the cqld4 driver to bring it up to parity with +previous advanced testing features:

                                                              +
                                                                +
                                                              • verify
                                                              • +
                                                              • result set size metrics
                                                              • +
                                                              • explicit paging metrics
                                                              • +
                                                              +

                                                              Configuration

                                                              +

                                                              The DataStax Java Driver 4.* has a much different configuration system than previous versions. For +changing driver settings with this version it is highly recommended that users use the built-in +driver settings and configuration file/profile options, just as they would for an application. This +serves two goals: 1) to ensure that the settings you test with are portable from test environment to +application, and 2) to allow you to configure driver settings directly, without depending on +internal helper logic provided by NoSQLBench. This means that the driver options exposed are those +provided by the low-level driver, thus removing another dependency from your test setup.

                                                              +

                                                              Config Sources

                                                              +

                                                              By using the option driverconfig, you can have as many configuration sources as you like, even +mixing in JSON or remote URLs.

                                                              +

                                                              examples

                                                              +

                                                              Configure directly from a config file, or classpath resource:

                                                              +
                                                              # If this isn't found in the file system, the classpath will also be checked.
                                                              +nb5 ... driverconfig=myconfig.json
                                                              +
                                                              +

                                                              Configure directly from JSON:

                                                              +
                                                              nb5 ... driverconfig='{basic.request.timeout:"2 seconds"}'
                                                              +
                                                              +

                                                              Configure directly form a remote URL:

                                                              +
                                                              nb5 ... driverconfig='http://gist.github.com...'
                                                              +
                                                              +

                                                              Basic Cqld4 driver options

                                                              +
                                                                +
                                                              • hosts & localdc - (required unless using scb) - Set the endpoint and local datacenter name +for the driver. +
                                                                  +
                                                                • example: host=mydsehost localdc=testdc1
                                                                • +
                                                                +
                                                              • +
                                                              • port (optional for hosts) - Set the port to connect to for the CQL binary protocol.
                                                              • +
                                                              • driverconfig - (explained above) - set the configuration source for the driver.
                                                              • +
                                                              • username OR userfile - (optional, only one may be used) - If you need to specify a +username but want to put it in a file instead, simply use the userfile=myfile option. It is +not uncommon to say userfile=userfile.
                                                              • +
                                                              +
                                                                +
                                                              • password OR passfile - (optional, only one may be used) - Fi you need to specify a +password but want to put it ina file instead, simply use the passfile=mypassfile option. It +is not uncommon to say passfile=passfile.
                                                              • +
                                                              • showstmt - enable per-statement diagnostics which show as much of the statement as possible +for the given statement type. WARNING - Do not use this for performance testing, only for +diagnostics.
                                                              • +
                                                              • maxpages - configure the maximum number of pages allowed in a CQL result set. This is +configured to maxpages=1 by default, so that users will be aware of any paging that occurs +by default. If you expect and want to allow paging in your operation, then set this number +higher. A synthetic exception is generated as UnexpectedPagingException by default when +the number of pages exceeds maxpages.
                                                              • +
                                                              +

                                                              Activity level Driver Config

                                                              +

                                                              The activity parameters which are provided by the driver are exposed as driver.<name>. Any +configuration option that is specified this way will be applied directly to the driver through the +type-safe configuration layer. For example, specifying driver.basic.request.timeout='2 seconds' +has the same effect as setting basic.request.timeout in a driver configuration file.

                                                              +

                                                              Backwards Compatibility with cql and cqld3

                                                              +

                                                              Many driver options were provided in a more convenient form for testing in previous CQL drivers with +NoSQLBench. Due to the changes in driver 4.x, the implementation of these options had to change as +well. Where possible, a backwards-compatible option helper was provided so that test defined for +cql and cqld3 drivers would just work with the cqld4 driver. In some cases, this simply was +not possible as some options were no longer supported, or changed so much that there was no longer a +direct mapping that would work consistently across versions. You can try to use the previous +options, like pooling and so on. If the option is not supported as such, it will cause an error +with an explanation. Otherwise, these helper options will simply set the equivalent options in the +driver profile to achieve the same effect. As stated above, it is highly recommended that driver +settings be captured in a configuration file and set with driverconfig=<file>.json

                                                              +

                                                              Statement Forms

                                                              +

                                                              The CQLd4 driver supports idiomatic usage of all the main statement APIs within the native Java +driver. The syntax for specifying these types is simplified as well, using only a single +type field which allows values of simple, prepared, raw, gremlin, fluent, and so on. The previous +form of specifing type: cql and optional modifiers like prepared and +parameterized is deprecated now, sinces all the forms are explicitly supported by a well-defined +type name.

                                                              +

                                                              The previous form will work, but you will get a warning, as these should be deprecated going +forward. It is best to use the forms in the examples below. The defaults and field names for the +classic form have not changed.

                                                              +

                                                              CQLd4 Op Template Examples

                                                              +
                                                              ops:
                                                              +
                                                              +  # prepared statement
                                                              +  # allows for parameterization via bindings, and uses prepared statements internally
                                                              +  example-prepared-cql-stmt:
                                                              +    prepared: |
                                                              +     select one, two from buckle.myshoe where ...
                                                              +
                                                              +  # prepared statement (verbose form)
                                                              +  example-prepared-cql-stmt-verbose:
                                                              +    type: prepared
                                                              +    stmt: |
                                                              +      select one, two from buckle.myshoe where ...
                                                              +
                                                              +  # simple statement
                                                              +  # allows for parameterization via bindings, but does not use prepared statements internally
                                                              +  example-simple-cql-stmt:
                                                              +    simple: |
                                                              +     select three, four from knock.onthedoor where ...
                                                              +
                                                              +  # raw statement
                                                              +  # pre-renders the statement into a string, with no driver-supervised parameterization
                                                              +  # useful for testing variant DDL where some fields are not parameterizable
                                                              +  # NOTE: the raw form does its best to quote non-literals where needed, but you may
                                                              +  # have to inject single or double quotes in special cases.
                                                              +  example-raw-cql-stmt:
                                                              +    raw: |
                                                              +     create table if not exist {ksname}.{tblname} ...
                                                              +
                                                              +  # gremlin statement using the fluent API, as it would be written in a client application
                                                              +  example-fluent-graph-stmt:
                                                              +    fluent: >-
                                                              +      g.V().hasLabel("device").has("deviceid", UUID.fromString({deviceid}))
                                                              +    # if imports are not specified, the following is auto imported.
                                                              +    # if imports are specified, you must also provide the __ class if needed
                                                              +    imports:
                                                              +     - org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
                                                              +
                                                              +  # gremlin statement using string API (not recommended)
                                                              +  example-raw-gremlin-stmt:
                                                              +    gremlin: >-
                                                              +      g.V().hasLabel("device").has("deviceid", UUID.fromString('{deviceid})')
                                                              +
                                                              +

                                                              CQL Op Template - Optional Fields

                                                              +

                                                              If any of these are provided as op template fields or as op params, or as activity params, then they +will have the described effect. The calls to set these parameters on an individual statement are +only incurred if they are provided. Otherwise, defaults are used. These options can be applied to +any of the statement forms above.

                                                              +
                                                              params:
                                                              +
                                                              +  # Set the consistency level for this statement
                                                              +  # For Astra, use only LOCAL_QUORUM
                                                              +  # Otherwise, one of
                                                              +  # ALL|EACH_QUORUM|QUORUM|LOCAL_QUORUM|ONE|TWO|THREE|LOCAL_ONE|ANY
                                                              +  cl: LOCAL_QUORUM
                                                              +  # or consistency_level: ...
                                                              +
                                                              +  # Set the serial consistency level for this statement.
                                                              +  # Note, you probably don't need this unless you are using LWTs
                                                              +  # SERIAL ~ QUORUM, LOCAL_SERIAL ~ LOCAL_QUORUM
                                                              +  scl: LOCAL_SERIAL
                                                              +  # or serial_consistency_level: ...
                                                              +
                                                              +  # Set a statement as idempotent. This is important for determining
                                                              +  # when ops can be trivially retried with no concern for unexpected
                                                              +  # mutation in the event that it succeeds multiple times.
                                                              +  # true or false
                                                              +  idempotent: false
                                                              +
                                                              +  # Set the timeout for the operation, from the driver's perspective,
                                                              +  # in seconds. "2 seconds" is the default, but DDL statements, truncate or drop
                                                              +  # statements will generally need more. If you want milliseconds, just use
                                                              +  # fractional seconds, like 0.500
                                                              +  timeout: 2.0
                                                              +
                                                              +  # Set the maximum number of allowed pages for this request before a
                                                              +  # UnexpectedPagingException is thrown.
                                                              +  maxpages: 1
                                                              +
                                                              +  # Set the LWT rebinding behavior for this statement. If set to true, then
                                                              +  # any statement result which was not applied will be retried with the
                                                              +  # conditional fields set to the currently visible values. This makes all LWT
                                                              +  # statements do another round trip of retrying (assuming the data doesn't
                                                              +  # match the preconditions) in order to test LWT performance.
                                                              +  retryreplace: true
                                                              +
                                                              +  # Set the number of retries allowed by the retryreplace option. This is set
                                                              +  # to 1 conservatively, as with the maxpages setting. This means that you will
                                                              +  # see an error if the first LWT retry after an unapplied change was not successful.
                                                              +  maxlwtretries: 1
                                                              +
                                                              +  ## The following options are meant for advanced testing scenarios only,
                                                              +  ## and are not generally meant to be used in typical application-level,
                                                              +  ## data mode, performance or scale testing. These expose properties
                                                              +  ## which should not be set for general use. These allow for very specific
                                                              +  ## scenarios to be constructed for core system-level testing.
                                                              +  ## Some of them will only work with specially provided bindings which
                                                              +  ## can provide the correct instantiated object type.
                                                              +
                                                              +  # replace the payload with a map of String->ByteBuffer for this operation
                                                              +  # type: Map<String, ByteBuffer>
                                                              +  custom_payload: ...
                                                              +
                                                              +  # set an instantiated ExecutionProfile to be used for this operation
                                                              +  # type: com.datastax.oss.driver.api.core.config.DriverExecutionProfile
                                                              +  execution_profile: ...
                                                              +
                                                              +  # set a named execution profile to be used for this operation
                                                              +  # type: String
                                                              +  execution_profile_name: ...
                                                              +
                                                              +  # set a resolved target node to be used for this operation
                                                              +  # type: com.datastax.oss.driver.api.core.metadata.Node
                                                              +  node: ...
                                                              +
                                                              +  # set the timestamp to be used as the "now" reference for this operation
                                                              +  # type: int
                                                              +  now_in_seconds: ...
                                                              +
                                                              +  # set the page size for this operation
                                                              +  # type: int
                                                              +  page_size: ...
                                                              +
                                                              +  # set the query timestamp for this operation (~ USING TIMESTAMP)
                                                              +  # type: long
                                                              +  query_timestamp:
                                                              +
                                                              +  # set the routing key for this operation, as a single bytebuffer
                                                              +  # type: ByteArray
                                                              +  routing_key: ...
                                                              +
                                                              +  # set the routing key for this operation as an array of bytebuffers
                                                              +  # type: ByteArray[]
                                                              +  routing_keys: ...
                                                              +
                                                              +  # set the routing token for this operation
                                                              +  # type: com.datastax.oss.driver.api.core.metadata.token.Token
                                                              +  routing_token: ...
                                                              +
                                                              +  # enable (or disable) tracing for this operation
                                                              +  # This should be used with great care, as tracing imposed overhead
                                                              +  # far and above most point queries or writes. Use it sparsely or only
                                                              +  # for functional investigation
                                                              +  # type: boolean
                                                              +  tracing: ...
                                                              +
                                                              +

                                                              Driver Cache

                                                              +

                                                              Like all driver adapters, the CQLd4 driver has the ability to use multiple low-level driver +instances for the purposes of advanced testing. To take advantage of this, simply set a space +parameter in your op templates, with a dynamic value. +WARNING: If you use the driver cache feature, be aware that creating a large number of driver +instances will be very expensive. Generally driver instances are meant to be initialized and then +shared throughout the life-cycle of an application process. Thus, if you are doing multi-instance +driver testing, it is best to use bindings functions for the space parameter which have bounded +cardinality per host.

                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/diag/index.html b/reference/drivers/diag/index.html new file mode 100644 index 000000000..5886fb447 --- /dev/null +++ b/reference/drivers/diag/index.html @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + diag | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              diag

                                                              +

                                                              This is a diagnostic activity type. Its action simply reports the cycle number and the reporting delay between it's schedule reporting time and the current time. The reporting is interleaved between the threads, with the logical number of reports remaining constant regardless of the thread count.

                                                              +

                                                              example activitydef

                                                              +

                                                              alias=testdiag;driver=diag;threads=50;interval=2000;

                                                              +

                                                              controls

                                                              +

                                                              When the interval parameter is changed, all motor slots are notified and the reporting times are updated for each +active motor.

                                                              +

                                                              parameters

                                                              +
                                                                +
                                                              • interval - The number of milliseconds to delay between each report. +( default: 1000ms )
                                                              • +
                                                              • modulo - The cycle rate at which to generate a single output status line. +( default: modulo=10000000 )
                                                              • +
                                                              • errormodulo - The cycle rate at which to generate a non-zero status code +(1=every cycle, 10=every 10th cycle) +( default: errormodule=1000 )
                                                              • +
                                                              • phases - The number of phases to run. +( default: phases=1 )
                                                              • +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/driver-discovery/index.html b/reference/drivers/driver-discovery/index.html new file mode 100644 index 000000000..02c768a93 --- /dev/null +++ b/reference/drivers/driver-discovery/index.html @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + Built-In Adapters | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Built-In Adapters

                                                              +

                                                              NoSQLBench supports a variety of different operations. For operations like +sending a query to a database, a native driver is typically used with help of the +DriverAdapter API. For basic operations, like writing the content of a templated +message to stdout, no native driver is needed, although the mechanism of stdout +is still implemented via the same Adapter API. In effect, if you want to +allow NoSQLBench to understand your op templates in a new way, you add an Adapter +and program it to interpret op templates in a specific way.

                                                              +

                                                              Each op template of an activity can be configured to use a specific adapter. The driver=... +parameter sets the default adapter to use for all op templates in an activity. However, +this can be overridden per op template with the driver field.

                                                              +

                                                              Discovering Driver Adapters

                                                              +

                                                              NoSQLBench comes with some drivers built-in. You can discover these by running:

                                                              +
                                                              nb5 --list-drivers
                                                              +
                                                              +

                                                              Each one comes with its own built-in documentation. It can be accessed with this command:

                                                              +
                                                              nb5 help <driver>
                                                              +
                                                              +

                                                              This section contains the per-driver documentation that you get when you run the above command. +These driver docs are auto-populated when NoSQLBench is built, so they are exactly the same as +you will see with the above command, only rendered in HTML.

                                                              +

                                                              External Adapter jars

                                                              +

                                                              It is possible to load an adapter from a jar at runtime. If the environment variable NBLIBDIR +is set, it is taken as a library search path for jars, separated by a colon. For each element in the +lib paths that exists, it is added to the classpath. If the element is a named .jar file, it is +added. If it is a directory, then all jar files in that directory are added.

                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/dynamodb/index.html b/reference/drivers/dynamodb/index.html new file mode 100644 index 000000000..713dabd9d --- /dev/null +++ b/reference/drivers/dynamodb/index.html @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + dynamodb | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              dynamodb

                                                              +

                                                              The DynamoDB driver supports a basic set of commands as specified at +Amazon DynamoDB Docs.

                                                              +

                                                              Activity Parameters

                                                              +

                                                              The activity parameters for this driver are basically properties for the DynamoDB driver. +If any of these are not specified, then they are not applied to the client builder, +thus the default is whatever it is for the native client.

                                                              +
                                                                +
                                                              • region - The region which the driver should connect to. This is the +simplest way to configure the rest of the client, since defaults are +automatically looked up for the region. This is the only option that is +required.
                                                              • +
                                                              • endpoint - The endpoint for the region. Do not specify this if you have +already specified region.
                                                              • +
                                                              • signing_region - The signing region for the client. You do not have +to specify this if you specified region.
                                                              • +
                                                              • client_socket_timeout - adjust the default for the client session. (integer)
                                                              • +
                                                              • client_execution_timeout - adjust the default for the client session. (integer)
                                                              • +
                                                              • client_max_connections - adjust the default for the client session. (integer)
                                                              • +
                                                              • client_max_error_retry - adjust the default for the client session. (integer)
                                                              • +
                                                              • client_user_agent_prefix - adjust the default for the client session. (String)
                                                              • +
                                                              • client_consecutive_retries_before_throttling - adjust the default for +the client session. (integer)
                                                              • +
                                                              • client_gzip - adjust the default for the client session. (boolean)
                                                              • +
                                                              • client_tcp_keepalive - adjust the default for the client session. (boolean)
                                                              • +
                                                              • client_disable_socket_proxy - adjust the default for the client session. (boolean)
                                                              • +
                                                              • client_so_send_size_hint - adjust the default for the client session. (integer)
                                                              • +
                                                              • client_so_recv_size_hint - adjust the default for the client session. (integer)
                                                              • +
                                                              +

                                                              Op Templates

                                                              +

                                                              Specifically, the following commands are supported as of this release:

                                                              +
                                                                +
                                                              • CreateTable
                                                              • +
                                                              • GetItem
                                                              • +
                                                              • PutItem
                                                              • +
                                                              • Query
                                                              • +
                                                              • DeleteTable
                                                              • +
                                                              +

                                                              Examples

                                                              +
                                                              ops:
                                                              +
                                                              +  # the op name, used in logging and metrics
                                                              +  example-CreateTable:
                                                              +    # the type and target of the command
                                                              +    CreateTable: TEMPLATE(table,tabular)
                                                              +    # map of key structure for the table
                                                              +    Keys:
                                                              +      part: HASH
                                                              +      clust: RANGE
                                                              +    # attributes of the fields
                                                              +    Attributes:
                                                              +      part: S
                                                              +      clust: S
                                                              +    # either PROVISIONED or PAY_PER_REQUEST
                                                              +    BillingMode: PROVISIONED
                                                              +    # required for BillingMode: PROVISIONED
                                                              +    ReadCapacityUnits: "TEMPLATE(rcus,40000)"
                                                              +    # required for BillingMode: PROVISIONED
                                                              +    WriteCapacityUnits: "TEMPLATE(wcus,40000)"
                                                              +
                                                              +  example-PutItem:
                                                              +    # the type and target of the command
                                                              +    PutItem: TEMPLATE(table,tabular)
                                                              +    # A json payload
                                                              +    json: |
                                                              +      {
                                                              +       "part": "{part_layout}",
                                                              +       "clust": "{clust_layout}",
                                                              +       "data0": "{data0}"
                                                              +      }
                                                              +
                                                              +  example-GetItem:
                                                              +    # the type and target of the command
                                                              +    GetItem: TEMPLATE(table,tabular)
                                                              +    # the identifiers for the item to read
                                                              +    key:
                                                              +      part: "{part_read}"
                                                              +      clust: "{clust_read}"
                                                              +    ## optionally, set a projection
                                                              +    # projection: projection-spec
                                                              +    # optionally, override ConsistentRead defaults
                                                              +    ConsistentRead: true
                                                              +
                                                              +
                                                              +  example-Query:
                                                              +    # the type and target of the command
                                                              +    Query: TEMPLATE(table,tabular)
                                                              +    # The query key
                                                              +    key:
                                                              +      part: "{part_read}"
                                                              +      clust: "{clust_read}"
                                                              +    # optionally, override the default for ConsistentRead
                                                              +    ConsistentRead: true
                                                              +    # optionally, set a limit
                                                              +    Limit: "{limit}"
                                                              +    ## optionally, set a projection
                                                              +    # projection: projection-spec
                                                              +    ## optionally, set an exclusive start key
                                                              +    # ExclusiveStartKey: key-spec
                                                              +
                                                              +  example-DeleteTable:
                                                              +    # the type and target of the command
                                                              +    # the table identifier/name (string) to delete
                                                              +    DeleteTable: TEMPLATE(table,timeseries)
                                                              +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/http/index.html b/reference/drivers/http/index.html new file mode 100644 index 000000000..9271eac87 --- /dev/null +++ b/reference/drivers/http/index.html @@ -0,0 +1,404 @@ + + + + + + + + + + + + + + + + http | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              http

                                                              +

                                                              This driver allows you to make http requests using the native HTTP client +that is bundled with the JVM. It supports free-form construction of +requests.

                                                              +

                                                              You specify what a request looks like by providing a set of request +parameters. They can be in either literal (static) form with no dynamic +data binding, or they can each be in a string template form that draws +from data bindings. Each cycle, a request is assembled from these +parameters and executed.

                                                              +

                                                              Example Statements

                                                              +

                                                              The simplest possible statement form looks like this:

                                                              +
                                                              op: http://google.com/
                                                              +
                                                              +

                                                              Or, you can have a list:

                                                              +
                                                              # A list of statements
                                                              +ops:
                                                              + - http://google.com/
                                                              + - http://amazon.com/
                                                              +
                                                              +

                                                              Or you can template the values used in the URI, and even add ratios:

                                                              +
                                                              # A list of named statements with variable fields and specific ratios:
                                                              +ops:
                                                              +    - s1: http://google.com/search?query={query}
                                                              +      ratio: 3
                                                              +    - s2: https://www.amazon.com/s?k={query}
                                                              +      ratio: 2
                                                              +bindings:
                                                              +    query: >
                                                              +        WeightedStrings('function generator;backup generator;static generator');
                                                              +        UrlEncode();
                                                              +
                                                              +

                                                              You can even make a detailed request with custom headers and result +verification conditions:

                                                              +
                                                              # Require that the result be status code 200-299 match regex "OK, account id is .*" in the body
                                                              +ops:
                                                              +    - get-from-google:
                                                              +      method: GET
                                                              +      uri: "https://google.com/"
                                                              +      version: "HTTP/1.1"
                                                              +      Content-Type: "application/json"
                                                              +      ok-status: "2[0-9][0-9]"
                                                              +      ok-body: "^(OK, account id is .*)$"
                                                              +
                                                              +

                                                              For those familiar with what an HTTP request looks like on the wire, the +format below may be familiar. This isn't actually the content that is +submitted, but it is recognized as a valid way to express the request +parameters in a familiar and condensed form. A custom config parser makes +this form available fo rhose who want to emulate a well-known pattern:

                                                              +
                                                              ops:
                                                              +    - s1: |
                                                              +          GET https://google.com/ HTTP/1.1
                                                              +          Content-Type: application/json
                                                              +      ok-status: 2[0-9][0-9]
                                                              +      ok-body: ^(OK, account id is.*)$
                                                              +
                                                              +

                                                              Of course, in the above form, the response validators are still separate +parameters.

                                                              +

                                                              Bindings

                                                              +

                                                              All request fields can be made dynamic with binding functions. To make a +request that has all dynamic fields, you can do something like this:

                                                              +
                                                              ops:
                                                              +    - s1: |
                                                              +          {method} {scheme}://{host}:{port}/{path}?{query} {version}
                                                              +          Content-Type: {content_type}
                                                              +          Token: {mybearertoken}
                                                              +
                                                              +          {body}
                                                              +
                                                              +

                                                              The above example is in the inline request form. It is parsed and +interpreted internally as if you had configured your op template like +this:

                                                              +
                                                              ops:
                                                              +    - method: { method }
                                                              +      uri: { scheme }://{host}:{port}/{path}?{query}
                                                              +      version: { version }
                                                              +      "Content-Type": { content_type }
                                                              +      "Token": { mybearertoken }
                                                              +      body: { body }
                                                              +
                                                              +

                                                              The above two examples are semantically identical, only the format is +different. Notice that the expansion of the URI is still captured in a +field called uri, with all the dynamic pieces stitched together in the +value. You can't use arbitrary request fields. Every request field must +from (method, uri, version, body, ok-status, ok-body) or otherwise be +capitalized to signify an HTTP header.

                                                              +

                                                              The HTTP RFCs do not require headers to be capitalized, but they are +capitalized ubiquitously in practice, so we follow that convention here +for clarity. Headers are in-fact case-insensitive, so any issues created +by this indicate a non-conformant server/application implementation.

                                                              +

                                                              For URIs which are fully static (There are no dynamic fields, request +generation will be much faster, since the request is fully built and +cached at startup.

                                                              +

                                                              Request Fields

                                                              +

                                                              At a minimum, a URI must be provided. This is enough to build a +request with. All other request fields are optional and have reasonable +defaults:

                                                              +
                                                                +
                                                              • uri - This is the URI that you might put into the URL bar of your +browser. There is no default. +Example: https://en.wikipedia.org/wiki/Leonhard_Euler +If the uri contains a question mark '?' as a query delimiter, then all +embedded sections which are contained within URLENCODE[[ ... ]] +sections are preprocessed by the HTTP driver. This allows you to keep +your test data in a recognizable form. This is done at startup, so there +is no cost during the test run. As an added convenience, binding points +which are within the encoded block will be preserved, so +both https://en.wikipedia.org/URLENCODE[[wiki/]]{topic} and +https://en.wikipedia.org/URLENCODE[[wiki/{topic}]] will yield the same +configuration. For a terser form, you can use E[[...]]. You must also +ensure that the values that are inserted at binding points are produced +in a valid form for a URI. You can use the URLEncode() +binding function where needed to achieve this. +NOTE, If you are using dynamic values for the uri field, and +a test value for cycle 0 includes neither URLENCODE[[ nor E[], +then it is skipped. You can override this with enable_urlencode: true.
                                                              • +
                                                              • method - An optional request method. If not provided, "GET" is +assumed. Any method name will work here, even custom ones that are +specific to a given target system. No validation is done for standard +method names, as there is no way to know what method names may be valid.
                                                              • +
                                                              • version - The HTTP version to use. If this value is not provided, +the default version for the Java HttpClient is used. If it is provided, +it must be one of 'HTTP/1.1' or 'HTTP/2.0'.
                                                              • +
                                                              • body - The content of the request body, for methods which support +it.
                                                              • +
                                                              • ok-status - An optional set of rules to verify that a response is +valid. This is a simple comma or space separated list of integer status +codes or a pattern which is used as a regex against the string form of a +status code. If any characters other than digits spaces and commas are +found in this value, then it is taken as a regex. If this is not +provided, then any status code which is >=200 and <300 is considered +valid.
                                                              • +
                                                              • ok-body - An optional regex pattern which will be applied to the +body to verify that it is a valid response. If this is not provided, +then content bodies are read, but any content is considered valid.
                                                              • +
                                                              +

                                                              Any other statement parameter which is capitalized is taken as a request +header. If additional fields are provided which are not included in the +above list, or which are not capitalized, then an error is thrown.

                                                              +

                                                              Error Handling & Retries

                                                              +

                                                              By default, a request which encounters an exception is retried up to 10 +times. If you want to change this, set another value to the +retries= activity parameters.

                                                              +

                                                              Presently, no determination is made about whether an errored +response should be retryable, but it is possible to configure this if +you have a specific exception type that indicates a retryable operation.

                                                              +

                                                              The HTTP driver is the first NB driver to include a completely +configurable error handler chain. This is explained in the +error-handlers topic. By default, the HTTP activity's error handler is +wired to stop the activity for any error encountered.

                                                              +

                                                              SSL Support

                                                              +

                                                              SSL should work for any basic client request that doesn't need custom SSL +configuration. If needed, more configurable SSL support will be added.

                                                              +

                                                              Client Behavior

                                                              +

                                                              TCP Sessions & Clients

                                                              +

                                                              Client instances are created for each unique space value. NoSQLBench +provides a way for all driver adapters to instance native clients according +to a data from a binding. This is standardized under the op template parameter +space, which is wired by default to the static value default. This means +that each activity that uses the http driver shares a client instance across +all threads by default. If you want to have a new http client per-thread, +simply add a binding for space: ThreadNumToInteger() and reference it in +an op template like space: {space}, OR use an inline op field in your op +template like space: {(ThreadNumToInteger())}.

                                                              +

                                                              You can use any binding function you want for the space op field. However, +if you were to assign it something like "space: {(Identity()}" you would +not have a good result, as you would be spinning up and caching a new http client +instance for every single cycle.

                                                              +

                                                              Chunked encoding and web sockets

                                                              +

                                                              Presently, this driver only does basic request-response style requests. +Thus, adding headers which take TCP socket control away from the +HttpClient will likely yield inconsistent (or undefined) +results. Support may be added for long-lived connections in a future +release. However, chunked encoding responses are supported, although they +will be received fully before being processed further. Connecting to a long-lived +connection that streams chunked encoding responses indefinitely will have +undefined results.

                                                              +

                                                              HTTP Activity Parameters

                                                              +
                                                                +
                                                              • +

                                                                follow_redirects - default: normal - One of never, always, or +normal. Normal redirects are those which do not redirect from HTTPS to +HTTP.

                                                                +
                                                              • +
                                                              • +

                                                                diagnostics - default: none - synonym: diag +example: diag=brief,1000 - print diagnostics for every 1000th cycle, +including only brief details as explained below.

                                                                +

                                                                This setting is a selector for what level of verbosity you will get on +the console. If you set this to diag=all, you'll get every request and +response logged to console. This is only for verifying that a test is +configured and to spot check services before running higher scale tests.

                                                                +

                                                                All the data shown in diagnostics is post-hoc, directly from the +response provided by the internal HTTP client in the Java runtime.

                                                                +

                                                                If you want finer control over how much information diagnostics +provides, you can specify a comma separated list of the below.

                                                                +
                                                                  +
                                                                • headers - show headers
                                                                • +
                                                                • stats - show basic stats of each request
                                                                • +
                                                                • data - show all of each response body this setting
                                                                • +
                                                                • data10 - show only the first 10 characters of each response body +this setting supersedes data
                                                                • +
                                                                • data100 - show only the first 100 characters of each response body +this setting supersedes data10
                                                                • +
                                                                • data1000 - show only the first 1000 characters of each response body +this setting supersedes data100
                                                                • +
                                                                • redirects - show details for interstitial request which are made +when the client follows a redirect directive like a location +header
                                                                • +
                                                                • requests - show details for requests
                                                                • +
                                                                • responses - show details for responses
                                                                • +
                                                                • codes - shows explanatory details (high-level) of http response status codes
                                                                • +
                                                                • brief - Show headers, stats, requests, responses, and 10 characters
                                                                • +
                                                                • all - Show everything, including full payloads and redirects
                                                                • +
                                                                • a modulo - any number, like 3000 - causes the diagnostics to be +reported only on this cycle modulo. If you set diag=300,brief +then you will get the brief diagnostic output for every 300th +response.
                                                                • +
                                                                +

                                                                The requests, responses, and redirects settings work in combination. +For example, if you specify responses, and redirect, but not requests, +then you will only see the response portion of all calls made by the +client. All available filters layer together in this way.

                                                                +
                                                              • +
                                                              • +

                                                                timeout - default: forever - Sets the timeout of each request in +milliseconds.

                                                                +
                                                              • +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/index.html b/reference/drivers/index.html new file mode 100644 index 000000000..2413f1a29 --- /dev/null +++ b/reference/drivers/index.html @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + diag | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              diag

                                                              +

                                                              This is a diagnostic activity type. Its action simply reports the cycle number and the reporting delay between it's schedule reporting time and the current time. The reporting is interleaved between the threads, with the logical number of reports remaining constant regardless of the thread count.

                                                              +

                                                              example activitydef

                                                              +

                                                              alias=testdiag;driver=diag;threads=50;interval=2000;

                                                              +

                                                              controls

                                                              +

                                                              When the interval parameter is changed, all motor slots are notified and the reporting times are updated for each +active motor.

                                                              +

                                                              parameters

                                                              +
                                                                +
                                                              • interval - The number of milliseconds to delay between each report. +( default: 1000ms )
                                                              • +
                                                              • modulo - The cycle rate at which to generate a single output status line. +( default: modulo=10000000 )
                                                              • +
                                                              • errormodulo - The cycle rate at which to generate a non-zero status code +(1=every cycle, 10=every 10th cycle) +( default: errormodule=1000 )
                                                              • +
                                                              • phases - The number of phases to run. +( default: phases=1 )
                                                              • +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/jdbc/index.html b/reference/drivers/jdbc/index.html new file mode 100644 index 000000000..ace3a5962 --- /dev/null +++ b/reference/drivers/jdbc/index.html @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + JDBC driver | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              JDBC driver

                                                              +

                                                              This JDBC driver leverages Hikari Connection Pool for connection pool and works with PostgreSQL®. This leverages NoSQLBench based workload generation and performance testing against any PostgreSQL-compatible database cluster. Example: CockroachDB® or YugabyteDB® (YSQL API).

                                                              +

                                                              Executing JDBC Workload

                                                              +

                                                              The following is an example of invoking a JDBC workload.

                                                              +
                                                              <nb_cmd> run driver=jdbc workload="/path/to/workload.yaml" cycles=1000 threads=100 url="jdbc:postgresql://" serverName=localhost portNumber=5432 databaseName=defaultdb ... -vv --show-stacktraces
                                                              +
                                                              +

                                                              In the above NB command, following are JDBC driver specific parameters:

                                                              +
                                                                +
                                                              • url: URL of the database cluster. Default is jdbc:postgresql://.
                                                              • +
                                                              • serverName: Default is localhost.
                                                              • +
                                                              • portNumber: Default is 5432.
                                                              • +
                                                              • serverName: The database name. The default is to connect to a database with the same name as the user name used to connect to the server.
                                                              • +
                                                              +

                                                              Other NB engine parameters are straight forward:

                                                              +
                                                                +
                                                              • driver: must be jdbc.
                                                              • +
                                                              • threads: depending on the workload type, the NB thread number determines how many clients will be created. All the clients will share the Connection originated from the Hikari Connection Pool.
                                                              • +
                                                              • *.yaml: the NB jdbc scenario definition workload yaml file.
                                                              • +
                                                              • <nb_cmd>: is ./nb (using binary) or the java -jar nb5.jar.
                                                              • +
                                                              +

                                                              Configuration

                                                              +

                                                              These are the main configurations with which we could issue a query and process the results back based on the PostgreSQL® Query pattern.

                                                              +

                                                              Config Sources

                                                              +
                                                                +
                                                              • execute: This is to issue any DDL statements such CREATE DATABASE|TABLE or DROP DATABASE|TABLE operations which returns nothing.
                                                              • +
                                                              • query: This is to issue DML statement such as SELECT operation which would return a ResultSet object to process.
                                                              • +
                                                              • update: This is to issue DML statements such as INSERT|UPDATE|DELETE operations that will return how many number of rows were affected by that operation.
                                                              • +
                                                              +

                                                              Statement Forms

                                                              +

                                                              The syntax for specifying these types is simplified as well, using only a single type field which allows values of execute, query, & update +and specifying the raw statements in the stmt. Alternatively, one could directly use one of the types and provide the raw query directly.

                                                              +

                                                              Examples

                                                              +

                                                              Check out the default activities under the activities.baselinesv2 directory.

                                                              +

                                                              Op Template Examples

                                                              +
                                                              ops:
                                                              +  drop-database:
                                                              +    type: execute
                                                              +    stmt: |
                                                              +      DROP DATABASE IF EXISTS TEMPLATE(database,baselines);
                                                              +  create-table:
                                                              +    execute: |
                                                              +      CREATE TABLE IF NOT EXISTS TEMPLATE(database,baselines).TEMPLATE(table,keyvalue);
                                                              +  select-table:
                                                              +    query: |
                                                              +      SELECT one, two, three FROM TEMPLATE(database,baselines).TEMPLATE(table,keyvalue) WHERE ...;
                                                              +  insert-table:
                                                              +    update: |
                                                              +      UPDATE TABLE TEMPLATE(database,baselines).TEMPLATE(table,keyvalue) SET key = 'value' WHERE ...;
                                                              +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/mongodb/index.html b/reference/drivers/mongodb/index.html new file mode 100644 index 000000000..dc6a8601b --- /dev/null +++ b/reference/drivers/mongodb/index.html @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + MongoDB | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              MongoDB

                                                              +

                                                              This is a driver for MongoDB. It supports the db.runCommand API described in here.

                                                              +

                                                              Consult +MongoDB commands +for details on command structure.

                                                              +

                                                              Example activity definitions

                                                              +

                                                              Run a mongodb activity with definitions from activities/mongodb-basic.yaml

                                                              +
                                                              nb5 driver=mongodb yaml=activities/mongo-basic.yaml
                                                              +
                                                              +

                                                              MongoDB ActivityType Parameters

                                                              +
                                                                +
                                                              • +

                                                                connection (Mandatory) - connection string of the target MongoDB.

                                                                +

                                                                Example: mongodb://127.0.0.1

                                                                +
                                                              • +
                                                              • +

                                                                database (Mandatory) - target database

                                                                +

                                                                Example: testdb

                                                                +
                                                              • +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/pulsar/index.html b/reference/drivers/pulsar/index.html new file mode 100644 index 000000000..9ffb20b61 --- /dev/null +++ b/reference/drivers/pulsar/index.html @@ -0,0 +1,466 @@ + + + + + + + + + + + + + + + + pulsar | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              pulsar

                                                              +

                                                              1. Overview

                                                              +

                                                              This driver allows you to simulate and run different types of workloads (as below) against a Pulsar cluster through NoSQLBench (NB).

                                                              +
                                                                +
                                                              • Admin API - create/delete tenants
                                                              • +
                                                              • Admin API - create/delete namespaces
                                                              • +
                                                              • Admin API - create/delete topics +
                                                                  +
                                                                • Topics can be partitioned or non-partitioned
                                                                • +
                                                                +
                                                              • +
                                                              • Producer - publish messages with schema support +
                                                                  +
                                                                • Default schema type is byte[]
                                                                • +
                                                                • Avro schema and KeyValue schema are also supported
                                                                • +
                                                                +
                                                              • +
                                                              • Consumer - consume messages with schema support and the following support +
                                                                  +
                                                                • Different subscription types
                                                                • +
                                                                • Multi-topic subscription (including Topic patterns)
                                                                • +
                                                                • Subscription initial position
                                                                • +
                                                                • Dead letter topic policy
                                                                • +
                                                                • Negative acknowledgement and acknowledgement timeout redelivery backoff policy
                                                                • +
                                                                +
                                                              • +
                                                              +

                                                              1.1. Issues Tracker

                                                              +

                                                              If you have issues or new requirements for this driver, please add them at the pulsar issues tracker.

                                                              +

                                                              2. Execute the NB Pulsar Driver Workload

                                                              +

                                                              In order to run a NB Pulsar driver workload, it follows similar command as other NB driver types. But it does have its unique execution parameters. The general command has the following format:

                                                              +
                                                              <nb_cmd> run driver=pulsar threads=<thread_num> cycles=<cycle_count> web_url=<pulsar_web_svc_url> service_url=<pulsar_svc_url> config=<pulsar_client_config_property_file> yaml=<nb_scenario_yaml_file> [<other_common_NB_execution_parameters>]
                                                              +
                                                              +

                                                              In the above command, make sure the driver type is pulsar and provide the following Pulsar driver specific parameters:

                                                              +
                                                                +
                                                              • web_url: Pulsar web service url and default to "http://localhost:8080"
                                                              • +
                                                              • service_url: Pulsar native protocol service url and default to "pulsar://localhost:6650"
                                                              • +
                                                              • config: Pulsar schema/client/producer/consumer related configuration (as a property file)
                                                              • +
                                                              +

                                                              2.1. NB Pulsar Driver Yaml File High Level Structure

                                                              +

                                                              Just like other NB driver types, the actual NB Pulsar workload is defined in a YAML file with the following high level structure:

                                                              +
                                                              description: |
                                                              +  ...
                                                              +
                                                              +bindings:
                                                              +  ...
                                                              +
                                                              +params:
                                                              +  ...
                                                              +
                                                              +blocks:
                                                              +  <block_1>:
                                                              +    ops:
                                                              +      op1:
                                                              +        <OpTypeIdentifier>: "<static_or_dynamic_value>"
                                                              +        <op_param_1>: "<some_value>"
                                                              +        <op_param_2>: "<some_value>"
                                                              +        ...
                                                              +
                                                              +  <block_2>:
                                                              +  ...
                                                              +
                                                              +
                                                                +
                                                              • description: This is an (optional) section where to provide general description of the Pulsar NB workload defined in this file.
                                                              • +
                                                              • bindings: This section defines all NB bindings that are required in all OpTemplate blocks
                                                              • +
                                                              • params: This section defines Document level configuration parameters that apply to all OpTemplate blocks.
                                                              • +
                                                              • blocks: This section defines the OpTemplate blocks that are needed to execute Pulsar specific workloads. Each OpTemplate block may contain multiple OpTemplates.
                                                              • +
                                                              +

                                                              2.2. NB Pulsar Driver Configuration Parameters

                                                              +

                                                              The NB Pulsar driver configuration parameters can be set at 3 different levels:

                                                              +
                                                                +
                                                              • Global level
                                                              • +
                                                              • Document level +
                                                                  +
                                                                • The parameters at this level are those within a NB yaml file that impact all OpTemplates
                                                                • +
                                                                +
                                                              • +
                                                              • Op level (or Cycle level) +
                                                                  +
                                                                • The parameters at this level are those within a NB yaml file that are associated with each individual OpTemplate
                                                                • +
                                                                +
                                                              • +
                                                              +

                                                              Please NOTE that when a parameter is specified at multiple levels, the one at the lowest level takes precedence.

                                                              +

                                                              2.2.1. Global Level Parameters

                                                              +

                                                              The parameters at this level are those listed in the command line config properties file.

                                                              +

                                                              The NB Pulsar driver relies on Pulsar's Java Client API complete its workloads such as creating/deleting tenants/namespaces/topics, generating messages, creating producers to send messages, and creating consumers to receive messages. The Pulsar client API has different configuration parameters to control the execution behavior. For example, this document lists all possible configuration parameters for how a Pulsar producer can be created.

                                                              +

                                                              All these Pulsar "native" parameters are supported by the NB Pulsar driver, via the global configuration properties file (e.g. config.properties). An example of the structure of this file looks like below:

                                                              +
                                                              ### Schema related configurations - MUST start with prefix "schema."
                                                              +#schema.key.type=avro
                                                              +#schema.key.definition=</path/to/avro-key-example.avsc>
                                                              +schema.type=avro
                                                              +schema.definition=</path/to/avro-value-example.avsc>
                                                              +
                                                              +### Pulsar client related configurations - MUST start with prefix "client."
                                                              +# http://pulsar.apache.org/docs/en/client-libraries-java/#client
                                                              +client.connectionTimeoutMs=5000
                                                              +client.authPluginClassName=org.apache.pulsar.client.impl.auth.AuthenticationToken
                                                              +client.authParams=
                                                              +# ...
                                                              +
                                                              +### Producer related configurations (global) - MUST start with prefix "producer."
                                                              +# http://pulsar.apache.org/docs/en/client-libraries-java/#configure-producer
                                                              +producer.sendTimeoutMs=
                                                              +producer.blockIfQueueFull=true
                                                              +# ...
                                                              +
                                                              +### Consumer related configurations (global) - MUST start with prefix "consumer."
                                                              +# http://pulsar.apache.org/docs/en/client-libraries-java/#configure-consumer
                                                              +consumer.subscriptionInitialPosition=Earliest
                                                              +consumer.deadLetterPolicy={"maxRedeliverCount":"5","retryLetterTopic":"public/default/retry","deadLetterTopic":"public/default/dlq","initialSubscriptionName":"dlq-sub"}
                                                              +consumer.ackTimeoutRedeliveryBackoff={"minDelayMs":"10","maxDelayMs":"20","multiplier":"1.2"}
                                                              +# ...
                                                              +
                                                              +

                                                              There are multiple sections in this file that correspond to different +categories of the configuration parameters:

                                                              +
                                                                +
                                                              • Pulsar Schema related settings: +
                                                                  +
                                                                • All settings under this section starts with schema. prefix.
                                                                • +
                                                                • At the moment, there are 3 schema types supported +
                                                                    +
                                                                  • Default raw byte[]
                                                                  • +
                                                                  • Avro schema for the message payload
                                                                  • +
                                                                  • KeyValue based Avro schema for both message key and message payload
                                                                  • +
                                                                  +
                                                                • +
                                                                +
                                                              • +
                                                              • Pulsar Client related settings: +
                                                                  +
                                                                • All settings under this section starts with client. prefix.
                                                                • +
                                                                • This section defines all configuration parameters that are related with defining a PulsarClient object. + +
                                                                • +
                                                                +
                                                              • +
                                                              • Pulsar Producer related settings: +
                                                                  +
                                                                • All settings under this section starts with producer prefix.
                                                                • +
                                                                • This section defines all configuration parameters that are related with defining a Pulsar Producer object. + +
                                                                • +
                                                                +
                                                              • +
                                                              • Pulsar Consumer related settings: +
                                                                  +
                                                                • All settings under this section starts with consumer prefix.
                                                                • +
                                                                • This section defines all configuration parameters that are related with defining a Pulsar Consumer object. + +
                                                                • +
                                                                +
                                                              • +
                                                              +

                                                              2.2.2. Document Level Parameters

                                                              +

                                                              For the Pulsar NB driver, Document level parameters can only be statically bound; and currently, the following Document level configuration parameters are supported:

                                                              +
                                                                +
                                                              • async_api (boolean): +
                                                                  +
                                                                • When true, use async Pulsar client API.
                                                                • +
                                                                +
                                                              • +
                                                              • use_transaction (boolean): +
                                                                  +
                                                                • When true, use Pulsar transaction.
                                                                • +
                                                                +
                                                              • +
                                                              • admin_delop (boolean): +
                                                                  +
                                                                • When true, delete Tenants/Namespaces/Topics. Otherwise, create them.
                                                                • +
                                                                • Only applicable to administration related operations
                                                                • +
                                                                +
                                                              • +
                                                              • seq_tracking (boolean): +
                                                                  +
                                                                • When true, a sequence number is created as part of each message's properties
                                                                • +
                                                                • This parameter is used in conjunction with the next one in order to simulate abnormal message processing errors and then be able to detect such errors successfully.
                                                                • +
                                                                +
                                                              • +
                                                              • seqerr_simu: +
                                                                  +
                                                                • A list of error simulation types separated by comma (,)
                                                                • +
                                                                • Valid error simulation types +
                                                                    +
                                                                  • out_of_order: simulate message out of sequence
                                                                  • +
                                                                  • msg_loss: simulate message loss
                                                                  • +
                                                                  • msg_dup: simulate message duplication
                                                                  • +
                                                                  +
                                                                • +
                                                                +
                                                              • +
                                                              • e2e_starting_time_source: +
                                                                  +
                                                                • Starting timestamp for end-to-end operation. When specified, will update the e2e_msg_latency histogram with the calculated end-to-end latency. The latency is calculated by subtracting the starting time from the current time. The starting time is determined from a configured starting time source. The unit of the starting time is milliseconds since epoch.
                                                                • +
                                                                • The possible values for e2e_starting_time_source: +
                                                                    +
                                                                  • message_publish_time : uses the message publishing timestamp as the starting time
                                                                  • +
                                                                  • message_event_time : uses the message event timestamp as the starting time
                                                                  • +
                                                                  • message_property_e2e_starting_time : uses a message property e2e_starting_time as the starting time.
                                                                  • +
                                                                  +
                                                                • +
                                                                +
                                                              • +
                                                              +

                                                              3. NB Pulsar Driver OpTemplates

                                                              +

                                                              For the NB Pulsar driver, each OpTemplate has the following format:

                                                              +
                                                              blocks:
                                                              +  <some_block_name>:
                                                              +    ops:
                                                              +      <some_op_name>:
                                                              +        <OpTypeIdentifier>: <tenant|namespace|topic_name>
                                                              +        <op_param_1>: "<some_value>"
                                                              +        <op_param_2>: "<some_value>"
                                                              +        ...
                                                              +
                                                              +

                                                              The OpTypeIdentifier determines which NB Pulsar workload type (OpType) to run, and it has the following value:

                                                              +
                                                              public enum PulsarOpType {
                                                              +    AdminTenant,
                                                              +    AdminNamespace,
                                                              +    AdminTopic,
                                                              +    MessageProduce,
                                                              +    MessageConsume
                                                              +}
                                                              +
                                                              +

                                                              Its value is mandatory and depending on the actual identifier, its value can be one of the following:

                                                              +
                                                                +
                                                              • Tenant name: for AdminTenant type
                                                              • +
                                                              • Namespace name: for AdminNamespace type and in format "/"
                                                              • +
                                                              • Topic name: for the rest of the types and in format [(persistent|non-persistent)://]// +is mandatory for each NB Pulsar operation type
                                                              • +
                                                              +

                                                              Each Pulsar OpType may have optional Op specific parameters. Please refer to here for the example NB Pulsar YAML files for each OpType

                                                              +

                                                              4. Message Generation and Schema Support

                                                              +

                                                              4.1. Message Generation

                                                              +

                                                              A Pulsar message has three main components: message key, message properties, and message payload. Among them, message payload is mandatory when creating a message.

                                                              +

                                                              When running the "message producing" workload, the NB Pulsar driver is able to generate a message with its full content via the following OpTemplate level parameters:

                                                              +
                                                                +
                                                              • msg_key: defines message key value
                                                              • +
                                                              • msg_property: defines message property values
                                                              • +
                                                              • msg_value: defines message payload value
                                                              • +
                                                              +

                                                              The actual values of them can be static or dynamic (which are determined by NB data binding rules)

                                                              +

                                                              For msg_key, its value can be either

                                                              +
                                                                +
                                                              • a plain text string, or
                                                              • +
                                                              • a JSON string that follows the specified "key" Avro schema (when KeyValue schema is used)
                                                              • +
                                                              +

                                                              For msg_property, its value needs to be a JSON string that contains a list of key-value pairs. An example is as below. Please NOTE that if the provided value is not a valid JSON string, the NB Pulsar driver will ignore it and treat the message as having no properties.

                                                              +
                                                                msg_property: |
                                                              +    {
                                                              +      "prop1": "{myprop1}",
                                                              +      "prop2": "{myprop2}"
                                                              +    }
                                                              +
                                                              +

                                                              For msg_value, its value can be either

                                                              +
                                                                +
                                                              • a plain simple text, or
                                                              • +
                                                              • a JSON string that follows the specified "value" Avro schema (when Avro schema or KeyValue schema is used)
                                                              • +
                                                              +

                                                              4.2. Schema Support

                                                              +

                                                              The NB Pulsar driver supports the following Pulsar schema types:

                                                              +
                                                                +
                                                              • Primitive schema types
                                                              • +
                                                              • Avro schema type (only for message payload - msg_value)
                                                              • +
                                                              • KeyValue schema type (with both key and value follows an Avro schema)
                                                              • +
                                                              +

                                                              The following 2 global configuration parameters define the required schema type

                                                              +
                                                                +
                                                              • schema.key.type: defines message key type
                                                              • +
                                                              • schema.type: defines message value type +For them, if the parameter value is not specified, it means using the default byte[]/BYTES type as the schema type. Otherwise, if it is specified as "avro", it means using Avro as the schema type.
                                                              • +
                                                              +

                                                              The following 2 global configuration parameters define the schema specification (ONLY needed when Avro is the schema type)

                                                              +
                                                                +
                                                              • schema.key.definition: a file path that defines the message key Avro schema specification
                                                              • +
                                                              • schema.definition: a file path the message value Avro schema specification +The NB Pulsar driver will throw an error if the schema type is Avro but no schema specification definition file is not provided or is not valid.
                                                              • +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/s4j/index.html b/reference/drivers/s4j/index.html new file mode 100644 index 000000000..2d1559afc --- /dev/null +++ b/reference/drivers/s4j/index.html @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + + + S4J | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              1. Overview

                                                              +

                                                              This driver is similar to NB Pulsar driver that allows NB based workload generation and performance testing against a Pulsar cluster. It also follows a similar pattern to configure and connect to the Pulsar cluster for workload execution.

                                                              +

                                                              However, the major difference is instead of simulating native Pulsar client workloads, the NB S4J driver allows simulating JMS oriented workloads (that follows JMS spec 2.0 and 1.1) to be executed on the Pulsar cluster. Under the hood, this is achieved through DataStax's [Starlight for JMS API] (https://github.com/datastax/pulsar-jms).

                                                              +

                                                              2. Execute NB S4J Workload

                                                              +

                                                              The following is an example of executing a NB S4J workload (defined as pulsar_s4j.yaml)

                                                              +
                                                              $ <nb_cmd> run driver=s4j cycles=10000 threads=4 num_conn=2 num_session=2 session_mode="client_ack" strict_msg_error_handling="false" web_url=http://localhost:8080 service_url=pulsar://localhost:6650 config=/path/to/nb_s4j_config.properties yaml=/path/to/pulsar_s4j.yaml -vv --logs-dir=s4j_log
                                                              +
                                                              +

                                                              In the above NB CLI command, the S4J driver specific parameters are listed as below:

                                                              +
                                                                +
                                                              • num_conn: the number of JMS connections to be created
                                                              • +
                                                              • num_session: the number of JMS sessions per JMS connection +
                                                                  +
                                                                • Note that multiple JMS sessions can be created from one JMS connection, and they share the same connection characteristics.
                                                                • +
                                                                +
                                                              • +
                                                              • session_mode: the session mode used when creating a JMS session
                                                              • +
                                                              • web_url: the URL of the Pulsar web service
                                                              • +
                                                              • service_url: the URL of the Pulsar native protocol service
                                                              • +
                                                              • (optional) strict_msg_error_handling: whether to do strict error handling +
                                                                  +
                                                                • when true, Pulsar client error will not stop NB S4J execution
                                                                • +
                                                                • otherwise, any Pulsar client error will stop NB S4J execution
                                                                • +
                                                                +
                                                              • +
                                                              • (optional) max_s4jop_time: maximum time (in seconds) to execute the actual S4J operations (e.g. message sending or receiving). If NB execution time is beyond this limit, each NB cycle is just a no-op. Please NOTE: +
                                                                  +
                                                                • this is useful when controlled NB execution is needed with NB CLI scripting.
                                                                • +
                                                                • if this parameter is not specified or the value is 0, it means no time limitation. Every single NB cycle will trigger an actual S4J operation.
                                                                • +
                                                                +
                                                              • +
                                                              • (optional) track_msg_cnt: When set to true (with default as false), the S4J driver will keep track of the confirmed response count for message sending and receiving.
                                                              • +
                                                              +

                                                              Other NB engine parameters are straight forward:

                                                              +
                                                                +
                                                              • driver: must be s4j
                                                              • +
                                                              • threads: depending on the workload type, the NB thread number determines how many producers or consumers will be created. All producers or consumers will share the available JMS connections and sessions
                                                              • +
                                                              • yamL: the NB S4J scenario definition yaml file
                                                              • +
                                                              • config: specify the file that contains the connection parameters used by the S4J API
                                                              • +
                                                              +

                                                              3. NB S4J Driver Configuration Parameter File

                                                              +

                                                              The S4J API has a list of configuration options that can be found here: https://docs.datastax.com/en/fast-pulsar-jms/docs/1.1/pulsar-jms-reference.html#_configuration_options.

                                                              +

                                                              The NB S4J driver supports these configuration options via a config property file, an example of which is listed below. The configuration parameters in this file are grouped into several groups. The comments below explain how the grouping works.

                                                              +
                                                              ###########
                                                              +# Overview: Starlight for JMS (S4J) API configuration items are listed at:
                                                              +#           https://docs.datastax.com/en/fast-pulsar-jms/docs/1.1/pulsar-jms-reference.html#_configuration_options
                                                              +enableTransaction=true
                                                              +
                                                              +####
                                                              +# S4J API specific configurations (non Pulsar specific) - jms.***
                                                              +
                                                              +jms.enableClientSideEmulation=true
                                                              +jms.usePulsarAdmin=false
                                                              +#...
                                                              +
                                                              +#####
                                                              +# Pulsar client related configurations - client.***
                                                              +# - Valid settings: http://pulsar.apache.org/docs/en/client-libraries-java/#client
                                                              +#
                                                              +# - These Pulsar client settings (without the "client." prefix) will be
                                                              +#   directly used as S4J configuration settings, on a 1-to-1 basis.
                                                              +#--------------------------------------
                                                              +# only relevant when authentication is enabled
                                                              +client.authPlugin=org.apache.pulsar.client.impl.auth.AuthenticationToken
                                                              +client.authParams=file:///path/to/authentication/jwt/file
                                                              +# only relevant when in-transit encryption is enabled
                                                              +client.tlsTrustCertsFilePath=/path/to/certificate/file
                                                              +#...
                                                              +
                                                              +#####
                                                              +# Producer related configurations (global) - producer.***
                                                              +# - Valid settings: http://pulsar.apache.org/docs/en/client-libraries-java/#configure-producer
                                                              +#
                                                              +# - These Pulsar producer settings (without "producer." prefix) will be collectively (as a map)
                                                              +#   mapped to S4J connection setting of "producerConfig"
                                                              +#--------------------------------------
                                                              +producer.blockIfQueueFull=true
                                                              +# disable producer batching
                                                              +#producer.batchingEnabled=false
                                                              +#...
                                                              +
                                                              +#####
                                                              +# Consumer related configurations (global) - consumer.***
                                                              +# - Valid settings: http://pulsar.apache.org/docs/en/client-libraries-java/#configure-consumer
                                                              +#
                                                              +# - These Pulsar producer settings (without "consumer." portion) will be collectively (as a map)
                                                              +#   mapped to S4J connection setting of "consumerConfig"
                                                              +#--------------------------------------
                                                              +#...
                                                              +
                                                              +

                                                              4. NB S4J Scenario Definition File

                                                              +

                                                              Like any NB scenario yaml file, the NB S4J yaml file is composed of 3 major components:

                                                              +
                                                                +
                                                              • bindings: define NB bindings
                                                              • +
                                                              • params: define document level parameters
                                                              • +
                                                              • blocks: define various statement blocks. Each statement block represents one JMS workload type
                                                              • +
                                                              +
                                                              bindings:
                                                              + ... ...
                                                              +params:
                                                              + ... ...
                                                              +blocks:
                                                              + ... ...
                                                              +
                                                              +

                                                              4.1. Document Level Parameters

                                                              +

                                                              The parameters defined in this section will be applicable to all statement blocks. An example of some common parameters that can be set at the document level is listed below:

                                                              +
                                                                +
                                                              • temporary_dest: whether JMS workload is dealing with a temporary destination
                                                              • +
                                                              • dest_type: JMS destination type - queue or topic
                                                              • +
                                                              +
                                                              params:
                                                              + temporary_dest: "false"
                                                              + dest_type: "<jms_destination_type>"
                                                              + async_api: "true"
                                                              + txn_batch_num: <number_of_message_ops_in_one_transaction>
                                                              + blocking_msg_recv: <whehter_to_block_when_receiving_messages>
                                                              + shared_topic: <if_shared_topic_or_not>  // only relevant when the destination type is a topic
                                                              + durable_topic: <if_durable_topic_or_not>  // only relevant when the destination type is a topic
                                                              +
                                                              +

                                                              Please NOTE that the above parameters won't necessarily be specified at the document level. If they're specified at the statement level, they will only impact the statement within which they're specified.

                                                              +

                                                              4.2. NB S4J Workload Types

                                                              +

                                                              The NB S4J driver supports 2 types of JMS operations:

                                                              +
                                                                +
                                                              • One for message producing/sending/publishing +
                                                                  +
                                                                • this is identified by NB Op identifier MessageProduce
                                                                • +
                                                                +
                                                              • +
                                                              • One for message consuming/receiving/subscribing +
                                                                  +
                                                                • this is identified by NB Op identifier MessageConsume
                                                                • +
                                                                +
                                                              • +
                                                              +

                                                              4.2.1. Publish Messages to a JMS Destination, Queue or Topic

                                                              +

                                                              The NB S4J statement block for publishing messages to a JMS destination (either a Queue or a topic) has the following format.

                                                              +
                                                                +
                                                              • Optionally, you can specify the JMS headers (msg_header) and properties (msg_property) via valid JSON strings in key: value format.
                                                              • +
                                                              • The default message type (msg_type) is "byte". But optionally, you can specify other message types such as "text", "map", etc.
                                                              • +
                                                              • The message payload (msg_body) is the only mandatory field.
                                                              • +
                                                              +
                                                              blocks:
                                                              +  msg-produce-block:
                                                              +    ops:
                                                              +      op1:
                                                              +        ## The value represents the destination (queue or topic) name)
                                                              +        MessageProduce: "mys4jtest_t"
                                                              +
                                                              +        ## (Optional) JMS headers (in JSON format).
                                                              +        msg_header: |
                                                              +          {
                                                              +            "<header_key>": "<header_value>"
                                                              +          }
                                                              +
                                                              +        ## (Optional) JMS properties, predefined or customized (in JSON format).
                                                              +        msg_property: |
                                                              +          {
                                                              +            "<property1_key>": "<property_value1>",
                                                              +            "<property2_key>": "<property_value2>"
                                                              +          }
                                                              +
                                                              +        ## (Optional) JMS message types, default to be BYTES.
                                                              +        msg_type: "text"
                                                              +
                                                              +        ## (Mandatory) JMS message body. Value depends on msg_type.
                                                              +        msg_body: "{mytext_val}"
                                                              +
                                                              +

                                                              4.2.2. Receiving Messages from a JMS Destination, Queue or Topic

                                                              +

                                                              The generic NB S4J statement block for receiving messages to a JMS destination (either a Queue or a topic) has the following format. All the statement specific parameters are listed as below.

                                                              +
                                                                +
                                                              • msg_selector: Message selector string
                                                              • +
                                                              • no_local: Only applicable to a Topic as the destination. This allows a subscriber to inhibit the delivery of messages published by its own connection.
                                                              • +
                                                              • read_timeout: The timeout value for receiving a message from a destination +
                                                                  +
                                                                • This setting only works if no_wait is false
                                                                • +
                                                                • If the read_timeout value is 0, it behaves the same as no_wait is true
                                                                • +
                                                                +
                                                              • +
                                                              • no_wait: Whether to receive the next message immediately if one is available
                                                              • +
                                                              • msg_ack_ratio: the ratio of the received messages being acknowledged
                                                              • +
                                                              • slow_ack_in_sec: whether to simulate a slow consumer (pause before acknowledging after receiving a message) +
                                                                  +
                                                                • value 0 means no simulation (consumer acknowledges right away)
                                                                • +
                                                                +
                                                              • +
                                                              • negative ack/ack timeout/deadletter topic related settings +
                                                                  +
                                                                • The settings here (as the scenario specific settings) will be merged with the
                                                                • +
                                                                • global settings in s4j_config.properties file
                                                                • +
                                                                +
                                                              • +
                                                              +
                                                              blocks:
                                                              +  msg-produce-block:
                                                              +    ops:
                                                              +      op1:
                                                              +        ## The value represents the destination (queue or topic) name)
                                                              +        MessageProduce: "mys4jtest_t"
                                                              +
                                                              +        ## (Optional) client side message selector
                                                              +        msg_selector: ""
                                                              +
                                                              +        ## (Optional) No Local
                                                              +        no_local: "true"
                                                              +
                                                              +        ## (Optional) Read Timeout
                                                              +        read_timeout: "10"
                                                              +
                                                              +        ## (Optional) Receive message without wait
                                                              +        no_wait: "true"
                                                              +
                                                              +        ## (Optional) Message acknowledgement ratio
                                                              +        msg_ack_ratio: "0.5"
                                                              +
                                                              +        ## (Optional) Simulate slow consumer acknowledgement
                                                              +        # must be non-negative numbers. negative numbers will be treated as 0
                                                              +        # 0 - means no simulation
                                                              +        # positive value - the number of seconds to pause before acknowledgement
                                                              +        slow_ack_in_sec: "0"
                                                              +
                                                              +        #####
                                                              +        ## (Optional) Statement level settings for Consumer
                                                              +        #
                                                              +        ## AckTimeout value (at least 1 second)
                                                              +        consumer.ackTimeoutMillis: 1000
                                                              +
                                                              +        ## DLQ policy
                                                              +        consumer.deadLetterPolicy: '{ "maxRedeliverCount": "2" }'
                                                              +
                                                              +        ## NegativeAck Redelivery policy
                                                              +        consumer.negativeAckRedeliveryBackoff: |
                                                              +          {
                                                              +          }
                                                              +
                                                              +        ## AckTimeout Redelivery policy
                                                              +        consumer.ackTimeoutRedeliveryBackoff: |
                                                              +          {
                                                              +            "minDelayMs":"10",
                                                              +            "maxDelayMs":"20",
                                                              +            "multiplier":"1.2"
                                                              +          }
                                                              +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/stdout/index.html b/reference/drivers/stdout/index.html new file mode 100644 index 000000000..a2d207270 --- /dev/null +++ b/reference/drivers/stdout/index.html @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + stdout | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              stdout

                                                              +

                                                              This is an activity type which allows for the generation of data +into to stdout or a file. It reads the standard nosqlbench YAML +format. It can read YAML activity files for any activity type +that uses the curly brace token form in statements.

                                                              +

                                                              Example activity definitions

                                                              +

                                                              Run a stdout activity named 'stdout-test', with definitions from activities/stdout-test.yaml

                                                              +
                                                              nb5 driver=stdout workload=stdout-test
                                                              +
                                                              +

                                                              Only run statement groups which match a tag regex

                                                              +
                                                              nb5 driver=stdout workload=stdout-test tags=group:'ddl.*'
                                                              +
                                                              +

                                                              Run the matching 'dml' statements, with 100 cycles, from [1000..1100)

                                                              +
                                                              nb5 driver=stdout workload=stdout-test tags=group:'dml.*' cycles=1000..11000 filename=test.csv
                                                              +
                                                              +

                                                              This last example shows that the cycle range is [inclusive..exclusive), +to allow for stacking test intervals. This is standard across all +activity types.

                                                              +

                                                              stdout ActivityType Parameters

                                                              +
                                                                +
                                                              • filename - this is the name of the output file +(defaults to "stdout", which actually writes to stdout, not the filesystem)
                                                              • +
                                                              • newline - whether to automatically add a missing newline to the end +of any statements. +default: true
                                                              • +
                                                              • format - which format to use. If provided, the format will override any statement formats provided by the YAML. +valid values are (csv, readout, json, inlinejson, assignments, and diag) +
                                                                  +
                                                                • When 'format=diag', then the internal construction logic for the binding is logged in detail and nosqlbench exits. +This is useful for detailed diagnostics when you run into trouble, but not generally otherwise. This provides +details that you may include in a bug report if you think there is a bindings bug.
                                                                • +
                                                                +
                                                              • +
                                                              • bindings - This is a simple way to specify a filter for the names of bindings that you want to use. +If this is 'doc', then all the document level bindings are used. If it is any other value, it is taken +as a pattern (regex) to subselect a set of bindings by name. You can simply use the name of a binding +here as well. +default: doc
                                                              • +
                                                              +

                                                              Configuration

                                                              +

                                                              This activity type uses the uniform yaml configuration format. +For more details on this format, please refer to the +Standard YAML Format

                                                              +

                                                              Configuration Parameters

                                                              +
                                                                +
                                                              • newline - If a statement has this param defined, then it determines +whether or not to automatically add a missing newline for that statement +only. If this is not defined for a statement, then the activity-level +parameter takes precedence.
                                                              • +
                                                              +

                                                              Statement Format

                                                              +

                                                              The statement format for this activity type is a simple string. Tokens between +curly braces are used to refer to binding names, as in the following example:

                                                              +
                                                                  ops:
                                                              +     op1: "It is {minutes} past {hour}."
                                                              +
                                                              +

                                                              If you want to suppress the trailing newline that is automatically added, then +you must either pass newline=false as an activity param, or specify it +in the statement params in your config as in:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    stmt: "It is {minutes} past {hour}."
                                                              +    newline: false
                                                              +
                                                              +

                                                              Auto-generated statements

                                                              +

                                                              If no statement is provided, then the defined binding names are used as-is +to create a CSV-style line format. The values are concatenated with +comma delimiters, so a set of bindings like this:

                                                              +
                                                                  bindings:
                                                              +     one: Identity()
                                                              +     two: NumberNameToString()
                                                              +
                                                              +

                                                              would create an automatic string template like this:

                                                              +
                                                              ops:
                                                              + op1: "{one},{two}\n"
                                                              +
                                                              +

                                                              The auto-generation behavior is forced when the format parameter is supplied.

                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/tcpclient/index.html b/reference/drivers/tcpclient/index.html new file mode 100644 index 000000000..3e6a129e6 --- /dev/null +++ b/reference/drivers/tcpclient/index.html @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + tcpclient | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              tcpclient

                                                              +

                                                              tcpclient acts like a client push version of stdout over TCP

                                                              +

                                                              The tcpclient driver is based on the behavior of the stdout driver. You configure the tcpclient driver in exactly the +same way as the stdout driver, except for the additional parameters shown here.

                                                              +

                                                              The tcpclient driver connects to a configured host and port (a socket address). When a server is listening on that socket, +then the data for each cycle is written via the socket just like stdout would write.

                                                              +

                                                              Examples

                                                              +

                                                              Run a stdout activity named 'stdout-test', with definitions from activities/stdout-test.yaml

                                                              +
                                                              ... driver=tcpclient yaml=stdout-test
                                                              +
                                                              +

                                                              Driver Parameters

                                                              +
                                                                +
                                                              • +

                                                                retry_delay - The internal retry frequency at which the internal cycle loop will attempt to add data to the +buffer. This applies when the internal buffer is full and no clients are consuming data from it.

                                                                +
                                                                  +
                                                                • unit: milliseconds
                                                                • +
                                                                • default: 1000
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                retries - The number of retries which the internal cycle loop will attempt before marking a row of output as +failed.

                                                                +
                                                                  +
                                                                • default: 3
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                ssl - boolean to enable or disable ssl

                                                                +
                                                                  +
                                                                • default: false
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +

                                                                To enable, specifies the type of the SSL implementation with either jdk or openssl.

                                                                +

                                                                See the ssl help topic for more details with nb5 help ssl for more details.

                                                                +
                                                              • +
                                                              • +

                                                                host - this is the name to bind to (local interface address)

                                                                +
                                                                  +
                                                                • default: localhost
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                port - this is the name of the port to listen on

                                                                +
                                                                  +
                                                                • default: 12345
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                capacity - the size of the internal blocking queue

                                                                +
                                                                  +
                                                                • default: 10
                                                                • +
                                                                • unit: lines of output
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              +

                                                              Statement Format

                                                              +

                                                              Refer to the help for the stdout driver for details.

                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/drivers/tcpserver/index.html b/reference/drivers/tcpserver/index.html new file mode 100644 index 000000000..59da23c83 --- /dev/null +++ b/reference/drivers/tcpserver/index.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + tcpserver | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              tcpserver

                                                              +

                                                              tcpserver acts like a server push version of stdout over TCP

                                                              +

                                                              The tcpserver driver is based on the behavior of the stdout driver. You configure the tcpserver driver in exactly the +same way as the stdout driver, except for the additional parameters shown here.

                                                              +

                                                              The tcpserver driver listens on a configured host and port (a socket address). When any clients are connected, the +internal queue is buffered to them as long as there is data in it. For each cycle of data in the internal buffer, one of +the connected clients will get it in unspecified order.

                                                              +

                                                              The driver activity will block as long as there are still messages in the queue (Max:capacity). To ensure that the queue is empties and the activity shuts down correctly, one must make sure that a client connects to the server to receive the queued messages.

                                                              +

                                                              If the buffer is primed with data when a client is connected it will get all of the data at once. After this, data is +added to the buffer at whatever cyclerate the activity is configured for. If you add data to the buffer faster than you +can consume it with connected clients, you will have a number of failed operations.

                                                              +

                                                              However, the opposite is not true. You should generally ensure that you can consume the data as fast as you provide it, +and the error counts give you a relatively easy way to verify this. If you wish to disable this behavior, set the +retries to a very high value. In this case, the tries metric will still give you some measure of internal buffer +saturation.

                                                              +

                                                              Examples

                                                              +

                                                              Run a stdout activity named 'stdout-test', with definitions from activities/stdout-test.yaml

                                                              +
                                                              ... driver=tcpserver yaml=stdout-test
                                                              +
                                                              +

                                                              Driver Parameters

                                                              +
                                                                +
                                                              • +

                                                                retry_delay - The internal retry frequency at which the internal cycle loop will attempt to add data to the +buffer. This applies when the internal buffer is full and no clients are consuming data from it.

                                                                +
                                                                  +
                                                                • unit: milliseconds
                                                                • +
                                                                • default: 1000
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                retries - The number of retries which the internal cycle loop will attempt before marking a row of output as +failed.

                                                                +
                                                                  +
                                                                • default: 3
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                ssl - boolean to enable or disable ssl

                                                                +
                                                                  +
                                                                • default: false
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +

                                                                To enable, specifies the type of the SSL implementation with either jdk or openssl.

                                                                +

                                                                See the ssl help topic for more details with nb5 help ssl for more details.

                                                                +
                                                              • +
                                                              • +

                                                                host - this is the name to bind to (local interface address)

                                                                +
                                                                  +
                                                                • default: localhost
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                port - this is the name of the port to listen on

                                                                +
                                                                  +
                                                                • default: 12345
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              • +

                                                                capacity - the size of the internal blocking queue

                                                                +
                                                                  +
                                                                • default: 10
                                                                • +
                                                                • unit: lines of output
                                                                • +
                                                                • dynamic: false
                                                                • +
                                                                +
                                                              • +
                                                              +

                                                              Statement Format

                                                              +

                                                              Refer to the help for the stdout driver for details.

                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/index.html b/reference/index.html new file mode 100644 index 000000000..be9eb68f1 --- /dev/null +++ b/reference/index.html @@ -0,0 +1,510 @@ + + + + + + + + + + + + + + + + Op Templates | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Op Templates

                                                              +

                                                              Op templates are the recipes provided by users for an operation. These hold examples of payload +data, metadata that configures the driver, timeout settings and so on.

                                                              +

                                                              The field name used in workload templates to represent operations can often be symbolic to users. +For this reason, several names are allowed: ops, op, operations, statements, statement. It doesn't +matter whether the value is provided as a map, list, or scalar. These all allow for the same +level of templating. Map forms are preferred, since they include naming in a more streamlined +structure. When you use list form, you have to provide the name as a separate field.

                                                              +

                                                              A name is automatically provided by the API when there is one missing.

                                                              +

                                                              a single un-named op template

                                                              +

                                                              yaml:

                                                              +
                                                              op: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "op": "select * from bar.table;"
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--stmt1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--stmt1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              un-named op templates as a list of strings

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    "select * from bar.table;"
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--stmt1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--stmt1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              named op templates as a list of maps with name-stmt as first entry

                                                              +

                                                              This form will take the first key and value of the map as the name and statement for the op +template.

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - op1: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    {
                                                              +      "op1": "select * from bar.table;"
                                                              +    }
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              op templates as a list of maps with name field

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - name: op1
                                                              +    op: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    {
                                                              +      "name": "op1",
                                                              +      "op": "select * from bar.table;"
                                                              +    }
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              named op templates as a map of strings

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": "select * from bar.table;"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              named op templates as a map of maps

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    stmt: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Op Template Properties

                                                              +

                                                              All the forms above merely show how you can structure op templates into common collection forms and +have them be interpreted in a flexible yet obvious way.

                                                              +

                                                              However, all the properties described in templated_workloads.md +can be attached directly to op templates too. This section contains a few examples to illustrate +this at work.

                                                              +

                                                              detailed op template example

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    name: special-op-name
                                                              +    op: select * from ks1.tb1;
                                                              +    bindings:
                                                              +      binding1: NumberNameToString();
                                                              +    tags:
                                                              +      block: schema
                                                              +    params:
                                                              +      prepared: false
                                                              +    description: This is just an example operation
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "bindings": {
                                                              +        "binding1": "NumberNameToString();"
                                                              +      },
                                                              +      "description": "This is just an example operation",
                                                              +      "name": "special-op-name",
                                                              +      "op": "select * from ks1.tb1;",
                                                              +      "params": {
                                                              +        "prepared": false
                                                              +      },
                                                              +      "tags": {
                                                              +        "block": "schema"
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "bindings": {
                                                              +      "binding1": "NumberNameToString();"
                                                              +    },
                                                              +    "description": "This is just an example operation",
                                                              +    "name": "block0--special-op-name",
                                                              +    "op": {
                                                              +      "stmt": "select * from ks1.tb1;"
                                                              +    },
                                                              +    "params": {
                                                              +      "prepared": false
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "schema",
                                                              +      "name": "block0--special-op-name",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Property Layering

                                                              +

                                                              Properties that are provided at the top (doc) level become defaults for each nested layer (block or +ops). Each named binding, param, or tag is automatically assigned to any contained layers which do +not have one of the same name. When two layers contain the same named binding, param or tag, the +inner-most scope decides the value seen at the op level.

                                                              +

                                                              block-level defaults and overrides

                                                              +

                                                              yaml:

                                                              +
                                                              tags:
                                                              +  docleveltag: is-tagging-everything # applies to all operations in this case
                                                              +
                                                              +bindings:
                                                              +  binding1: Identity(); # will be overridden at the block level
                                                              +
                                                              +params:
                                                              +  prepared: true # set prepared true by default for all contained op templates
                                                              +
                                                              +blocks:
                                                              +  block-named-fred:
                                                              +    bindings:
                                                              +      binding1: NumberNameToString();
                                                              +    tags:
                                                              +      block: schema
                                                              +    params:
                                                              +      prepared: false
                                                              +    description: This is just an example operation
                                                              +    ops:
                                                              +      op1:
                                                              +        name: special-op-name
                                                              +        op: select * from ks1.tb1;
                                                              +
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "tags": {
                                                              +    "docleveltag": "is-tagging-everything"
                                                              +  },
                                                              +  "bindings": {
                                                              +    "binding1": "Identity();"
                                                              +  },
                                                              +  "params": {
                                                              +    "prepared": true
                                                              +  },
                                                              +  "blocks": {
                                                              +    "block-named-fred": {
                                                              +      "bindings": {
                                                              +        "binding1": "NumberNameToString();"
                                                              +      },
                                                              +      "description": "This is just an example operation",
                                                              +      "params": {
                                                              +        "prepared": false
                                                              +      },
                                                              +      "tags": {
                                                              +        "block": "schema"
                                                              +      },
                                                              +      "ops": {
                                                              +        "op1": {
                                                              +          "name": "special-op-name",
                                                              +          "op": "select * from ks1.tb1;"
                                                              +        }
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "bindings": {
                                                              +      "binding1": "NumberNameToString();"
                                                              +    },
                                                              +    "name": "block-named-fred--special-op-name",
                                                              +    "op": {
                                                              +      "stmt": "select * from ks1.tb1;"
                                                              +    },
                                                              +    "params": {
                                                              +      "prepared": false
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "schema",
                                                              +      "docleveltag": "is-tagging-everything",
                                                              +      "name": "block-named-fred--special-op-name",
                                                              +      "block": "block-named-fred"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/versions/index.html b/reference/versions/index.html new file mode 100644 index 000000000..7d01d0bb9 --- /dev/null +++ b/reference/versions/index.html @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + Version Info | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Version Info

                                                              +

                                                              The version of NB5 which provided some of the docs content is:

                                                              +
                                                              version=5.17.2-SNAPSHOT
                                                              +groupId=io.nosqlbench
                                                              +artifactId=nbr
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/versions/nb-version-info/index.html b/reference/versions/nb-version-info/index.html new file mode 100644 index 000000000..44dbf9027 --- /dev/null +++ b/reference/versions/nb-version-info/index.html @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + Version Info | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Version Info

                                                              +

                                                              The version of NB5 which provided some of the docs content is:

                                                              +
                                                              version=5.17.2-SNAPSHOT
                                                              +groupId=io.nosqlbench
                                                              +artifactId=nbr
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/workload_definition/00-workload-specification/index.html b/reference/workload_definition/00-workload-specification/index.html new file mode 100644 index 000000000..0b29797d2 --- /dev/null +++ b/reference/workload_definition/00-workload-specification/index.html @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + Workload Specification | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Workload Specification

                                                              +

                                                              This directory contains the testable specification for workload definitions used by NoSQLBench. +All the content blocks in this section have been validated with the latest NoSQLBench build.

                                                              +

                                                              Usually, users will not need to delve too deeply into this section. It is useful as a detailed +guide for contributors and driver developers. If you are using a driver which leaves you +wondering what a good op template example looks like, then the driver needs better examples in +its documentation!

                                                              +

                                                              Synopsis

                                                              +

                                                              There are two primary views of workload definitions that we care about:

                                                              +
                                                                +
                                                              1. The User View of op templates +
                                                                  +
                                                                1. Op templates are simply the schematic recipes for building an operation once you know the +cycle it is for.
                                                                2. +
                                                                3. Op templates are provided by users in YAML or JSON or even directly via runtime API. This +is called a workload template, which contains op templates.
                                                                4. +
                                                                5. Op templates can be provided with optional metadata which serve to label, group, +parameterize or otherwise make the individual op templates more manageable.
                                                                6. +
                                                                7. A variety of forms are supported which are self-evident, but which allow users to have +some flexibility in how they structure their YAML, JSON, or runtime collections. **This +specification is about how these various forms are allowed, and how they relate to a +fully-qualified and de-normalized op template view.
                                                                8. +
                                                                +
                                                              2. +
                                                              3. The Developer View of the ParsedOp API. This is the view of an op template which presents the +developer with a very high-level toolkit for building op synthesis functions.
                                                              4. +
                                                              +

                                                              Details

                                                              +

                                                              The documentation in this directory serve as a testable specification for all the above. It +shows specific examples of all the valid op template forms in both YAML and JSON, as well as how +the data is normalized to feed developer's view of the ParsedOp API.

                                                              + +

                                                              If you want to understand the rest of this document, it is crucial that you have a working knowledge +of the standard YAML format and several examples from the current drivers. You can learn this from +the main documentation which demonstrates step-by-step how to build a workload. Reading further in +this document will be most useful for core NB developers, or advanced users who want to know all +the possible ways of building workloads.

                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/workload_definition/01-spectest-formatting/index.html b/reference/workload_definition/01-spectest-formatting/index.html new file mode 100644 index 000000000..080b0453c --- /dev/null +++ b/reference/workload_definition/01-spectest-formatting/index.html @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + SpecTest Formatting | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              SpecTest Formatting

                                                              +

                                                              The specifications and examples follow a pattern:

                                                              +
                                                                +
                                                              1. Some or part of a templated workload in yaml format.
                                                              2. +
                                                              3. The JSON equivalent as it would be loaded. This is cross-checked against the result of parsing +the yaml into data.
                                                              4. +
                                                              5. The Workload API view of the same data rendered as a JSON data structure. This is cross-checked +against the workload API's rendering of the loaded data.
                                                              6. +
                                                              +

                                                              To be matched by the testing layer, you must prefix each section with a format marker with emphasis, +like this:

                                                              +

                                                              format:

                                                              +
                                                              body of example
                                                              +
                                                              +

                                                              Further, to match the pattern above, these must occur in sequences like the following, with no other +intervening content. If the second fenced code section is a JSON array, then each object within +it is compared pair-wise with the yaml structure as in a multi-doc scenario. The following +example is actually tested along with the non-empty templates. It is valid because the second +block is in array form, and thus compares 0 pair-wise elements.

                                                              +

                                                              yaml:

                                                              +
                                                              # some yaml here
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +

                                                              The above sequence of 6 contiguous markdown elements follows a recognizable pattern to the +specification testing harness. The names above the sections are required to match and fenced +code sections are required to follow each.

                                                              +

                                                              All the markdown files in this directory are loaded and scanned for this pattern, and all +such sequences are verified each time NoSQLBench is built.

                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/workload_definition/02-workload-structure/index.html b/reference/workload_definition/02-workload-structure/index.html new file mode 100644 index 000000000..4e5c8597f --- /dev/null +++ b/reference/workload_definition/02-workload-structure/index.html @@ -0,0 +1,562 @@ + + + + + + + + + + + + + + + + Workload Structure | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Workload Structure

                                                              +

                                                              Keywords

                                                              +

                                                              The following words have special meaning in templated workloads:

                                                              +
                                                                +
                                                              • name - names things
                                                              • +
                                                              • desc, description - describes the current element. First line is summary.
                                                              • +
                                                              • scenarios - describes named command sequences for automated workflows
                                                              • +
                                                              • bindings - defines procedural generation functions
                                                              • +
                                                              • params - decorates operations with special configurations
                                                              • +
                                                              • tags - describes elements for filtering and grouping
                                                              • +
                                                              • op, ops, operations statement, statements - defines op templates
                                                              • +
                                                              • blocks - groups any or all elements
                                                              • +
                                                              +
                                                              +

                                                              Description

                                                              +

                                                              zero or one description fields:

                                                              +

                                                              The first line of the description represents the summary of the description in summary views. +Otherwise, the whole value is used.

                                                              +

                                                              yaml:

                                                              +
                                                              description: |
                                                              +  summary of this workload
                                                              +  and more details
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "description": "summary of this workload\nand more details\n"
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +
                                                              +

                                                              Scenarios

                                                              +

                                                              zero or one scenarios fields, containing one of the following forms

                                                              +

                                                              The way that you create macro-level workloads from individual stages is called named scenarios in +NB. These are basically command line templates which can be invoked automatically by calling their +name out on your command line. More details on their usage are in the workload construction guide. +We're focused merely on the structural rules here.

                                                              +

                                                              single un-named step

                                                              +

                                                              yaml:

                                                              +
                                                              scenarios:
                                                              +  default: run driver=diag cycles=10
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "scenarios": {
                                                              +    "default": "run driver=diag cycles=10"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +

                                                              multiple named steps

                                                              +

                                                              yaml:

                                                              +
                                                              scenarios:
                                                              +  default:
                                                              +    step1: run alias=first driver=diag cycles=10
                                                              +    step2: run alias=second driver=diag cycles=10
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "scenarios": {
                                                              +    "default": {
                                                              +      "step1": "run alias=first driver=diag cycles=10",
                                                              +      "step2": "run alias=second driver=diag cycles=10"
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +

                                                              list of un-named steps

                                                              +

                                                              yaml:

                                                              +
                                                              scenarios:
                                                              +  default:
                                                              +    - run alias=first driver=diag cycles=10
                                                              +    - run alias=second driver=diag cycles=10
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "scenarios": {
                                                              +    "default": [
                                                              +      "run alias=first driver=diag cycles=10",
                                                              +      "run alias=second driver=diag cycles=10"
                                                              +    ]
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +

                                                              silent locked step parameters

                                                              +

                                                              For scenario steps which should not be overridable by user parameters on the command line, a double +equals is used to lock the values for a given step without informing the user that their provided +value was ignored. This can be useful in cases where there are multiple steps and some parameters +should only be changeable for some steps.

                                                              +

                                                              yaml:

                                                              +
                                                              # The user is not allowed to change the value for the alias parameter, and attempting to do so
                                                              +# will cause an error to be thrown and the scenario halted.
                                                              +scenarios:
                                                              +  default: run alias==first driver=diag cycles=10
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "scenarios": {
                                                              +    "default": "run alias==first driver=diag cycles=10"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +

                                                              verbose locked step parameters

                                                              +

                                                              For scenario steps which should not be overridable by user parameters on the command line, a triple +equals is used to indicate that changing these parameters is not allowed. If a user tries to +override a verbose locked parameter, an error is thrown and the scenario is not allowed to run. This +can be useful when you want to clearly indicate that a parameter must remain as it is.

                                                              +

                                                              yaml:

                                                              +
                                                              # The user is not allowed to change the value for the alias parameter, and attempting to do so
                                                              +# will cause an error to be thrown and the scenario halted.
                                                              +scenarios:
                                                              +  default: run alias===first driver=diag cycles=10
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "scenarios": {
                                                              +    "default": "run alias===first driver=diag cycles=10"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +
                                                              +

                                                              Bindings

                                                              +

                                                              zero or one bindings fields, containing a map of named bindings recipes

                                                              +

                                                              Bindings are the functions which synthesize data for your operations. They are specified in recipes +which are just function chains from the provided libraries.

                                                              +

                                                              yaml:

                                                              +
                                                              bindings:
                                                              +  cycle: Identity();
                                                              +  name: NumberNameToString();
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "bindings": {
                                                              +    "cycle": "Identity();",
                                                              +    "name": "NumberNameToString();"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +
                                                              +

                                                              Params

                                                              +

                                                              zero of one params fields, containing a map of parameter names to values

                                                              +

                                                              Params are modifiers to your operations. They specify important details which are not part of the +operation's command or payload, like consistency level, or timeout settings.

                                                              +

                                                              yaml:

                                                              +
                                                              params:
                                                              +  param1: pvalue1
                                                              +  param2: pvalue2
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "params": {
                                                              +    "param1": "pvalue1",
                                                              +    "param2": "pvalue2"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +
                                                              +

                                                              Tags

                                                              +

                                                              zero or one tags fields, containing a map of tag names and values

                                                              +

                                                              Tags are how you mark your operations for special inclusion into tests. They are basically naming +metadata that lets you filter what type of operations you actually use. Further details on tags are +in the workload construction guide.

                                                              +

                                                              yaml:

                                                              +
                                                              tags:
                                                              +  block: main
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "tags": {
                                                              +    "block": "main"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +
                                                              +

                                                              Blocks

                                                              +

                                                              Blocks are used to logically partition a workload for the purposes of grouping, configuring or +executing subsets and op sequences. Blocks can contain any of the defined elements above. +Every op template within a block automatically gets a tag with the name 'block' and the value of +the block name. This makes it easy to select a whole block at a time with a tag filter like +tags=block:"schema.*".

                                                              +

                                                              Blocks are not recursive. You may not put a block inside another block.

                                                              +

                                                              named blocks as a map of property maps

                                                              +

                                                              yaml:

                                                              +
                                                              blocks:
                                                              +  namedblock1:
                                                              +    ops:
                                                              +      op1: select * from bar.table;
                                                              +      op2:
                                                              +        type: batch
                                                              +        stmt: insert into bar.table (a,b,c) values (1,2,3);
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "blocks": {
                                                              +    "namedblock1": {
                                                              +      "ops": {
                                                              +        "op1": "select * from bar.table;",
                                                              +        "op2": {
                                                              +          "type": "batch",
                                                              +          "stmt": "insert into bar.table (a,b,c) values (1,2,3);"
                                                              +        }
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "namedblock1--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "namedblock1--op1",
                                                              +      "block": "namedblock1"
                                                              +    }
                                                              +  },
                                                              +  {
                                                              +    "name": "namedblock1--op2",
                                                              +    "op": {
                                                              +      "stmt": "insert into bar.table (a,b,c) values (1,2,3);"
                                                              +    },
                                                              +    "params": {
                                                              +      "type": "batch"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "namedblock1--op2",
                                                              +      "block": "namedblock1"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              lists of blocks as a list of property maps

                                                              +

                                                              When blocks are defined as a list of entries, each entry is a map.

                                                              +

                                                              yaml:

                                                              +
                                                              blocks:
                                                              +  - ops:
                                                              +      op1: select * from bar.table;
                                                              +      op2:
                                                              +        type: batch
                                                              +        stmt: insert into bar.table (a,b,c) values (1,2,3);
                                                              +  - name: this-is-block-2
                                                              +    ops:
                                                              +      op3: select * from foo.table;
                                                              +
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "blocks": [
                                                              +    {
                                                              +      "ops": {
                                                              +        "op1": "select * from bar.table;",
                                                              +        "op2": {
                                                              +          "type": "batch",
                                                              +          "stmt": "insert into bar.table (a,b,c) values (1,2,3);"
                                                              +        }
                                                              +      }
                                                              +    },
                                                              +    {
                                                              +      "name": "this-is-block-2",
                                                              +      "ops": {
                                                              +        "op3": "select * from foo.table;"
                                                              +      }
                                                              +    }
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block1--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block1--op1",
                                                              +      "block": "block1"
                                                              +    }
                                                              +  },
                                                              +  {
                                                              +    "name": "block1--op2",
                                                              +    "op": {
                                                              +      "stmt": "insert into bar.table (a,b,c) values (1,2,3);"
                                                              +    },
                                                              +    "params": {
                                                              +      "type": "batch"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block1--op2",
                                                              +      "block": "block1"
                                                              +    }
                                                              +  },
                                                              +  {
                                                              +    "name": "this-is-block-2--op3",
                                                              +    "op": {
                                                              +      "stmt": "select * from foo.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "this-is-block-2--op3",
                                                              +      "block": "this-is-block-2"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +
                                                              +

                                                              Names

                                                              +

                                                              All documents, blocks, and ops within a workload can have an assigned name. When map and list forms +are both supported for entries, the map form provides the name. When list forms are used, an +additional field named name can be used.

                                                              +

                                                              yaml:

                                                              +
                                                              blocks:
                                                              +  - name: myblock
                                                              +    op: "test op"
                                                              +
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "blocks": [
                                                              +    {
                                                              +      "name": "myblock",
                                                              +      "op": "test op"
                                                              +    }
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "myblock--stmt1",
                                                              +    "op": {
                                                              +      "stmt": "test op"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "myblock--stmt1",
                                                              +      "block": "myblock"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              --

                                                              +

                                                              Putting things together

                                                              +

                                                              This document is focused on the basic properties that can be added to a templated workload. To see +how they are combined together, see Op Templates Basics.

                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/workload_definition/04-op-template-basics/index.html b/reference/workload_definition/04-op-template-basics/index.html new file mode 100644 index 000000000..2af747752 --- /dev/null +++ b/reference/workload_definition/04-op-template-basics/index.html @@ -0,0 +1,510 @@ + + + + + + + + + + + + + + + + Op Templates | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Op Templates

                                                              +

                                                              Op templates are the recipes provided by users for an operation. These hold examples of payload +data, metadata that configures the driver, timeout settings and so on.

                                                              +

                                                              The field name used in workload templates to represent operations can often be symbolic to users. +For this reason, several names are allowed: ops, op, operations, statements, statement. It doesn't +matter whether the value is provided as a map, list, or scalar. These all allow for the same +level of templating. Map forms are preferred, since they include naming in a more streamlined +structure. When you use list form, you have to provide the name as a separate field.

                                                              +

                                                              A name is automatically provided by the API when there is one missing.

                                                              +

                                                              a single un-named op template

                                                              +

                                                              yaml:

                                                              +
                                                              op: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "op": "select * from bar.table;"
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--stmt1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--stmt1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              un-named op templates as a list of strings

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    "select * from bar.table;"
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--stmt1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--stmt1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              named op templates as a list of maps with name-stmt as first entry

                                                              +

                                                              This form will take the first key and value of the map as the name and statement for the op +template.

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - op1: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    {
                                                              +      "op1": "select * from bar.table;"
                                                              +    }
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              op templates as a list of maps with name field

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - name: op1
                                                              +    op: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    {
                                                              +      "name": "op1",
                                                              +      "op": "select * from bar.table;"
                                                              +    }
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              named op templates as a map of strings

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": "select * from bar.table;"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              named op templates as a map of maps

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    stmt: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Op Template Properties

                                                              +

                                                              All the forms above merely show how you can structure op templates into common collection forms and +have them be interpreted in a flexible yet obvious way.

                                                              +

                                                              However, all the properties described in templated_workloads.md +can be attached directly to op templates too. This section contains a few examples to illustrate +this at work.

                                                              +

                                                              detailed op template example

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    name: special-op-name
                                                              +    op: select * from ks1.tb1;
                                                              +    bindings:
                                                              +      binding1: NumberNameToString();
                                                              +    tags:
                                                              +      block: schema
                                                              +    params:
                                                              +      prepared: false
                                                              +    description: This is just an example operation
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "bindings": {
                                                              +        "binding1": "NumberNameToString();"
                                                              +      },
                                                              +      "description": "This is just an example operation",
                                                              +      "name": "special-op-name",
                                                              +      "op": "select * from ks1.tb1;",
                                                              +      "params": {
                                                              +        "prepared": false
                                                              +      },
                                                              +      "tags": {
                                                              +        "block": "schema"
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "bindings": {
                                                              +      "binding1": "NumberNameToString();"
                                                              +    },
                                                              +    "description": "This is just an example operation",
                                                              +    "name": "block0--special-op-name",
                                                              +    "op": {
                                                              +      "stmt": "select * from ks1.tb1;"
                                                              +    },
                                                              +    "params": {
                                                              +      "prepared": false
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "schema",
                                                              +      "name": "block0--special-op-name",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Property Layering

                                                              +

                                                              Properties that are provided at the top (doc) level become defaults for each nested layer (block or +ops). Each named binding, param, or tag is automatically assigned to any contained layers which do +not have one of the same name. When two layers contain the same named binding, param or tag, the +inner-most scope decides the value seen at the op level.

                                                              +

                                                              block-level defaults and overrides

                                                              +

                                                              yaml:

                                                              +
                                                              tags:
                                                              +  docleveltag: is-tagging-everything # applies to all operations in this case
                                                              +
                                                              +bindings:
                                                              +  binding1: Identity(); # will be overridden at the block level
                                                              +
                                                              +params:
                                                              +  prepared: true # set prepared true by default for all contained op templates
                                                              +
                                                              +blocks:
                                                              +  block-named-fred:
                                                              +    bindings:
                                                              +      binding1: NumberNameToString();
                                                              +    tags:
                                                              +      block: schema
                                                              +    params:
                                                              +      prepared: false
                                                              +    description: This is just an example operation
                                                              +    ops:
                                                              +      op1:
                                                              +        name: special-op-name
                                                              +        op: select * from ks1.tb1;
                                                              +
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "tags": {
                                                              +    "docleveltag": "is-tagging-everything"
                                                              +  },
                                                              +  "bindings": {
                                                              +    "binding1": "Identity();"
                                                              +  },
                                                              +  "params": {
                                                              +    "prepared": true
                                                              +  },
                                                              +  "blocks": {
                                                              +    "block-named-fred": {
                                                              +      "bindings": {
                                                              +        "binding1": "NumberNameToString();"
                                                              +      },
                                                              +      "description": "This is just an example operation",
                                                              +      "params": {
                                                              +        "prepared": false
                                                              +      },
                                                              +      "tags": {
                                                              +        "block": "schema"
                                                              +      },
                                                              +      "ops": {
                                                              +        "op1": {
                                                              +          "name": "special-op-name",
                                                              +          "op": "select * from ks1.tb1;"
                                                              +        }
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "bindings": {
                                                              +      "binding1": "NumberNameToString();"
                                                              +    },
                                                              +    "name": "block-named-fred--special-op-name",
                                                              +    "op": {
                                                              +      "stmt": "select * from ks1.tb1;"
                                                              +    },
                                                              +    "params": {
                                                              +      "prepared": false
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "schema",
                                                              +      "docleveltag": "is-tagging-everything",
                                                              +      "name": "block-named-fred--special-op-name",
                                                              +      "block": "block-named-fred"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/workload_definition/05-op-template-payloads/index.html b/reference/workload_definition/05-op-template-payloads/index.html new file mode 100644 index 000000000..4f1079569 --- /dev/null +++ b/reference/workload_definition/05-op-template-payloads/index.html @@ -0,0 +1,480 @@ + + + + + + + + + + + + + + + + Op Template Payloads | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Op Template Payloads

                                                              +

                                                              Payloads in NoSQLBench op templates can be of any type that you can create from bindings, string +templates, data structure, or any combination thereof. Yet, the recipe format for these bindings is +simple and direct. If you know what you want the op to do, then one of the supported forms here +should get you there.

                                                              +

                                                              The payload of an operation is handled as any content which is assigned to the op field in the +uniform op structure.

                                                              +

                                                              assigned ops as string

                                                              +

                                                              When you are using the command, it is possible to specify op=... instead of providing a workload +path. When you do that, a workload description is automatically derived for you on-the-fly.

                                                              +

                                                              nb run driver=stdout op='cycle number {{NumberNameToString}'

                                                              +

                                                              The equivalent structure has the same effect as if you had created a workload description like this:

                                                              +

                                                              yaml:

                                                              +
                                                              ops: "cycle number '{{NumberNameToString}}'"
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": "cycle number '{{NumberNameToString}}'"
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block0--stmt1",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "cycle number '{{NumberNameToString}}'"
                                                              +    },
                                                              +    "name": "block0--stmt1"
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              assigned ops as a list of strings

                                                              +

                                                              If the value type of the top-level ops field is in list form, then each value is processed +individually.

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - "even cycle '{{NumberNameToString}}'"
                                                              +  - "odd  cycle '{{NumberNameToString}}'"
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    "even cycle '{{NumberNameToString}}'",
                                                              +    "odd  cycle '{{NumberNameToString}}'"
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block0--stmt1",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "even cycle '{{NumberNameToString}}'"
                                                              +    },
                                                              +    "name": "block0--stmt1"
                                                              +  },
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block0--stmt2",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "odd  cycle '{{NumberNameToString}}'"
                                                              +    },
                                                              +    "name": "block0--stmt2"
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              assigned ops as a map of strings

                                                              +

                                                              A more preferable way to add ops to a structure is in map form. This is also covered elsewhere, but +it is important for examples further below so we'll refresh it here:

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  myop1: "even cycle '{{NumberNameToString}}'"
                                                              +  myop2: "odd  cycle '{{NumberNameToString}}'"
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "myop1": "even cycle '{{NumberNameToString}}'",
                                                              +    "myop2": "odd  cycle '{{NumberNameToString}}'"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block0--myop1",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "even cycle '{{NumberNameToString}}'"
                                                              +    },
                                                              +    "name": "block0--myop1"
                                                              +  },
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block0--myop2",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "odd  cycle '{{NumberNameToString}}'"
                                                              +    },
                                                              +    "name": "block0--myop2"
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              assigned op payload as a simple map of op fields

                                                              +

                                                              When your operation takes on a non-statement form, you simply provide a map structure at the +top-level of the op:

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    opfield1: opvalue1
                                                              +    opfield2: opvalue2
                                                              +
                                                              +
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "opfield1": "opvalue1",
                                                              +      "opfield2": "opvalue2"
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "opfield1": "opvalue1",
                                                              +      "opfield2": "opvalue2"
                                                              +    },
                                                              +    "name": "block0--op1"
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              assigned op payload as an array of values

                                                              +

                                                              When your operation takes on a non-statement form, you simply provide a map structure at the +top-level of the op. Notice that the structurally normalized form shows the field values moved +underneath the canonical 'op' field by default. This is because the structurally normalized +op template form always has a map in the op field. The structural short-hand for creating an +op template that is list based simply moves any list entries at the op template level down in +the named 'op' field for you.

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    - opvalue1
                                                              +    - opvalue2
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": [
                                                              +      "opvalue1",
                                                              +      "opvalue2"
                                                              +    ]
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": [
                                                              +        "opvalue1",
                                                              +        "opvalue2"
                                                              +      ]
                                                              +    },
                                                              +    "name": "block0--op1"
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              op payload with structured value types

                                                              +

                                                              From the examples above, it's clear that you can use string and maps in your op fields. Here, we +show how you can use arbitrary levels of structured types based on commodity collection types like +List and Map for Java and JSON objects and arrays.

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    index_map:
                                                              +      username: user_index
                                                              +      geocode: georef_v23
                                                              +    rollups:
                                                              +      - by_username/@4h
                                                              +      - by_session_len/@1h
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "index_map": {
                                                              +        "username": "user_index",
                                                              +        "geocode": "georef_v23"
                                                              +      },
                                                              +      "rollups": [
                                                              +        "by_username/@4h",
                                                              +        "by_session_len/@1h"
                                                              +      ]
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "index_map": {
                                                              +        "username": "user_index",
                                                              +        "geocode": "georef_v23"
                                                              +      },
                                                              +      "rollups": [
                                                              +        "by_username/@4h",
                                                              +        "by_session_len/@1h"
                                                              +      ]
                                                              +    },
                                                              +    "name": "block0--op1"
                                                              +  }
                                                              +]
                                                              +
                                                              +
                                                              +

                                                              Binding Points at any position in op field data

                                                              +

                                                              You can use either named binding points references like {userid} or binding definitions such +as {{Template('user-{}',ToString())}}. The only exception to this rule is that you may not +(yet) use dynamic values for keys within your structure.

                                                              +

                                                              yaml:

                                                              +
                                                              bindings:
                                                              +  user_index: Mod(1000L); ToString();
                                                              +
                                                              +ops:
                                                              +  op1:
                                                              +    index_map:
                                                              +      username: "{user_index}"
                                                              +      geocode: "{{Template('georef_v{}',HashRange(0,23))}}"
                                                              +    rollups:
                                                              +      - by_username/@4h
                                                              +      - by_session_len/@1h
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "bindings": {
                                                              +    "user_index": "Mod(1000L); ToString();"
                                                              +  },
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "index_map": {
                                                              +        "username": "{user_index}",
                                                              +        "geocode": "{{Template('georef_v{}',HashRange(0,23))}}"
                                                              +      },
                                                              +      "rollups": [
                                                              +        "by_username/@4h",
                                                              +        "by_session_len/@1h"
                                                              +      ]
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "bindings": {
                                                              +      "user_index": "Mod(1000L); ToString();"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "index_map": {
                                                              +        "username": "{user_index}",
                                                              +        "geocode": "{{Template('georef_v{}',HashRange(0,23))}}"
                                                              +      },
                                                              +      "rollups": [
                                                              +        "by_username/@4h",
                                                              +        "by_session_len/@1h"
                                                              +      ]
                                                              +    },
                                                              +    "name": "block0--op1"
                                                              +  }
                                                              +]
                                                              +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/workload_definition/06-op-template-variations/index.html b/reference/workload_definition/06-op-template-variations/index.html new file mode 100644 index 000000000..2ac09e71f --- /dev/null +++ b/reference/workload_definition/06-op-template-variations/index.html @@ -0,0 +1,637 @@ + + + + + + + + + + + + + + + + Op Template Variations | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Op Templates Variations

                                                              +

                                                              These examples illustrate a variety of valid op template structures.

                                                              +

                                                              Op Naming

                                                              +

                                                              map of op templates with explicit name

                                                              +

                                                              If you use a map of op templates, they can still override the name of the op simply by adding +the name key.

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    name: special-op-name
                                                              +    op: select * from ks1.tb1;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "name": "special-op-name",
                                                              +      "op": "select * from ks1.tb1;"
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--special-op-name",
                                                              +    "op": {
                                                              +      "stmt": "select * from ks1.tb1;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "block0",
                                                              +      "name": "block0--special-op-name"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              map of op templates without explicit name

                                                              +

                                                              This yaml document contains a single named op template op1 which contains a scoped op op with +two op fields field1 and field2.

                                                              +

                                                              The op template takes its name op1 from the map key under the ops property.

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    op:
                                                              +      field1: select * from ks1.tb1;
                                                              +      field2: field 2 value
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "op": {
                                                              +        "field1": "select * from ks1.tb1;",
                                                              +        "field2": "field 2 value"
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "field1": "select * from ks1.tb1;",
                                                              +      "field2": "field 2 value"
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "block0",
                                                              +      "name": "block0--op1"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Op Fields

                                                              +

                                                              Anonymous fields go to op by default

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    field1: select * from ks1.tb1;
                                                              +    field2: field 2 value
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "field1": "select * from ks1.tb1;",
                                                              +      "field2": "field 2 value"
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "field1": "select * from ks1.tb1;",
                                                              +      "field2": "field 2 value"
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "block0",
                                                              +      "name": "block0--op1"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Anonymous fields may include scoped params

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    field1: select * from ks1.tb1;
                                                              +    field2: field 2 value
                                                              +    params:
                                                              +      paramname1: paramvalue1
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "field1": "select * from ks1.tb1;",
                                                              +      "field2": "field 2 value",
                                                              +      "params": {
                                                              +        "paramname1": "paramvalue1"
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "field1": "select * from ks1.tb1;",
                                                              +      "field2": "field 2 value"
                                                              +    },
                                                              +    params: {
                                                              +      "paramname1": "paramvalue1"
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "block0",
                                                              +      "name": "block0--op1"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Scoped op fields allow dangling param values

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    op:
                                                              +      field1: select * from ks1.tb1;
                                                              +      field2: field 2 value
                                                              +    paramname1: paramval1
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "op": {
                                                              +        "field1": "select * from ks1.tb1;",
                                                              +        "field2": "field 2 value"
                                                              +      },
                                                              +      "paramname1": "paramval1"
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "field1": "select * from ks1.tb1;",
                                                              +      "field2": "field 2 value"
                                                              +    },
                                                              +    "params": {
                                                              +      "paramname1": "paramval1"
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "block0",
                                                              +      "name": "block0--op1"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Scoped op and param fields disallow dangling fields

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    op:
                                                              +      field1: select * from ks1.tb1;
                                                              +      field2: field 2 value
                                                              +    params:
                                                              +      paramname1: paramval1
                                                              +#   dangling1: value
                                                              +#   ^ NOT ALLOWED HERE
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "op": {
                                                              +        "field1": "select * from ks1.tb1;",
                                                              +        "field2": "field 2 value"
                                                              +      },
                                                              +      "params": {
                                                              +        "paramname1": "paramval1"
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "field1": "select * from ks1.tb1;",
                                                              +      "field2": "field 2 value"
                                                              +    },
                                                              +    "params": {
                                                              +      "paramname1": "paramval1"
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "block0",
                                                              +      "name": "block0--op1"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              params at doc level

                                                              +

                                                              yaml:

                                                              +
                                                              params:
                                                              +  pname: pvalue
                                                              +ops: "my test op"
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "params": {
                                                              +    "pname": "pvalue"
                                                              +  },
                                                              +  "ops": "my test op"
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "params": {
                                                              +      "pname": "pvalue"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--stmt1",
                                                              +      "block": "block0"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "my test op"
                                                              +    },
                                                              +    "name": "block0--stmt1"
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              params at block level

                                                              +

                                                              yaml:

                                                              +
                                                              blocks:
                                                              +  block1:
                                                              +    params:
                                                              +      pname: pvalue
                                                              +    ops: "my test op"
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "blocks": {
                                                              +    "block1": {
                                                              +      "params": {
                                                              +        "pname": "pvalue"
                                                              +      },
                                                              +      "ops": "my test op"
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "params": {
                                                              +      "pname": "pvalue"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block1--stmt1",
                                                              +      "block": "block1"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "my test op"
                                                              +    },
                                                              +    "name": "block1--stmt1"
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              params at op level

                                                              +

                                                              yaml:

                                                              +
                                                              blocks:
                                                              +  block1:
                                                              +    ops:
                                                              +      op1:
                                                              +        op: "my test op"
                                                              +        params:
                                                              +          pname: pvalue
                                                              +
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "blocks": {
                                                              +    "block1": {
                                                              +      "ops": {
                                                              +        "op1": {
                                                              +          "op": "my test op",
                                                              +          "params": {
                                                              +            "pname": "pvalue"
                                                              +          }
                                                              +        }
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "params": {
                                                              +      "pname": "pvalue"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block1--op1",
                                                              +      "block": "block1"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "my test op"
                                                              +    },
                                                              +    "name": "block1--op1"
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              params field at op field level is not treated as special

                                                              +

                                                              When you put your params within the op fields by name, alongside the other op fields, it is not +treated specially. This is not disallowed, as there may be scenarios where this is otherwise a valid +value. Further, params within the op field would not provide any benefit over simply having those +named values in the op field directly, as this is consulted first for dynamic and static values.

                                                              +

                                                              yaml:

                                                              +
                                                              blocks:
                                                              +  block1:
                                                              +    ops:
                                                              +      op1:
                                                              +        op:
                                                              +          stmt: "my test op"
                                                              +          params:
                                                              +            pname: pvalue
                                                              +
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "blocks": {
                                                              +    "block1": {
                                                              +      "ops": {
                                                              +        "op1": {
                                                              +          "op": {
                                                              +            "stmt": "my test op",
                                                              +            "params": {
                                                              +              "pname": "pvalue"
                                                              +            }
                                                              +          }
                                                              +        }
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block1--op1",
                                                              +      "block": "block1"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "my test op",
                                                              +      "params": {
                                                              +        "pname": "pvalue"
                                                              +      }
                                                              +    },
                                                              +    "name": "block1--op1"
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              params field at op name level is not treated as special

                                                              +

                                                              When you are using map-based op template names, and one of them has a name of 'param', it is treated +just as any other op template name. The fields will not be recognized as param names and values, +but as op template fields.

                                                              +

                                                              yaml:

                                                              +
                                                              blocks:
                                                              +  block1:
                                                              +    ops:
                                                              +      op1:
                                                              +        op:
                                                              +          stmt: "my test op"
                                                              +      params:
                                                              +        pname: pvalue
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "blocks": {
                                                              +    "block1": {
                                                              +      "ops": {
                                                              +        "op1": {
                                                              +          "op": {
                                                              +            "stmt": "my test op"
                                                              +          }
                                                              +        },
                                                              +        "params": {
                                                              +          "pname": "pvalue"
                                                              +        }
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block1--op1",
                                                              +      "block": "block1"
                                                              +    },
                                                              +    "op": {
                                                              +      "stmt": "my test op"
                                                              +    },
                                                              +    "name": "block1--op1"
                                                              +  },
                                                              +  {
                                                              +    "tags": {
                                                              +      "name": "block1--params",
                                                              +      "block": "block1"
                                                              +    },
                                                              +    "op": {
                                                              +      "pname": "pvalue"
                                                              +    },
                                                              +    "name": "block1--params"
                                                              +  }
                                                              +]
                                                              +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/workload_definition/07-template-variables/index.html b/reference/workload_definition/07-template-variables/index.html new file mode 100644 index 000000000..dee5b5fde --- /dev/null +++ b/reference/workload_definition/07-template-variables/index.html @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + Template Variables | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Template Variables

                                                              +

                                                              Template variables allow for workload descriptions to be parameterized outside the structure of the +templating language.

                                                              +

                                                              Template variables are resolved in the workload after the on-disk format is loaded and before yaml parsing.

                                                              +

                                                              angle bracket value with defaults

                                                              +

                                                              yaml:

                                                              +
                                                              name: <<myname,thedefault>>
                                                              +desc: <<mydesc:mydescription>>
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +    "name": "thedefault",
                                                              +    "desc": "mydescription"
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +

                                                              It's easier on syntax checkers if you use this form.

                                                              +

                                                              call form with defaults

                                                              +

                                                              yaml:

                                                              +
                                                              name: TEMPLATE(myname,thedefault)
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +    "name": "thedefault"
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +

                                                              call form with no default, requires input

                                                              +

                                                              yaml:

                                                              +
                                                              name: TEMPLATE(myname)
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +    "name": "UNSET:myname"
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              +

                                                              call form with null default

                                                              +

                                                              yaml:

                                                              +
                                                              name: TEMPLATE(myname,)
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +    "name": null
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[]
                                                              +
                                                              + +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/workload_definition/08-parsed-op-api/index.html b/reference/workload_definition/08-parsed-op-api/index.html new file mode 100644 index 000000000..d7d9a51fc --- /dev/null +++ b/reference/workload_definition/08-parsed-op-api/index.html @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + ParsedOp API | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              ParsedOp API

                                                              +

                                                              In the workload template examples, we show statements as being formed from a string value. This is a +specific type of statement form, although it is possible to provide structured op templates as well.

                                                              +

                                                              The ParsedOp API is responsible for converting all valid op template forms into a consistent and +unambiguous model. Thus, the rules for mapping the various forms to the command model must be +precise. Those rules are the substance of this specification.

                                                              +

                                                              Op Synthesis

                                                              +

                                                              Executable operations are created on the fly by NoSQLBench via a process called Op Synthesis. +This is done incrementally in stages. The following narrative describes this process in logical +stages. (The implementation may vary from this, but it explains the effects, nonetheless.)

                                                              +

                                                              Everything here happens during activity initialization, before the activity starts running +cycles:

                                                              +
                                                                +
                                                              1. Template Variable Expansion - If there are template variables, such as +TEMPLATE(name,defaultval) or &lt;&lt;name:defaultval&gt;&gt;, then these are expanded +according to their defaults and any overrides provided in the activity params. This is a macro +substitution only, so the values are simply interposed into the character stream of the document.
                                                              2. +
                                                              3. Jsonnet Evaluation - If the source file was in jsonnet format (the extension was .jsonnet) +then it is interpreted by sjsonnet, with all activity parameters available as external variables.
                                                              4. +
                                                              5. Structural Normalization - The workload template (yaml, json, or data structure) is loaded +into memory and transformed into a standard format. This means taking various list and map +forms at every level and converting them to a singular standard form in memory.
                                                              6. +
                                                              7. Auto-Naming - All elements which do not already have a name are assigned a simple name like +block2 or op3.
                                                              8. +
                                                              9. Auto-Tagging - All op templates are given standard tag values under reserved tag names: +
                                                                  +
                                                                • block: the name of the block containing the op template. For example: block2.
                                                                • +
                                                                • name: the name of the op template, prefixed with the block value and --. For example, +block2--op1.
                                                                • +
                                                                +
                                                              10. +
                                                              11. Property De-normalization - Default values for all the standard op template properties are +copied from the doc to the block layer unless the same-named key exists. Then the same +method is applied from the doc layer to the op template layer. At this point, the op +templates are effectively an ordered list of data structures, each containing all necessary +details for use.
                                                              12. +
                                                              13. Tag Filtering - The activity's tag param is used to filter all the op templates +according to their tag map.
                                                              14. +
                                                              15. Bind Point and Capture Points - Each op template is now converted into a ParsedOp, which is +a swiss-army knife of op template introspection and function generation. It is the direct +programmatic API that driver adapters use in subsequent steps. +
                                                                  +
                                                                • Any string sequences with bind points like this has a {bindpoint} are automatically +converted to a long -> string function.
                                                                • +
                                                                • Any direct references with no surrounding text like {bindpoint} are automatically +converted to direct binding references.
                                                                • +
                                                                • Any other string form is cached as a static value.
                                                                • +
                                                                • The same process is applied to Lists and Maps, allowing structural templates which read +like JSON with bind points in arbitrary places.
                                                                • +
                                                                +
                                                              16. +
                                                              17. Op Mapping - Using the ParsedOp API, each op template is categorized by the active driver +according to that driver's documented examples and type-matching rules. Once the op mapper +determines what op type a user intended, it uses this information and the associated op +fields to create an Op Dispenser.
                                                              18. +
                                                              19. Op Sequencing - The op dispensers are kept as an internal sequence, and installed into a +LUT according to their ratios and the specified +(or default) sequencer. By default, round-robin with bucket exhaustion is used. The ratios +specified are used directly in the LUT.
                                                              20. +
                                                              +

                                                              When this is complete, you are left with an efficient lookup table which indexes into a set of +OpDispensers. The length of this lookup table is called the sequence length, and that value is +used, by default, to set the stride for the activity. This stride determines the size of +per-thread cycle batching, effectively turning each sequence into a thread-safe set of +operations which are serialized, and thus suitable for testing linearized operations with +suitable dependency and error-handling mechanisms. (But wait, there's more!)

                                                              +

                                                              Special Cases

                                                              +

                                                              Drivers are assigned to op templates individually, meaning you can specify the driver within an +op template, not even assigning a default for the activity. Further, certain drivers are able to +fill in missing details for op templates, like the stdout driver which only requires bindings.

                                                              +

                                                              This means that there are distinct cases for configuration which are valid, and these are +checked at initialization time:

                                                              +
                                                                +
                                                              • A driver must be selected for each op template either directly or via activity params.
                                                              • +
                                                              • If the whole workload template provided does not include actual op templates AND a +default driver is provided which can create synthetic op templates, it is given the raw +workload template, incomplete as it is, and asked to provide op templates which have all +normalization, naming, etc. already done. This is injected before the tag-filtering phase.
                                                              • +
                                                              • In any case that an actual non-zero list of op templates is provided and tag filtering removes +them all, an error is thrown.
                                                              • +
                                                              • If, after tag filtering no op template are in the active list, an error is thrown.
                                                              • +
                                                              +

                                                              The ParsedOp

                                                              +

                                                              The components of a fully-parsed op template (AKA a ParsedOp) are:

                                                              +

                                                              name

                                                              +

                                                              Each ParsedOp knows its name, which is simply the op template name that it was made from. This +is useful for diagnostics, logging, and metrics.

                                                              +

                                                              description

                                                              +

                                                              Every named element of a workload may be given a description.

                                                              +

                                                              tags

                                                              +

                                                              Every op template has tags, even if they are auto-assigned from the block and op template names. +If you assign explicit tags to an op template, the standard tags are still provided. Thus, it is +an error to directly provide a tag named block or name.

                                                              +

                                                              bindings

                                                              +

                                                              Although bindings are usually defined as workload template level property, they can also be +provided directly as an op field property.

                                                              +

                                                              op fields

                                                              +

                                                              The op property of an op template or ParsedOp is the root of the op fields. This is a map of +specific fields specified by the user.

                                                              +

                                                              static op fields

                                                              +

                                                              Some op fields are simply static values. Since these values are not generated per cycle, they are +kept separate as reference data. Knowing which fields are static and which are not makes it +possible for developers to optimize op synthesis.

                                                              +

                                                              dynamic op fields

                                                              +

                                                              Other fields may be specified as recipes, with the actual value to be filled-in once the cycle +value is known. All such fields are known as dynamic op fields, and are provided to the op +dispenser as a long function, where the input is always the cycle value and the output is a +type-specific value as determined by the associated binding recipe.

                                                              +

                                                              bind points

                                                              +

                                                              This is how dynamic values are indicated. Each bind point in an op template results in some type of +procedural generation binding. These can be references to named bindings elsewhere in the +workload template, or they can be inline.

                                                              +

                                                              capture points

                                                              +

                                                              Names of result values to save, and the variable names they are to be saved as. The names represent +the name as it would be found in the native driver's API, such as the name userid +in select userid from .... In string form statements, users can specify that the userid should be +saved as the thread-local variable named userid simply by tagging it +like select [userid] from .... They can also specify that this value should be captured under a +different name with a variation like select [userid as user_id] from .... This is the standard +variable capture syntax for any string-based statement form.

                                                              +

                                                              params

                                                              +

                                                              A backwards-compatible feature called op params is still available. This is another root +property within an op template which can be used to accessorize op fields. By default, any op +field which is not explicitly rooted under the op property are put there anyway. This is also +true when there is an explicitly params property. However if the op property is provided, then +all non-reserved fields are given to the params property instead. If both the op and the +param op properties are specified, then no non-reserved op fields are allowed outside of these +root values. Thus it is possible to still support params, but it is highly recommended that +new driver developers avoid using this field, and instead allow all fields to be automatically +anchored under the op property. This keeps configs terse and simple going forward.

                                                              +

                                                              Params may not be dynamic.

                                                              +

                                                              Mapping Rules

                                                              +

                                                              A ParsedOp does not necessarily describe a specific low-level operation to be performed by +a native driver. It should do so, but it is up to the user to provide a valid op template +according to the documented rules of op construction for that driver type. These rules should be +clearly documented by the driver developer as examples in markdown that is required for every +driver. With this documentation, users can use nb5 help &lt;driver&gt; to see exactly how +to create op templates for a given driver.

                                                              +

                                                              String Form

                                                              +

                                                              Basic operations are made from a statement in some type of query language:

                                                              +
                                                              ops:
                                                              +  - stringform: select [userid] from db.users where user='{username}';
                                                              +    bindings:
                                                              +      username: NumberNameToString()
                                                              +
                                                              +

                                                              Reserved op fields

                                                              +

                                                              The property names ratio, driver, space, are considered reserved by the NoSQLBench runtime. +These are extracted and handled specially by the core runtime.

                                                              +

                                                              Base OpDispenser fields

                                                              +

                                                              The BaseOpDispenser, which is will be required as the base implementation of any op +dispenser going forward, provides cross-cutting functionality. These include start-timers, +stop-timers, instrument, and likely will include more as future cross-driver functionality is +added. These fields will be considered reserved property names.

                                                              +

                                                              Optimization

                                                              +

                                                              It should be noted that the op mapping process, where user intentions are mapped from op templates to +op dispensers is not something that needs to be done quickly. This occurs at initialization +time. Instead, it is more important to focus on user experience factors, such as flexibility, +obviousness, robustness, correctness, and so on. Thus, priority of design factors in this part +of NB is placed more on clear and purposeful abstractions and less on optimizing for speed. The +clarity and detail which is conveyed by this layer to the driver developer will then enable +them to focus on building fast and correct op dispensers. These dispensers are also constructed +before the workload starts running, but are used at high speed while the workload is running.

                                                              +

                                                              In essence:

                                                              +
                                                                +
                                                              • Any initialization code which happens before or in the OpDispenser constructor should not be +concerned with careful performance optimization.
                                                              • +
                                                              • Any code which occurs within the OpDispenser#apply method should be as lightweight as is +reasonable.
                                                              • +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/reference/workload_definition/index.html b/reference/workload_definition/index.html new file mode 100644 index 000000000..665647717 --- /dev/null +++ b/reference/workload_definition/index.html @@ -0,0 +1,510 @@ + + + + + + + + + + + + + + + + Op Templates | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Op Templates

                                                              +

                                                              Op templates are the recipes provided by users for an operation. These hold examples of payload +data, metadata that configures the driver, timeout settings and so on.

                                                              +

                                                              The field name used in workload templates to represent operations can often be symbolic to users. +For this reason, several names are allowed: ops, op, operations, statements, statement. It doesn't +matter whether the value is provided as a map, list, or scalar. These all allow for the same +level of templating. Map forms are preferred, since they include naming in a more streamlined +structure. When you use list form, you have to provide the name as a separate field.

                                                              +

                                                              A name is automatically provided by the API when there is one missing.

                                                              +

                                                              a single un-named op template

                                                              +

                                                              yaml:

                                                              +
                                                              op: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "op": "select * from bar.table;"
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--stmt1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--stmt1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              un-named op templates as a list of strings

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    "select * from bar.table;"
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--stmt1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--stmt1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              named op templates as a list of maps with name-stmt as first entry

                                                              +

                                                              This form will take the first key and value of the map as the name and statement for the op +template.

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - op1: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    {
                                                              +      "op1": "select * from bar.table;"
                                                              +    }
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              op templates as a list of maps with name field

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  - name: op1
                                                              +    op: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": [
                                                              +    {
                                                              +      "name": "op1",
                                                              +      "op": "select * from bar.table;"
                                                              +    }
                                                              +  ]
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              named op templates as a map of strings

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": "select * from bar.table;"
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              named op templates as a map of maps

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    stmt: select * from bar.table;
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "name": "block0--op1",
                                                              +    "op": {
                                                              +      "stmt": "select * from bar.table;"
                                                              +    },
                                                              +    "tags": {
                                                              +      "name": "block0--op1",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Op Template Properties

                                                              +

                                                              All the forms above merely show how you can structure op templates into common collection forms and +have them be interpreted in a flexible yet obvious way.

                                                              +

                                                              However, all the properties described in templated_workloads.md +can be attached directly to op templates too. This section contains a few examples to illustrate +this at work.

                                                              +

                                                              detailed op template example

                                                              +

                                                              yaml:

                                                              +
                                                              ops:
                                                              +  op1:
                                                              +    name: special-op-name
                                                              +    op: select * from ks1.tb1;
                                                              +    bindings:
                                                              +      binding1: NumberNameToString();
                                                              +    tags:
                                                              +      block: schema
                                                              +    params:
                                                              +      prepared: false
                                                              +    description: This is just an example operation
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "ops": {
                                                              +    "op1": {
                                                              +      "bindings": {
                                                              +        "binding1": "NumberNameToString();"
                                                              +      },
                                                              +      "description": "This is just an example operation",
                                                              +      "name": "special-op-name",
                                                              +      "op": "select * from ks1.tb1;",
                                                              +      "params": {
                                                              +        "prepared": false
                                                              +      },
                                                              +      "tags": {
                                                              +        "block": "schema"
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "bindings": {
                                                              +      "binding1": "NumberNameToString();"
                                                              +    },
                                                              +    "description": "This is just an example operation",
                                                              +    "name": "block0--special-op-name",
                                                              +    "op": {
                                                              +      "stmt": "select * from ks1.tb1;"
                                                              +    },
                                                              +    "params": {
                                                              +      "prepared": false
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "schema",
                                                              +      "name": "block0--special-op-name",
                                                              +      "block": "block0"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              +

                                                              Property Layering

                                                              +

                                                              Properties that are provided at the top (doc) level become defaults for each nested layer (block or +ops). Each named binding, param, or tag is automatically assigned to any contained layers which do +not have one of the same name. When two layers contain the same named binding, param or tag, the +inner-most scope decides the value seen at the op level.

                                                              +

                                                              block-level defaults and overrides

                                                              +

                                                              yaml:

                                                              +
                                                              tags:
                                                              +  docleveltag: is-tagging-everything # applies to all operations in this case
                                                              +
                                                              +bindings:
                                                              +  binding1: Identity(); # will be overridden at the block level
                                                              +
                                                              +params:
                                                              +  prepared: true # set prepared true by default for all contained op templates
                                                              +
                                                              +blocks:
                                                              +  block-named-fred:
                                                              +    bindings:
                                                              +      binding1: NumberNameToString();
                                                              +    tags:
                                                              +      block: schema
                                                              +    params:
                                                              +      prepared: false
                                                              +    description: This is just an example operation
                                                              +    ops:
                                                              +      op1:
                                                              +        name: special-op-name
                                                              +        op: select * from ks1.tb1;
                                                              +
                                                              +
                                                              +

                                                              json:

                                                              +
                                                              
                                                              +{
                                                              +  "tags": {
                                                              +    "docleveltag": "is-tagging-everything"
                                                              +  },
                                                              +  "bindings": {
                                                              +    "binding1": "Identity();"
                                                              +  },
                                                              +  "params": {
                                                              +    "prepared": true
                                                              +  },
                                                              +  "blocks": {
                                                              +    "block-named-fred": {
                                                              +      "bindings": {
                                                              +        "binding1": "NumberNameToString();"
                                                              +      },
                                                              +      "description": "This is just an example operation",
                                                              +      "params": {
                                                              +        "prepared": false
                                                              +      },
                                                              +      "tags": {
                                                              +        "block": "schema"
                                                              +      },
                                                              +      "ops": {
                                                              +        "op1": {
                                                              +          "name": "special-op-name",
                                                              +          "op": "select * from ks1.tb1;"
                                                              +        }
                                                              +      }
                                                              +    }
                                                              +  }
                                                              +}
                                                              +
                                                              +

                                                              ops:

                                                              +
                                                              
                                                              +[
                                                              +  {
                                                              +    "bindings": {
                                                              +      "binding1": "NumberNameToString();"
                                                              +    },
                                                              +    "name": "block-named-fred--special-op-name",
                                                              +    "op": {
                                                              +      "stmt": "select * from ks1.tb1;"
                                                              +    },
                                                              +    "params": {
                                                              +      "prepared": false
                                                              +    },
                                                              +    "tags": {
                                                              +      "block": "schema",
                                                              +      "docleveltag": "is-tagging-everything",
                                                              +      "name": "block-named-fred--special-op-name",
                                                              +      "block": "block-named-fred"
                                                              +    }
                                                              +  }
                                                              +]
                                                              +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/release-notes/index.html b/release-notes/index.html new file mode 100644 index 000000000..3223cac51 --- /dev/null +++ b/release-notes/index.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + What's New - NB5 | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Updates in Progress

                                                              +

                                                              👉 The docs are presently updated to support NoSQLBench v5.17. 👈

                                                              +

                                                              Welcome to NB5! This release represents a massive leap forward. There are so many improvements +that should have gone into smaller releases along the way, but here we are. We've had our heads +down, focusing on new APIs, porting drivers, and fixing bugs, but it's time to talk about the +new stuff!

                                                              +

                                                              For those who are experienced NB5 users, this will have few (but some!) surprises. For +those of you who are NB (4 or earlier) users, NB5 is a whole different kind of testing tool. The +changes allow for a much more streamlined user and developer experience, while also offering +additional capabilities never seen together in a systems testing tool.

                                                              +

                                                              Everything mentioned here will find its way into the main docs site before were done.

                                                              +

                                                              We've taken some care to make sure that there is support for earlier workloads where at all +possible. If we've missed something critical, please let us know, and we'll patch it up ASAP.

                                                              +

                                                              This is a narrative overview of changes for NB5 in general. Individual +releases will have itemized code changes +listed individually.

                                                              +

                                                              Artifacts

                                                              +

                                                              nb5

                                                              +

                                                              The main bundled artifact is now named nb5. This version of NoSQLBench is a +significant departure from the previous limitations and conventions, so a new name was fitting. +It also allows you to easily have both on your system if you are maintaining test harnesses. +This is a combination of the NoSQLBench core runtime module nbr and all the bundled driver +adapters which have been contributed to the project.

                                                              +

                                                              Packaging

                                                              +

                                                              The code base for nb5 is more modular and adaptable. The core runtime module nbr is now +separate, including only the core diagnostic driver which is used in integration tests. This allows +for leaner and meaner integration tests.

                                                              +

                                                              drivers

                                                              +

                                                              We've ported many drivers to the nb5 APIs. All CQL support is now being provided by +Datastax Java Driver for Apache Cassandra. +In addition, multiple contributors are stepping up to provide new drivers for many systems +across the NoSQL ecosystem.

                                                              +

                                                              Project

                                                              +

                                                              Significant changes were made for the benefit of both users and developers.

                                                              +

                                                              Team

                                                              +

                                                              We've expanded the developer team which maintains tools like NoSQLBench. This should allow us to +make improvements faster, focus on users more, and bring more strategic capabilities to the project +which can redefine how advanced testing is done.

                                                              +

                                                              WYSiWYG Docs

                                                              +

                                                              We've connected the integration and specification tests to the documentation in a way that +ties examples everything together. If the examples and integration tests that are used on this +site fail, the build fails. Otherwise, the most recent examples are auto exported from the main +code base to the docs site. This means that test coverage will improve examples in the docs, +which will stay constantly up to date. Expect coverage of this method to improve with each +release. Until we can say What You See Is What You Get across all nb5 functions and examples, +we're not done yet.

                                                              +

                                                              Releases

                                                              +

                                                              Going forward we'll enforce stricter release criteria. Interim releases will be flagged as +prerelease unless due diligence checks have been done and a peer review finds a prerelease +suitable for promotion to a main release. Once flagged as a normal release, CI/CD tools can pick +up the release from the github releases area automatically.

                                                              +

                                                              We have a set of release criteria which will be published to this site and used as a blueprint for +releases going forward. More information on how releases are managed can be found in our +Contributing section. This will include testing coverage, +static +analysis, and further integrated testing support.

                                                              +

                                                              Documentation

                                                              +

                                                              This doc site is a significant step up from the previous version. It is now more accessible, +more standards compliant, and generally more user-friendly. The dark theme is highly usable. +Syntax highlighting is much easier on the eyes, and page navigation works better! The starting +point for this site was provided by the abridge theme by +Jieiku.

                                                              +

                                                              Architecture

                                                              +

                                                              The impetus for a major new version of NoSQLBench came from user and developer needs. In +order to provide a consistent user experience across a variety of testing needs, the core +machinery needed an upgrade. The APIs for building drivers and features have been redesigned to +this end, resulting in a vast improvement for all who use or maintain nb5 core or drivers.

                                                              +

                                                              These benefits include:

                                                              +
                                                                +
                                                              • Vastly simplified driver contributor experience
                                                              • +
                                                              • Common features across all implemented DriverAdapters
                                                              • +
                                                              • Interoperability between drivers in the same scenario or activity
                                                              • +
                                                              • Standard core activity params across all drivers, like op=...
                                                              • +
                                                              • Standard metrics semantics across all drivers
                                                              • +
                                                              • Standard highly configurable error handler support
                                                              • +
                                                              • Standard op template features, like named start and stop timers
                                                              • +
                                                              • Standard diagnostic tools across all drivers, like dryrun=...
                                                              • +
                                                              +

                                                              The amount of Standard you see in this list is directly related to the burden removed from +both nb5 users and project contributors.

                                                              +

                                                              Some highlights of these will be described below, with more details in the user guide.

                                                              +
                                                                +
                                                              • The error handlers mechanism is now fully generalized across all +drivers. +It is also chainable, with specific support for handling each error type with a specific chain of +handlers, or +simply assigning a default to all of them as before.
                                                              • +
                                                              • The rate limiter is more efficient. This should allow it to work better in some scenarios +where inter-core contention was a limiting factor.
                                                              • +
                                                              • It is now possible to dry-run an activity with dryrun=op or similar. Each dryrun option goes +a little further into a normal run so that incremental verification of workloads can be done. +For example, the dryrun=op option uses all the logic of a normal execution, but it wraps +the op implementation in a no-op. The results of this will tell you how fast the client can +synthesize and dispatch operations when there is no op execution involved. The measurement +will be conservative due to the extra wrapping layer.
                                                              • +
                                                              • Thread management within activities is now more efficient, more consistent, and more real-time. +Polling calls were replaced with evented calls where possible.
                                                              • +
                                                              • Only op templates which are active (selected and have a positive ratio) are resolved at +activity initialization. This improves startup times for large workload with subsets of +operations enabled.
                                                              • +
                                                              • Native drivers (like the CQL Java Driver) now have their driver instance and object graph +cached, indexed by a named op field called space. By default, this is wired to return +default, thus each unique adapter will use the same internal object graph for execution. +This is how things worked for most drivers before. However, if the user specifies that the +space should vary, then they simply assign it a binding. This allows for advanced driver +testing across a number of client instances, either pseudo-randomly or in lock-step with +specific access patterns. If you don't want to use this, then ignore it and everything works +as it did before. But if you do, this is built-in to every driver by design.
                                                              • +
                                                              • The activity parameter driver simply sets the default adapter for an activity. You can set +this per op template, and run a different driver for every cycle. This field must be static on +each op template, however. This allows for mixed-mode workloads in the same op sequence.
                                                              • +
                                                              • Adapters can be loaded from external jars. This can help users who are building adapters and want +to avoid building the full runtime just for iterative testing.
                                                              • +
                                                              • The phase loop has been removed.
                                                              • +
                                                              • Operations can now generate more operations associated with a cycle. This opens the door to
                                                              • +
                                                              • There is a distinct API for implementing dynamic activity params distinctly from +initialization params.
                                                              • +
                                                              +

                                                              Ergonomics

                                                              +

                                                              Console

                                                              +
                                                                +
                                                              • ANSI color support in some places, such as in console logging patterns. The --ansi and +--console-pattern and --logging-pattern options work together. If a non-terminal is +detected on stdout, ANSI is automatically disabled.
                                                              • +
                                                              • The progress meter has been modified to show real-time, accurate, detailed numbers +including operations in flight.
                                                              • +
                                                              +

                                                              Discovery

                                                              +
                                                                +
                                                              • Discovery of bundled assets is now more consistent, supported with a family of --list-... +options.
                                                              • +
                                                              +

                                                              Configuration

                                                              +
                                                                +
                                                              • Drivers know what parameters they can be configured with. This allows for more +intelligent and useful feedback to users around appropriate parameter usage. If you get a +param name wrong, nb5 will likely suggest the next closest option.
                                                              • +
                                                              • S3 Urls should work in most places, including for loading workload templates. You only need to +configure your local authentication first.
                                                              • +
                                                              +

                                                              Templating

                                                              +

                                                              Much of the power of NB5 is illustrated in the new ways you can template workloads. This +includes structured data, dynamic op configuration, and driver instancing, to name a few.

                                                              +
                                                                +
                                                              • The structure of op templates (the YAML you write to simulate access patterns) has been +standardized around a strict set of specification tests and examples. These are documented +in-depth and tested against a specification with round-trip validation.
                                                              • +
                                                              • Now, JSON and Jsonnet are supported directly as workload template formats. Jsonnet allows you to +see the activity params as external variables.
                                                              • +
                                                              • All workload template structure is now supported as maps, in addition to the other structural +forms (previously called workload YAMLs). All of these forms automatically de-sugar into the +canonical forms for the runtime to use. This follows the previous pattern of "If it does what +it looks like, it is valid", but further allows simplification of workloads with inline +naming of elements.
                                                              • +
                                                              • In addition to workload template structure, op templates also support arbitrary structure +instead of just scalar or String values. This is especially useful for JSON payload modeling. +This means that op templates now have a generalized templating mechanism that works for all +data structures. You can reference bindings as before, but you can also create collections and +string templates by writing fields as they naturally occur, then adding {bindings} where you +need.
                                                              • +
                                                              • All op template fields can be made dynamic if an adapter supports it. It is up to the adapter +implementor to decide which op fields must be static.
                                                              • +
                                                              • Op template values auto-defer to configured values as static, then dynamic, and then +configured from activity parameters as defaults. If an adapter supports a parameter at the +activity level, and an op form supports the same field, then this occurs automatically.
                                                              • +
                                                              • Tags for basic workload template elements are provided gratis. You no longer need to specify the +conventional tags. All op templates now have block: <blockname> and name: <blockname>--<name> tags added. This works with regexes in tag filtering.
                                                              • +
                                                              • Named scenarios now allow for nb5 <workload-file> <scenario-name>.<scenario-step> .... You can +prototype and validate complex scenarios by sub-selecting the steps to execute.
                                                              • +
                                                              • You can use the op="..." activity parameter to specific a single-op workload on the +command line, as if you had read it from a workload YAML. This allows +for one-liner tests streamlined integration, and other simple utility usage.
                                                              • +
                                                              • Binding recipes can now occur inline, as {{Identity()}}. This works with the op +parameter above.
                                                              • +
                                                              • You can now set a minimum version of NoSQLBench to use for a workload. The min_version: "4.17. 15" property is checked starting from the most-significant number down. If there are new core +features that your workload depends on, you can use this to avoid ambiguous errors.
                                                              • +
                                                              • Template vars like <<name:value>> or TEMPLATE(name,value) can set defaults the first time they +are seen. This means you don't have to update them everywhere. A nice way to handle this is to +include them in the description once, since you should be documenting them anyway!
                                                              • +
                                                              • You can load JSON files directly. You can also load JSONNET files directly! If you need to +sanity check your jsonnet rendering, you can use dryrun=jsonnet.
                                                              • +
                                                              • All workload template elements can have a description.
                                                              • +
                                                              +

                                                              Misc Improvements

                                                              +

                                                              (some carry over from pre-nb5 features)

                                                              +
                                                                +
                                                              • Argsfile support for allowing sticky parameters on a system.
                                                              • +
                                                              • Tag filters are more expressive, with regexes and conjunctions.
                                                              • +
                                                              • Some scenario commands now allow for regex-style globbing on activity alias names.
                                                              • +
                                                              • Startup logging now includes details on version, hardware config, and scenario commands for +better diagnostics and bug reports.
                                                              • +
                                                              • The logging subsystem config is improved and standardized across the project.
                                                              • +
                                                              • Test output is now vectored exclusively through logging config.
                                                              • +
                                                              • Analysis methods are improved and more widely used.
                                                              • +
                                                              +

                                                              Deprecations and Standards

                                                              +
                                                                +
                                                              • NB5 depends on Java 17. Going forward, major versions will adopt the latest LTS java release.
                                                              • +
                                                              • Dependencies which require shading in order to play well with others are not supported. If you +have a native driver or need to depend on a library which is not a good citizen, you can only +use it with NB5 by using the external jar feature (explained elsewhere). This includes the +previous CQL drivers which were the 1.9.* and 3.*.* version. Only CQL driver 4.* is +provided in nb5.
                                                              • +
                                                              • Dependencies should behave as modular jars, according to JPMS specification. This does not +mean they need to be JPMS modules, only that the get halfway there.
                                                              • +
                                                              • Log4J2 is the standard logging provider in the runtime for NoSQLBench. An SLF4J stub +implementation is provided to allow clients which implement against the SLF4J API to work.
                                                              • +
                                                              • All new drivers added to the project are based on the Adapter API.
                                                              • +
                                                              +

                                                              Works In Progress

                                                              +
                                                                +
                                                              • These docs!
                                                              • +
                                                              • Bulk Loading efficiency for large tests
                                                              • +
                                                              • Linearized Op Modeling +
                                                                  +
                                                                • We now have a syntax for designating fields to extract from op results. This is part of the +support needed to make client-side joins and other patterns easy to emulate.
                                                                • +
                                                                +
                                                              • +
                                                              • Rate Limiter v3
                                                              • +
                                                              • VictoriaMetrics Integration +
                                                                  +
                                                                • Labeled metrics need to be fed to a victoria metrics docker via push. This approach will +remove much of the pain involved in using prometheus as an ephemeral testing apparatus.
                                                                • +
                                                                +
                                                              • +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/release-notes/whatsnew-v5/index.html b/release-notes/whatsnew-v5/index.html new file mode 100644 index 000000000..23bd003da --- /dev/null +++ b/release-notes/whatsnew-v5/index.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + What's New - NB5 | NoSQLBench Project (BUILD) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                              + +
                                                              +
                                                              + + + + + + + + +
                                                              + +

                                                              Updates in Progress

                                                              +

                                                              👉 The docs are presently updated to support NoSQLBench v5.17. 👈

                                                              +

                                                              Welcome to NB5! This release represents a massive leap forward. There are so many improvements +that should have gone into smaller releases along the way, but here we are. We've had our heads +down, focusing on new APIs, porting drivers, and fixing bugs, but it's time to talk about the +new stuff!

                                                              +

                                                              For those who are experienced NB5 users, this will have few (but some!) surprises. For +those of you who are NB (4 or earlier) users, NB5 is a whole different kind of testing tool. The +changes allow for a much more streamlined user and developer experience, while also offering +additional capabilities never seen together in a systems testing tool.

                                                              +

                                                              Everything mentioned here will find its way into the main docs site before were done.

                                                              +

                                                              We've taken some care to make sure that there is support for earlier workloads where at all +possible. If we've missed something critical, please let us know, and we'll patch it up ASAP.

                                                              +

                                                              This is a narrative overview of changes for NB5 in general. Individual +releases will have itemized code changes +listed individually.

                                                              +

                                                              Artifacts

                                                              +

                                                              nb5

                                                              +

                                                              The main bundled artifact is now named nb5. This version of NoSQLBench is a +significant departure from the previous limitations and conventions, so a new name was fitting. +It also allows you to easily have both on your system if you are maintaining test harnesses. +This is a combination of the NoSQLBench core runtime module nbr and all the bundled driver +adapters which have been contributed to the project.

                                                              +

                                                              Packaging

                                                              +

                                                              The code base for nb5 is more modular and adaptable. The core runtime module nbr is now +separate, including only the core diagnostic driver which is used in integration tests. This allows +for leaner and meaner integration tests.

                                                              +

                                                              drivers

                                                              +

                                                              We've ported many drivers to the nb5 APIs. All CQL support is now being provided by +Datastax Java Driver for Apache Cassandra. +In addition, multiple contributors are stepping up to provide new drivers for many systems +across the NoSQL ecosystem.

                                                              +

                                                              Project

                                                              +

                                                              Significant changes were made for the benefit of both users and developers.

                                                              +

                                                              Team

                                                              +

                                                              We've expanded the developer team which maintains tools like NoSQLBench. This should allow us to +make improvements faster, focus on users more, and bring more strategic capabilities to the project +which can redefine how advanced testing is done.

                                                              +

                                                              WYSiWYG Docs

                                                              +

                                                              We've connected the integration and specification tests to the documentation in a way that +ties examples everything together. If the examples and integration tests that are used on this +site fail, the build fails. Otherwise, the most recent examples are auto exported from the main +code base to the docs site. This means that test coverage will improve examples in the docs, +which will stay constantly up to date. Expect coverage of this method to improve with each +release. Until we can say What You See Is What You Get across all nb5 functions and examples, +we're not done yet.

                                                              +

                                                              Releases

                                                              +

                                                              Going forward we'll enforce stricter release criteria. Interim releases will be flagged as +prerelease unless due diligence checks have been done and a peer review finds a prerelease +suitable for promotion to a main release. Once flagged as a normal release, CI/CD tools can pick +up the release from the github releases area automatically.

                                                              +

                                                              We have a set of release criteria which will be published to this site and used as a blueprint for +releases going forward. More information on how releases are managed can be found in our +Contributing section. This will include testing coverage, +static +analysis, and further integrated testing support.

                                                              +

                                                              Documentation

                                                              +

                                                              This doc site is a significant step up from the previous version. It is now more accessible, +more standards compliant, and generally more user-friendly. The dark theme is highly usable. +Syntax highlighting is much easier on the eyes, and page navigation works better! The starting +point for this site was provided by the abridge theme by +Jieiku.

                                                              +

                                                              Architecture

                                                              +

                                                              The impetus for a major new version of NoSQLBench came from user and developer needs. In +order to provide a consistent user experience across a variety of testing needs, the core +machinery needed an upgrade. The APIs for building drivers and features have been redesigned to +this end, resulting in a vast improvement for all who use or maintain nb5 core or drivers.

                                                              +

                                                              These benefits include:

                                                              +
                                                                +
                                                              • Vastly simplified driver contributor experience
                                                              • +
                                                              • Common features across all implemented DriverAdapters
                                                              • +
                                                              • Interoperability between drivers in the same scenario or activity
                                                              • +
                                                              • Standard core activity params across all drivers, like op=...
                                                              • +
                                                              • Standard metrics semantics across all drivers
                                                              • +
                                                              • Standard highly configurable error handler support
                                                              • +
                                                              • Standard op template features, like named start and stop timers
                                                              • +
                                                              • Standard diagnostic tools across all drivers, like dryrun=...
                                                              • +
                                                              +

                                                              The amount of Standard you see in this list is directly related to the burden removed from +both nb5 users and project contributors.

                                                              +

                                                              Some highlights of these will be described below, with more details in the user guide.

                                                              +
                                                                +
                                                              • The error handlers mechanism is now fully generalized across all +drivers. +It is also chainable, with specific support for handling each error type with a specific chain of +handlers, or +simply assigning a default to all of them as before.
                                                              • +
                                                              • The rate limiter is more efficient. This should allow it to work better in some scenarios +where inter-core contention was a limiting factor.
                                                              • +
                                                              • It is now possible to dry-run an activity with dryrun=op or similar. Each dryrun option goes +a little further into a normal run so that incremental verification of workloads can be done. +For example, the dryrun=op option uses all the logic of a normal execution, but it wraps +the op implementation in a no-op. The results of this will tell you how fast the client can +synthesize and dispatch operations when there is no op execution involved. The measurement +will be conservative due to the extra wrapping layer.
                                                              • +
                                                              • Thread management within activities is now more efficient, more consistent, and more real-time. +Polling calls were replaced with evented calls where possible.
                                                              • +
                                                              • Only op templates which are active (selected and have a positive ratio) are resolved at +activity initialization. This improves startup times for large workload with subsets of +operations enabled.
                                                              • +
                                                              • Native drivers (like the CQL Java Driver) now have their driver instance and object graph +cached, indexed by a named op field called space. By default, this is wired to return +default, thus each unique adapter will use the same internal object graph for execution. +This is how things worked for most drivers before. However, if the user specifies that the +space should vary, then they simply assign it a binding. This allows for advanced driver +testing across a number of client instances, either pseudo-randomly or in lock-step with +specific access patterns. If you don't want to use this, then ignore it and everything works +as it did before. But if you do, this is built-in to every driver by design.
                                                              • +
                                                              • The activity parameter driver simply sets the default adapter for an activity. You can set +this per op template, and run a different driver for every cycle. This field must be static on +each op template, however. This allows for mixed-mode workloads in the same op sequence.
                                                              • +
                                                              • Adapters can be loaded from external jars. This can help users who are building adapters and want +to avoid building the full runtime just for iterative testing.
                                                              • +
                                                              • The phase loop has been removed.
                                                              • +
                                                              • Operations can now generate more operations associated with a cycle. This opens the door to
                                                              • +
                                                              • There is a distinct API for implementing dynamic activity params distinctly from +initialization params.
                                                              • +
                                                              +

                                                              Ergonomics

                                                              +

                                                              Console

                                                              +
                                                                +
                                                              • ANSI color support in some places, such as in console logging patterns. The --ansi and +--console-pattern and --logging-pattern options work together. If a non-terminal is +detected on stdout, ANSI is automatically disabled.
                                                              • +
                                                              • The progress meter has been modified to show real-time, accurate, detailed numbers +including operations in flight.
                                                              • +
                                                              +

                                                              Discovery

                                                              +
                                                                +
                                                              • Discovery of bundled assets is now more consistent, supported with a family of --list-... +options.
                                                              • +
                                                              +

                                                              Configuration

                                                              +
                                                                +
                                                              • Drivers know what parameters they can be configured with. This allows for more +intelligent and useful feedback to users around appropriate parameter usage. If you get a +param name wrong, nb5 will likely suggest the next closest option.
                                                              • +
                                                              • S3 Urls should work in most places, including for loading workload templates. You only need to +configure your local authentication first.
                                                              • +
                                                              +

                                                              Templating

                                                              +

                                                              Much of the power of NB5 is illustrated in the new ways you can template workloads. This +includes structured data, dynamic op configuration, and driver instancing, to name a few.

                                                              +
                                                                +
                                                              • The structure of op templates (the YAML you write to simulate access patterns) has been +standardized around a strict set of specification tests and examples. These are documented +in-depth and tested against a specification with round-trip validation.
                                                              • +
                                                              • Now, JSON and Jsonnet are supported directly as workload template formats. Jsonnet allows you to +see the activity params as external variables.
                                                              • +
                                                              • All workload template structure is now supported as maps, in addition to the other structural +forms (previously called workload YAMLs). All of these forms automatically de-sugar into the +canonical forms for the runtime to use. This follows the previous pattern of "If it does what +it looks like, it is valid", but further allows simplification of workloads with inline +naming of elements.
                                                              • +
                                                              • In addition to workload template structure, op templates also support arbitrary structure +instead of just scalar or String values. This is especially useful for JSON payload modeling. +This means that op templates now have a generalized templating mechanism that works for all +data structures. You can reference bindings as before, but you can also create collections and +string templates by writing fields as they naturally occur, then adding {bindings} where you +need.
                                                              • +
                                                              • All op template fields can be made dynamic if an adapter supports it. It is up to the adapter +implementor to decide which op fields must be static.
                                                              • +
                                                              • Op template values auto-defer to configured values as static, then dynamic, and then +configured from activity parameters as defaults. If an adapter supports a parameter at the +activity level, and an op form supports the same field, then this occurs automatically.
                                                              • +
                                                              • Tags for basic workload template elements are provided gratis. You no longer need to specify the +conventional tags. All op templates now have block: <blockname> and name: <blockname>--<name> tags added. This works with regexes in tag filtering.
                                                              • +
                                                              • Named scenarios now allow for nb5 <workload-file> <scenario-name>.<scenario-step> .... You can +prototype and validate complex scenarios by sub-selecting the steps to execute.
                                                              • +
                                                              • You can use the op="..." activity parameter to specific a single-op workload on the +command line, as if you had read it from a workload YAML. This allows +for one-liner tests streamlined integration, and other simple utility usage.
                                                              • +
                                                              • Binding recipes can now occur inline, as {{Identity()}}. This works with the op +parameter above.
                                                              • +
                                                              • You can now set a minimum version of NoSQLBench to use for a workload. The min_version: "4.17. 15" property is checked starting from the most-significant number down. If there are new core +features that your workload depends on, you can use this to avoid ambiguous errors.
                                                              • +
                                                              • Template vars like <<name:value>> or TEMPLATE(name,value) can set defaults the first time they +are seen. This means you don't have to update them everywhere. A nice way to handle this is to +include them in the description once, since you should be documenting them anyway!
                                                              • +
                                                              • You can load JSON files directly. You can also load JSONNET files directly! If you need to +sanity check your jsonnet rendering, you can use dryrun=jsonnet.
                                                              • +
                                                              • All workload template elements can have a description.
                                                              • +
                                                              +

                                                              Misc Improvements

                                                              +

                                                              (some carry over from pre-nb5 features)

                                                              +
                                                                +
                                                              • Argsfile support for allowing sticky parameters on a system.
                                                              • +
                                                              • Tag filters are more expressive, with regexes and conjunctions.
                                                              • +
                                                              • Some scenario commands now allow for regex-style globbing on activity alias names.
                                                              • +
                                                              • Startup logging now includes details on version, hardware config, and scenario commands for +better diagnostics and bug reports.
                                                              • +
                                                              • The logging subsystem config is improved and standardized across the project.
                                                              • +
                                                              • Test output is now vectored exclusively through logging config.
                                                              • +
                                                              • Analysis methods are improved and more widely used.
                                                              • +
                                                              +

                                                              Deprecations and Standards

                                                              +
                                                                +
                                                              • NB5 depends on Java 17. Going forward, major versions will adopt the latest LTS java release.
                                                              • +
                                                              • Dependencies which require shading in order to play well with others are not supported. If you +have a native driver or need to depend on a library which is not a good citizen, you can only +use it with NB5 by using the external jar feature (explained elsewhere). This includes the +previous CQL drivers which were the 1.9.* and 3.*.* version. Only CQL driver 4.* is +provided in nb5.
                                                              • +
                                                              • Dependencies should behave as modular jars, according to JPMS specification. This does not +mean they need to be JPMS modules, only that the get halfway there.
                                                              • +
                                                              • Log4J2 is the standard logging provider in the runtime for NoSQLBench. An SLF4J stub +implementation is provided to allow clients which implement against the SLF4J API to work.
                                                              • +
                                                              • All new drivers added to the project are based on the Adapter API.
                                                              • +
                                                              +

                                                              Works In Progress

                                                              +
                                                                +
                                                              • These docs!
                                                              • +
                                                              • Bulk Loading efficiency for large tests
                                                              • +
                                                              • Linearized Op Modeling +
                                                                  +
                                                                • We now have a syntax for designating fields to extract from op results. This is part of the +support needed to make client-side joins and other patterns easy to emulate.
                                                                • +
                                                                +
                                                              • +
                                                              • Rate Limiter v3
                                                              • +
                                                              • VictoriaMetrics Integration +
                                                                  +
                                                                • Labeled metrics need to be fed to a victoria metrics docker via push. This approach will +remove much of the pain involved in using prometheus as an ephemeral testing apparatus.
                                                                • +
                                                                +
                                                              • +
                                                              + +

                                                              Back to top

                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +
                                                              + +

                                                              Copyright © 2023-2023 NoSQLBench Project (BUILD)

                                                              +
                                                              +
                                                              + + diff --git a/robots.txt b/robots.txt new file mode 100644 index 000000000..2a4c1eab2 --- /dev/null +++ b/robots.txt @@ -0,0 +1,4 @@ +Sitemap: https://builddocs.nosqlbench.io/sitemap.xml +User-Agent: * +Allow: / +Host: https://builddocs.nosqlbench.io diff --git a/safari-pinned-tab.svg b/safari-pinned-tab.svg new file mode 100644 index 000000000..31cf03f8d --- /dev/null +++ b/safari-pinned-tab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/search.js b/search.js new file mode 100644 index 000000000..61c67c097 --- /dev/null +++ b/search.js @@ -0,0 +1,343 @@ +// in page results when press enter or click search icon from search box +function closeSearchNow() { + const main = document.querySelector("main"); + main.innerHTML = window.main +} +function goSearchNow() { + const main = document.querySelector("main"); + if (!window.main) { + window.main = main.innerHTML + }; + var results = document.getElementById("suggestions");// suggestions div generated by search box + + var ResultsClone = results.cloneNode(true);// make a clone of the results, so that we can alter it + ResultsClone.id = "results";// alter the id of our clone, so that we can apply different css style + + var headerDiv = document.createElement("div");// create a div element + + var headerContent = '

                                                              Results For: '.concat(document.getElementById("searchinput").value, "

                                                              ");// header to use at top of results page + + headerDiv.innerHTML = headerContent;// document element div (headerDiv), set the inner contents to our header html (headerContent) + + ResultsClone.insertBefore(headerDiv, ResultsClone.firstChild);//insert our header div at the top of the page + + main.innerHTML = ResultsClone.outerHTML;//display ResultsClone.outerHTML as the page + results.innerHTML = "";// clear the suggestions div popup + document.getElementById("searchinput").value = "";// clear the search input box + document.body.contains(document.closeSearch) && (document.closeSearch.onsubmit = function() { closeSearchNow() }) + return false +} +window.onload = function() { + document.body.contains(document.goSearch) && (document.goSearch.onsubmit = function() { return goSearchNow() }) +}; + +// Everything Below this line For Suggestsions as you type in search box +var suggestions = document.getElementById("suggestions"); +var searchinput = document.getElementById("searchinput"); + +/* Close search suggestion popup list */ +function closeAllLists(elmnt) { + var suggestions = document.getElementById("suggestions"); + while (suggestions.firstChild) { + suggestions.removeChild(suggestions.firstChild); + } +} + +function inputFocus(e) { + + if (e.keyCode === 191//forward slash + && document.activeElement.tagName !== "INPUT" + && document.activeElement.tagName !== "TEXTAREA") { + e.preventDefault(); + searchinput.focus(); + suggestions.classList.remove('d-none'); + } + + if (e.keyCode === 27 ) {//escape + searchinput.blur(); + suggestions.classList.add('d-none'); + closeAllLists(); + } + + const focusableSuggestions= suggestions.querySelectorAll('a'); + if (suggestions.classList.contains('d-none') + || focusableSuggestions.length === 0) { + return; + } + const focusable= [...focusableSuggestions]; + const index = focusable.indexOf(document.activeElement); + + let nextIndex = 0; + + if (e.keyCode === 38) {//up arrow + e.preventDefault(); + nextIndex= index > 0 ? index-1 : 0; + focusableSuggestions[nextIndex].focus(); + } + else if (e.keyCode === 40) {//down arrow + e.preventDefault(); + nextIndex= index+1 < focusable.length ? index+1 : index; + focusableSuggestions[nextIndex].focus(); + } + +} + +document.addEventListener("keydown", inputFocus); +document.addEventListener("click", function(event) {suggestions.contains(event.target) || suggestions.classList.add("d-none")}); + +// Get substring by bytes +// If using JavaScript inline substring method, it will return error codes +// Source: https://www.52pojie.cn/thread-1059814-1-1.html +function substringByByte(str, maxLength) { + var result = ""; + var flag = false; + var len = 0; + var length = 0; + var length2 = 0; + for (var i = 0; i < str.length; i++) { + var code = str.codePointAt(i).toString(16); + if (code.length > 4) { + i++; + if ((i + 1) < str.length) { + flag = str.codePointAt(i + 1).toString(16) == "200d"; + } + } + if (flag) { + len += getByteByHex(code); + if (i == str.length - 1) { + length += len; + if (length <= maxLength) { + result += str.substr(length2, i - length2 + 1); + } else { + break + } + } + } else { + if (len != 0) { + length += len; + length += getByteByHex(code); + if (length <= maxLength) { + result += str.substr(length2, i - length2 + 1); + length2 = i + 1; + } else { + break + } + len = 0; + continue; + } + length += getByteByHex(code); + if (length <= maxLength) { + if (code.length <= 4) { + result += str[i] + } else { + result += str[i - 1] + str[i] + } + length2 = i + 1; + } else { + break + } + } + } + return result; +} + +// Get the string bytes from binary +function getByteByBinary(binaryCode) { + // Binary system, starts with `0b` in ES6 + // Octal number system, starts with `0` in ES5 and starts with `0o` in ES6 + // Hexadecimal, starts with `0x` in both ES5 and ES6 + var byteLengthDatas = [0, 1, 2, 3, 4]; + var len = byteLengthDatas[Math.ceil(binaryCode.length / 8)]; + return len; +} + +// Get the string bytes from hexadecimal +function getByteByHex(hexCode) { + return getByteByBinary(parseInt(hexCode, 16).toString(2)); +} + +/* +Source: + - https://github.com/nextapps-de/flexsearch#index-documents-field-search + - https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html + - http://elasticlunr.com/ + - https://github.com/getzola/zola/blob/master/docs/static/search.js + - https://github.com/aaranxu/adidoks/blob/main/static/js/search.js +*/ +(function(){ + var index = elasticlunr.Index.load(window.searchIndex); + searchinput.addEventListener('input', show_results, true); + suggestions.addEventListener('click', accept_suggestion, true); + + function show_results(){ + var value = this.value.trim(); + var options = { + bool: "OR", + fields: { + title: {boost: 2}, + body: {boost: 1}, + } + }; + var results = index.search(value, options); + + var entry, childs = suggestions.childNodes; + var i = 0, len = results.length; + var items = value.split(/\s+/); + suggestions.classList.remove('d-none'); + + results.forEach(function(page) { + if (page.doc.body !== '') { + entry = document.createElement('div'); + + entry.innerHTML = ''; + + a = entry.querySelector('a'), + t = entry.querySelector('span:first-child'), + d = entry.querySelector('span:nth-child(2)'); + a.href = page.ref; + t.textContent = page.doc.title; + d.innerHTML = makeTeaser(page.doc.body, items); + + suggestions.appendChild(entry); + } + }); + + while(childs.length > len){ + suggestions.removeChild(childs[i]) + } + + } + + function accept_suggestion(){ + + while(suggestions.lastChild){ + + suggestions.removeChild(suggestions.lastChild); + } + + return false; + } + + // Taken from mdbook + // The strategy is as follows: + // First, assign a value to each word in the document: + // Words that correspond to search terms (stemmer aware): 40 + // Normal words: 2 + // First word in a sentence: 8 + // Then use a sliding window with a constant number of words and count the + // sum of the values of the words within the window. Then use the window that got the + // maximum sum. If there are multiple maximas, then get the last one. + // Enclose the terms in . + function makeTeaser(body, terms) { + var TERM_WEIGHT = 40; + var NORMAL_WORD_WEIGHT = 2; + var FIRST_WORD_WEIGHT = 8; + var TEASER_MAX_WORDS = 30; + + var stemmedTerms = terms.map(function (w) { + return elasticlunr.stemmer(w.toLowerCase()); + }); + var termFound = false; + var index = 0; + var weighted = []; // contains elements of ["word", weight, index_in_document] + + // split in sentences, then words + var sentences = body.toLowerCase().split(". "); + for (var i in sentences) { + var words = sentences[i].split(/[\s\n]/); + var value = FIRST_WORD_WEIGHT; + for (var j in words) { + + var word = words[j]; + + if (word.length > 0) { + for (var k in stemmedTerms) { + if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) { + value = TERM_WEIGHT; + termFound = true; + } + } + weighted.push([word, value, index]); + value = NORMAL_WORD_WEIGHT; + } + + index += word.length; + index += 1; // ' ' or '.' if last word in sentence + } + + index += 1; // because we split at a two-char boundary '. ' + } + + if (weighted.length === 0) { + if (body.length !== undefined && body.length > TEASER_MAX_WORDS * 10) { + return body.substring(0, TEASER_MAX_WORDS * 10) + '...'; + } else { + return body; + } + } + + var windowWeights = []; + var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS); + // We add a window with all the weights first + var curSum = 0; + for (var i = 0; i < windowSize; i++) { + curSum += weighted[i][1]; + } + windowWeights.push(curSum); + + for (var i = 0; i < weighted.length - windowSize; i++) { + curSum -= weighted[i][1]; + curSum += weighted[i + windowSize][1]; + windowWeights.push(curSum); + } + + // If we didn't find the term, just pick the first window + var maxSumIndex = 0; + if (termFound) { + var maxFound = 0; + // backwards + for (var i = windowWeights.length - 1; i >= 0; i--) { + if (windowWeights[i] > maxFound) { + maxFound = windowWeights[i]; + maxSumIndex = i; + } + } + } + + var teaser = []; + var startIndex = weighted[maxSumIndex][2]; + for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) { + var word = weighted[i]; + if (startIndex < word[2]) { + // missing text from index to start of `word` + teaser.push(body.substring(startIndex, word[2])); + startIndex = word[2]; + } + + // add around search terms + if (word[1] === TERM_WEIGHT) { + teaser.push(""); + } + + startIndex = word[2] + word[0].length; + // Check the string is ascii characters or not + var re = /^[\x00-\xff]+$/ + if (word[1] !== TERM_WEIGHT && word[0].length >= 12 && !re.test(word[0])) { + // If the string's length is too long, it maybe a Chinese/Japance/Korean article + // if using substring method directly, it may occur error codes on emoji chars + var strBefor = body.substring(word[2], startIndex); + var strAfter = substringByByte(strBefor, 12); + teaser.push(strAfter); + } else { + teaser.push(body.substring(word[2], startIndex)); + } + + if (word[1] === TERM_WEIGHT) { + teaser.push(""); + } + } + teaser.push("…"); + return teaser.join(""); + } +document.body.contains(document.goSearch) && (document.goSearch.onsubmit = function() { return goSearchNow() }) +}()); diff --git a/search_bundle.min.js b/search_bundle.min.js new file mode 100644 index 000000000..4f68789ad --- /dev/null +++ b/search_bundle.min.js @@ -0,0 +1 @@ +function closeSearchNow(){const d=document.querySelector("main");d.innerHTML=window.main}function goSearchNow(){const d=document.querySelector("main");window.main||(window.main=d.innerHTML);var e=document.getElementById("suggestions"),o=e.cloneNode(!0),t=(o.id="results",document.createElement("div")),s='

                                                              Results For: '.concat(document.getElementById("searchinput").value,"

                                                              ");return t.innerHTML=s,o.insertBefore(t,o.firstChild),d.innerHTML=o.outerHTML,e.innerHTML="",document.getElementById("searchinput").value="",document.body.contains(document.closeSearch)&&(document.closeSearch.onsubmit=function(){closeSearchNow()}),!1}window.searchIndex={fields:["title","body"],pipeline:["trimmer","stopWordFilter","stemmer"],ref:"id",version:"0.9.5",index:{body:{root:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2},"https://abridge.netlify.app/overview-images/":{tf:6.557438524302}},df:2,c:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},1:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-images/":{tf:6},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:3,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"!":{docs:{},df:0,d:{docs:{},df:0,o:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,y:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}},".":{docs:{},df:0,8:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},0:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-images/":{tf:3.4641016151377544}},df:2,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}}},0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},6:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,1:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},t:{docs:{},df:0,a:{docs:{},df:0,x:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}},1:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-images/":{tf:2.6457513110645907}},df:2,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},1:{docs:{},df:0,1:{docs:{},df:0,1:{docs:{},df:0,1:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},6:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},z:{docs:{},df:0,'"':{docs:{},df:0,"/":{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,p:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}},2:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:3.872983346207417}},df:2,l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,e:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},3:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178}},df:2,l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,1:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:4.242640687119285}},df:1,h:{docs:{},df:0,7:{docs:{},df:0,c:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178}},df:1,h:{docs:{},df:0,5:{docs:{},df:0,l:{docs:{},df:0,1:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}},6:{docs:{},df:0,c:{docs:{},df:0,1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},8:{docs:{"https://abridge.netlify.app/overview-images/":{tf:3},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},h:{docs:{},df:0,6:{docs:{},df:0,l:{docs:{},df:0,1:{docs:{},df:0,7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},z:{docs:{},df:0,'"':{docs:{},df:0,"/":{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}},p:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}},9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:3.1622776601683795}},df:1,2:{docs:{},df:0,x:{docs:{},df:0,1:{docs:{},df:0,9:{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1,".":{docs:{},df:0,p:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},m:{docs:{},df:0,".":{docs:{},df:0,p:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}},3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},b:{docs:{},df:0,a:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,_:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}},c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,2:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/privacy/":{tf:1}},df:1}}},2:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:6},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:3,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}},0:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:2.23606797749979}},df:2,1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,5:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},2:{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/privacy/":{tf:1}},df:1}},6:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},v:{docs:{},df:0,5:{docs:{},df:0,l:{docs:{},df:0,7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178}},df:1,4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},c:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},l:{docs:{},df:0,5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},2:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1,2:{docs:{},df:0,2:{docs:{},df:0,2:{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}}},3:{docs:{},df:0,l:{docs:{},df:0,1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.23606797749979}},df:1,7:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,2:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},6:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.23606797749979}},df:1,c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},7:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},8:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},9:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},9:{docs:{},df:0,c:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},c:{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},l:{docs:{},df:0,1:{docs:{},df:0,8:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},2:{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},t:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},3:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-images/":{tf:6.557438524302}},df:2,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,d:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}},0:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:2.6457513110645907}},df:2,2:{docs:{},df:0,c:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},1:{docs:{},df:0,c:{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},2:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,4:{docs:{},df:0,c:{docs:{},df:0,1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,v:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},6:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1},7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},8:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1,c:{docs:{},df:0,1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},l:{docs:{},df:0,2:{docs:{},df:0,9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},d:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,c:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}},l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},u:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},v:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},4:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:5.477225575051661},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:3,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,0:{docs:{},df:0,".":{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,b:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}}}},a:{docs:{},df:0,1:{docs:{},df:0,1:{docs:{},df:0,6:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1},3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,c:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1},6:{docs:{},df:0,c:{docs:{},df:0,2:{docs:{},df:0,7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1},8:{docs:{},df:0,9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,c:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},d:{docs:{},df:0,e:{docs:{},df:0,f:{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,_:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{},df:0,u:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}},h:{docs:{},df:0,7:{docs:{},df:0,l:{docs:{},df:0,2:{docs:{},df:0,1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},l:{docs:{},df:0,2:{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},u:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},z:{docs:{},df:0,m:{docs:{},df:0,4:{docs:{},df:0,0:{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}},5:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:5.5677643628300215},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:3,"#":{docs:{},df:0,t:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1},1:{docs:{},df:0,2:{docs:{},df:0,x:{docs:{},df:0,5:{docs:{},df:0,1:{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,".":{docs:{},df:0,p:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}},c:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},2:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},z:{docs:{},df:0,'"':{docs:{},df:0,"/":{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,p:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}},3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1},5:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1},6:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,c:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},7:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},8:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},c:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},h:{docs:{},df:0,6:{docs:{},df:0,l:{docs:{},df:0,2:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},u:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},v:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},z:{docs:{},df:0,'"':{docs:{},df:0,"/":{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,g:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,p:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}},6:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-images/":{tf:5.0990195135927845}},df:3,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,d:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}}},0:{docs:{},df:0,"*":{docs:{},df:0,6:{docs:{},df:0,0:{docs:{},df:0,"*":{docs:{},df:0,2:{docs:{},df:0,4:{docs:{},df:0,"*":{docs:{},df:0,3:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}},0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},1:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,0:{docs:{},df:0,".":{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,b:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:1}}}}}}},5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1},7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1},c:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,3:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},k:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}},l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1}},7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:5}},df:1,"#":{docs:{},df:0,"[":{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,x:{docs:{},df:0,_:{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,b:{docs:{},df:0,":":{docs:{},df:0,":":{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}},"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,b:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,y:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}},1:{docs:{},df:0,z:{docs:{},df:0,'"':{docs:{},df:0,"/":{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,p:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}},b:{docs:{},df:0,u:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,d:{docs:{},df:0,_:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{},df:0,_:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,x:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}},l:{docs:{},df:0,2:{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},z:{docs:{},df:0,'"':{docs:{},df:0,"/":{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,p:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}},8:{docs:{"https://abridge.netlify.app/overview-images/":{tf:3.1622776601683795},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}}},4:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1},5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},6:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1},a:{docs:{},df:0,s:{docs:{},df:0,y:{docs:{},df:0,n:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},m:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,i:{docs:{},df:0,f:{docs:{},df:0,y:{docs:{},df:0,_:{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}},9:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:3}},df:2,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,b:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,y:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}}},0:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}},5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1},6:{docs:{},df:0,0:{docs:{},df:0,".":{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,b:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}}}}},f:{docs:{},df:0,e:{docs:{},df:0,e:{docs:{},df:0,d:{docs:{},df:0,_:{docs:{},df:0,f:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}},l:{docs:{},df:0,3:{docs:{},df:0,6:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},4:{docs:{},df:0,9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},_:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,"[":{docs:{},df:0,"'":{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,q:{docs:{},df:0,u:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,_:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}},s:{docs:{},df:0,s:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,"[":{docs:{},df:0,"'":{docs:{},df:0,p:{docs:{},df:0,f:{docs:{},df:0,a:{docs:{},df:0,_:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,k:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}},a:{docs:{},df:0,b:{docs:{},df:0,b:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,e:{docs:{},df:0,v:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},o:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},r:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/about/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-abridge/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-code-blocks/":{tf:2.23606797749979}},df:3,e:{docs:{},df:0,".":{docs:{},df:0,c:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:2}}}}}}}}},s:{docs:{},df:0,"(":{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}},c:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},o:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},u:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2}},df:1,s:{docs:{},df:0,_:{docs:{},df:0,u:{docs:{},df:0,n:{docs:{},df:0,i:{docs:{},df:0,q:{docs:{},df:0,u:{docs:{},df:0,e:{docs:{},df:0,_:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,_:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,_:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,x:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}},t:{docs:{},df:0,i:{docs:{},df:0,x:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}},u:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}},d:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:3,d:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:2.449489742783178}},df:3,i:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}},r:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},j:{docs:{},df:0,u:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.4142135623730951}},df:1}}}},m:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},v:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}},f:{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}},g:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},r:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}},l:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,2:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},q:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},l:{docs:{},df:0,o:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2}}},o:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},r:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},t:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:3,"=":{docs:{},df:0,'"':{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178}},df:1}}}}},i:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}},m:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},n:{docs:{},df:0,d:{docs:{},df:0,"/":{docs:{},df:0,o:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:2.449489742783178}},df:1}}},a:{docs:{},df:0,e:{docs:{},df:0,p:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},r:{docs:{},df:0,o:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}},n:{docs:{},df:0,o:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},o:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:2}}}},p:{docs:{},df:0,p:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}},l:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}},q:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},r:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},e:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1},n:{docs:{},df:0,"'":{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2}}}},i:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,"'":{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},2:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}},r:{docs:{},df:0,a:{docs:{},df:0,y:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-rich-content/":{tf:2.6457513110645907}},df:2}}},t:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}}},s:{docs:{},df:0,p:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},s:{docs:{},df:0,o:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},t:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{},df:0,".":{docs:{},df:0,x:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},t:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,b:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}}}}}},u:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:2.8284271247461903}},df:1,"(":{docs:{},df:0,s:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,"=":{docs:{},df:0,"[":{docs:{},df:0,'"':{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,9:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,".":{docs:{},df:0,o:{docs:{},df:0,g:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}},t:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}}},g:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2.8284271247461903}},df:1,o:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:1,m:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}},p:{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1}},df:1}}},l:{docs:{},df:0,a:{docs:{},df:0,y:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:3}}}},r:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772}},df:1}}}}}}},v:{docs:{},df:0,o:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},w:{docs:{},df:0,h:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},b:{docs:{},df:0,$:{docs:{},df:0,2:{docs:{},df:0,5:{docs:{},df:0,4:{docs:{},df:0,$:{docs:{},df:0,2:{docs:{},df:0,4:{docs:{},df:0,9:{docs:{},df:0,$:{docs:{},df:0,1:{docs:{},df:0,2:{docs:{},df:0,7:{docs:{},df:0,$:{docs:{},df:0,1:{docs:{},df:0,2:{docs:{},df:0,4:{docs:{},df:0,$:{docs:{},df:0,1:{docs:{},df:0,2:{docs:{},df:0,3:{docs:{},df:0,$:{docs:{},df:0,1:{docs:{},df:0,1:{docs:{},df:0,3:{docs:{},df:0,$:{docs:{},df:0,8:{docs:{},df:0,8:{docs:{},df:0,$:{docs:{},df:0,8:{docs:{},df:0,3:{docs:{},df:0,$:{docs:{},df:0,7:{docs:{},df:0,4:{docs:{},df:0,$:{docs:{},df:0,6:{docs:{},df:0,1:{docs:{},df:0,$:{docs:{},df:0,5:{docs:{},df:0,5:{docs:{},df:0,$:{docs:{},df:0,5:{docs:{},df:0,4:{docs:{},df:0,$:{docs:{},df:0,3:{docs:{},df:0,8:{docs:{},df:0,$:{docs:{},df:0,3:{docs:{},df:0,1:{docs:{},df:0,$:{docs:{},df:0,3:{docs:{},df:0,0:{docs:{},df:0,$:{docs:{},df:0,2:{docs:{},df:0,8:{docs:{},df:0,$:{docs:{},df:0,2:{docs:{},df:0,7:{docs:{},df:0,$:{docs:{},df:0,2:{docs:{},df:0,2:{docs:{},df:0,$:{docs:{},df:0,2:{docs:{},df:0,1:{docs:{},df:0,$:{docs:{},df:0,1:{docs:{},df:0,9:{docs:{},df:0,$:{docs:{},df:0,1:{docs:{},df:0,7:{docs:{},df:0,$:{docs:{},df:0,1:{docs:{},df:0,6:{docs:{},df:0,$:{docs:{},df:0,1:{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},a:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1,g:{docs:{},df:0,r:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-images/":{tf:4}},df:1,_:{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}},t:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},n:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}},d:{docs:{},df:0,w:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}},s:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1},i:{docs:{"https://abridge.netlify.app/overview-math/":{tf:2.23606797749979}},df:1,c:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}}},e:{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}},f:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:3}}},g:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},t:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},i:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},l:{docs:{},df:0,o:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2},"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772}},df:3,q:{docs:{},df:0,u:{docs:{},df:0,o:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2.23606797749979}},df:1}}}}}}}},m:{docs:{},df:0,e:{docs:{},df:0,2:{docs:{},df:0,8:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},o:{docs:{},df:0,b:{docs:{},df:0,2:{docs:{},df:0,7:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},o:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}},r:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2}},x:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},r:{docs:{},df:0,o:{docs:{},df:0,w:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2.8284271247461903},"https://abridge.netlify.app/privacy/":{tf:1}},df:3}}}}}}},c:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2}},df:1,a:{docs:{},df:0,l:{docs:{},df:0,c:{docs:{},df:0,u:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},l:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}},t:{docs:{},df:0,e:{docs:{},df:0,g:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}},h:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}},r:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,f:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}}}}}}}}},e:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{},df:0,_:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{},df:0,u:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,f:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}},e:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},r:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}},i:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},l:{docs:{},df:0,a:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:5,"=":{docs:{},df:0,'"':{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}},i:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,".":{docs:{},df:0,w:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,_:{docs:{},df:0,p:{docs:{},df:0,o:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,s:{docs:{},df:0,"(":{docs:{},df:0,d:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}},o:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,s:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}},o:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.6457513110645907},"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2.23606797749979}},df:3},y:{docs:{},df:0,3:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},l:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},m:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}},o:{docs:{},df:0,n:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},s:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},u:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}},p:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:2}}}},n:{docs:{},df:0,c:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,"(":{docs:{},df:0,d:{docs:{},df:0,o:{docs:{},df:0,c:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,".":{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,b:{docs:{},df:0,y:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,p:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,'"':{docs:{},df:0,")":{docs:{},df:0,".":{docs:{},df:0,v:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},d:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},e:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},f:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,i:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1,".":{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-math/":{tf:1}},df:2}}}}},":":{docs:{},df:0,":":{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}},u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}},n:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}},s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}},t:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/contact/":{tf:1}},df:1}},i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1}}},e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:4,"/":{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,s:{docs:{},df:0,".":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1}}}}}}}}}},o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,9:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.7320508075688772}},df:1,".":{docs:{},df:0,f:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},m:{docs:{},df:0,p:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},o:{docs:{},df:0,g:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},w:{docs:{},df:0,a:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},_:{docs:{},df:0,a:{docs:{},df:0,v:{docs:{},df:0,1:{docs:{},df:0,".":{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}}}}},v:{docs:{},df:0,p:{docs:{},df:0,9:{docs:{},df:0,".":{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,b:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}}}}}}}}}},x:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,":":{docs:{},df:0,":":{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}},r:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,s:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}}}}}},v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},o:{docs:{},df:0,k:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.4142135623730951},"https://abridge.netlify.app/privacy/":{tf:1}},df:4}}},p:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}},r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},r:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},u:{docs:{},df:0,r:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}},v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},r:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:2.449489742783178},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:4,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},s:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/about/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:4}},t:{docs:{},df:0,r:{docs:{},df:0,l:{docs:{},df:0,"+":{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,"+":{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}}}},u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,l:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1},r:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},s:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},t:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}},d:{docs:{},df:0,3:{docs:{},df:0,c:{docs:{},df:0,3:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},"=":{docs:{},df:0,'"':{docs:{},df:0,m:{docs:{},df:0,2:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},2:{docs:{},df:0,7:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},3:{docs:{},df:0,3:{docs:{},df:0,9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},6:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},5:{docs:{},df:0,6:{docs:{},df:0,5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},7:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},9:{docs:{},df:0,9:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},a:{docs:{},df:0,i:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},n:{docs:{},df:0,d:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},t:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/privacy/":{tf:1}},df:2},e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/privacy/":{tf:1}},df:2}},y:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},e:{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},f:{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,l:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-code-blocks/":{tf:2.6457513110645907},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-images/":{tf:1}},df:5}}}}},m:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1,n:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},s:{docs:{},df:0,c:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},i:{docs:{},df:0,g:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}},r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}}},i:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,v:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}},f:{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:2}}}},r:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}}}}}},s:{docs:{},df:0,p:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,y:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:1}},df:3}}}}}},j:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},o:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,u:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}}}}}}}}}}}},".":{docs:{},df:0,c:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}},g:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,b:{docs:{},df:0,y:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,p:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,'"':{docs:{},df:0,")":{docs:{},df:0,".":{docs:{},df:0,v:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}},u:{docs:{},df:0,g:{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}},q:{docs:{},df:0,u:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,y:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}},e:{docs:{},df:0,s:{docs:{},df:0,n:{docs:{},df:0,"'":{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:2.449489742783178}},df:1}}}}},l:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},t:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}},l:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},o:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}},u:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},n:{docs:{},df:0,"'":{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},u:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},x:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,s:{docs:{},df:0,c:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}}}}}}}}}}}},e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2}},df:1,".":{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}}}}}}},"^":{docs:{},df:0,"{":{docs:{},df:0,i:{docs:{},df:0,"\\":{docs:{},df:0,p:{docs:{},df:0,i:{docs:{},df:0,"}":{docs:{},df:0,"+":{docs:{},df:0,1:{docs:{},df:0,"=":{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772}},df:1}}}}}}}}}}},a:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:2}},s:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:3}}}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},d:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.7320508075688772}},df:1,i:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},f:{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/privacy/":{tf:1}},df:1}}}}},i:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},l:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:2}}}}},i:{docs:{},df:0,f:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}},m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,c:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2}},df:1}}}},s:{docs:{},df:0,u:{docs:{},df:0,b:{docs:{},df:0,j:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2}},df:1}}}}}}}}}},b:{docs:{},df:0,e:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1}},df:3}}}},n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,a:{docs:{},df:0,b:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:2.6457513110645907}},df:2}}},d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:3,i:{docs:{},df:0,g:{docs:{},df:0,n:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},g:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},i:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},o:{docs:{},df:0,u:{docs:{},df:0,g:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},o:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:1,s:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,q:{docs:{},df:0,u:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},q:{docs:{},df:0,u:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}},r:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},s:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,p:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},q:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:1,c:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.7320508075688772}},df:1},u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},v:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},r:{docs:{},df:0,y:{docs:{},df:0,b:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}},x:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,a:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},m:{docs:{},df:0,p:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:4}}}},c:{docs:{},df:0,e:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}},r:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},e:{docs:{},df:0,c:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},r:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},i:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:2}}},p:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},e:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},l:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},q:{docs:{},df:0,u:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}},t:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772}},df:1}}},r:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:2.449489742783178}},df:2}}}}},f:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.449489742783178}},df:1,"(":{docs:{},df:0,"\\":{docs:{},df:0,x:{docs:{},df:0,i:{docs:{},df:0,")":{docs:{},df:0,",":{docs:{},df:0,e:{docs:{},df:0,"^":{docs:{},df:0,"{":{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}},"\\":{docs:{},df:0,",":{docs:{},df:0,e:{docs:{},df:0,"^":{docs:{},df:0,"{":{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}}}}}},x:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:1}},a:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1,t:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},t:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}},i:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}},l:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1,b:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1,_:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},p:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}}},s:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:1}},df:4},t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1,"=":{docs:{},df:0,'"':{docs:{},df:0,i:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}},s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:3,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},e:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:1}},df:2}}}},e:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1},l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:5.477225575051661}},df:1,s:{docs:{},df:0,"]":{docs:{},df:0,"(":{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,".":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}}},h:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1,"=":{docs:{},df:0,4:{docs:{},df:0,8:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},i:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},g:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}},l:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:2},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-math/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:4,n:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}}}},l:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,"#":{docs:{},df:0,8:{docs:{},df:0,f:{docs:{},df:0,1:{docs:{},df:0,f:{docs:{},df:0,1:{docs:{},df:0,d:{docs:{},df:0,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,p:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}},f:{docs:{},df:0,f:{docs:{},df:0,f:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}}}}}}}},r:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:4}}}},l:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}},u:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}},m:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,".":{docs:{},df:0,p:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,n:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}},n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1},o:{docs:{},df:0,l:{docs:{},df:0,d:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}},l:{docs:{},df:0,o:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},o:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},r:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2.6457513110645907}},df:2}},u:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},u:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},r:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},p:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1,"=":{docs:{},df:0,'"':{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,9:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}}}}}}},r:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}}},u:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:1}}}},u:{docs:{},df:0,g:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},n:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1,c:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,t:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.6457513110645907}},df:1}}}}}},s:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,n:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}},w:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1,"=":{docs:{},df:0,6:{docs:{},df:0,4:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}},g:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1,e:{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}}},s:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178}},df:1,e:{docs:{},df:0,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,b:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},o:{docs:{},df:0,o:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},s:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}}},".":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.8284271247461903}},df:1}}}},i:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178}},df:1,e:{docs:{},df:0,":":{docs:{},df:0,h:{docs:{},df:0,o:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1}}}}}}}}}}}}}},t:{docs:{},df:0,p:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,y:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,f:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}},s:{docs:{},df:0,p:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,z:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,f:{docs:{},df:0,o:{docs:{},df:0,"(":{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,s:{docs:{},df:0,p:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}},i:{docs:{},df:0,f:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2.449489742783178}},df:2,"(":{docs:{},df:0,s:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,"=":{docs:{},df:0,"[":{docs:{},df:0,'"':{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,9:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,_:{docs:{},df:0,a:{docs:{},df:0,v:{docs:{},df:0,1:{docs:{},df:0,".":{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}},v:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}},l:{docs:{},df:0,o:{docs:{},df:0,b:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-math/":{tf:2}},df:1}}}}},o:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,a:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}},e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1},k:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},o:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1},g:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1,e:{docs:{},df:0,"'":{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}}}}},p:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}},s:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}},t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.8284271247461903},"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:3.4641016151377544}},df:4,";":{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}},u:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},h:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:2,1:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},2:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,o:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},3:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},4:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},5:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},6:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},"=":{docs:{},df:0,4:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178}},df:1}}}},a:{docs:{},df:0,l:{docs:{},df:0,f:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}},p:{docs:{},df:0,p:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1},y:{docs:{},df:0,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,b:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,s:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}}},".":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1}}}},i:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,e:{docs:{},df:0,":":{docs:{},df:0,h:{docs:{},df:0,o:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}},r:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,s:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},s:{docs:{},df:0,_:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,f:{docs:{},df:0,i:{docs:{},df:0,e:{docs:{},df:0,d:{docs:{},df:0,_:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}},e:{docs:{},df:0,a:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}},v:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}},i:{docs:{},df:0,g:{docs:{},df:0,h:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.6457513110645907},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2,"=":{docs:{},df:0,'"':{docs:{},df:0,4:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1}},8:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1},9:{docs:{},df:0,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}},l:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:2}},p:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},r:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2.449489742783178}},df:2}},y:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},i:{docs:{},df:0,g:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},l:{docs:{},df:0,i:{docs:{},df:0,g:{docs:{},df:0,h:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:4}}}}}}}},o:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}},r:{docs:{},df:0,i:{docs:{},df:0,z:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.23606797749979}},df:1,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,b:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,v:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1}}}}}}}}}}}}}}}}}}}}}}}}},r:{docs:{},df:0,e:{docs:{},df:0,f:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,p:{docs:{},df:0,s:{docs:{},df:0,":":{docs:{},df:0,"/":{docs:{},df:0,"/":{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,s:{docs:{},df:0,".":{docs:{},df:0,e:{docs:{},df:0,x:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,".":{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{},df:0,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,d:{docs:{},df:0,a:{docs:{},df:0,s:{docs:{},df:0,h:{docs:{},df:0,b:{docs:{},df:0,o:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,d:{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,a:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:5,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}},5:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}},t:{docs:{},df:0,p:{docs:{},df:0,s:{docs:{},df:0,":":{docs:{},df:0,"/":{docs:{},df:0,"/":{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,".":{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,f:{docs:{},df:0,y:{docs:{},df:0,".":{docs:{},df:0,a:{docs:{},df:0,p:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}},u:{docs:{},df:0,m:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.8284271247461903}},df:1,i:{docs:{},df:0,t:{docs:{},df:0,y:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,5:{docs:{},df:0,5:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}},n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},i:{docs:{},df:0,"'":{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1},v:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}},c:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:3}}},d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.7320508075688772}},df:3,"=":{docs:{},df:0,'"':{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}},o:{docs:{},df:0,o:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}}}},s:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1}}}}},e:{docs:{},df:0,b:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},f:{docs:{},df:0,r:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.4142135623730951}},df:2}}}},m:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:4.898979485566356},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:3,e:{docs:{},df:0,"(":{docs:{},df:0,s:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,"=":{docs:{},df:0,"[":{docs:{},df:0,'"':{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,9:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}},"/":{docs:{},df:0,p:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}}}},g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,"(":{docs:{},df:0,s:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,".":{docs:{},df:0,"/":{docs:{},df:0,i:{docs:{},df:0,m:{docs:{},df:0,g:{docs:{},df:0,"/":{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}},"/":{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{},df:0,i:{docs:{},df:0,e:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}},f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}},"/":{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}},h:{docs:{},df:0,o:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,e:{docs:{},df:0,r:{docs:{},df:0,"(":{docs:{},df:0,s:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,"=":{docs:{},df:0,"[":{docs:{},df:0,'"':{docs:{},df:0,".":{docs:{},df:0,"/":{docs:{},df:0,i:{docs:{},df:0,m:{docs:{},df:0,g:{docs:{},df:0,"/":{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,".":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}},"/":{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{},df:0,i:{docs:{},df:0,e:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}},f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,".":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}},p:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2}}},r:{docs:{},df:0,o:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},n:{docs:{},df:0,c:{docs:{},df:0,l:{docs:{},df:0,u:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2}}},t:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},d:{docs:{},df:0,e:{docs:{},df:0,x:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,".":{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}},i:{docs:{},df:0,v:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}},f:{docs:{},df:0,l:{docs:{},df:0,u:{docs:{},df:0,x:{docs:{},df:0,d:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1,c:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}},o:{docs:{},df:0,r:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/privacy/":{tf:1}},df:2}}},t:{docs:{},df:0,y:{docs:{},df:0,"}":{docs:{},df:0,"^":{docs:{},df:0,"\\":{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,f:{docs:{},df:0,t:{docs:{},df:0,y:{docs:{},df:0,"\\":{docs:{},df:0,h:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}}}}},i:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}},l:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772}},df:3}}},s:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},r:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},p:{docs:{},df:0,i:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}}},t:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2}},df:1,"(":{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,f:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}}},_:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:1,0:{docs:{},df:0,"^":{docs:{},df:0,1:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}},e:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1},r:{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}},o:{docs:{},df:0,":":{docs:{},df:0,":":{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,u:{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"(":{docs:{},df:0,")":{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}},p:{docs:{},df:0,s:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},s:{docs:{},df:0,_:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},d:{docs:{},df:0,m:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},o:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1},s:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,"(":{docs:{},df:0,$:{docs:{},df:0,_:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,"[":{docs:{},df:0,"'":{docs:{},df:0,p:{docs:{},df:0,f:{docs:{},df:0,a:{docs:{},df:0,_:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,k:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}},t:{docs:{},df:0,"'":{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},a:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,s:{docs:{},df:0,b:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,d:{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,k:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{},df:0,r:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,g:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}}}}}}}}}}}}}}},t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},e:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2.449489742783178}},df:2}}}},j:{docs:{},df:0,a:{docs:{},df:0,k:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}},n:{docs:{"https://abridge.netlify.app/privacy/":{tf:1}},df:1},v:{docs:{},df:0,a:{docs:{},df:0,s:{docs:{},df:0,c:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:2}}}}}}}}},e:{docs:{},df:0,l:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1},y:{docs:{},df:0,":":{docs:{},df:0,":":{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,x:{docs:{},df:0,_:{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}},i:{docs:{},df:0,e:{docs:{},df:0,i:{docs:{},df:0,k:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}}}}},o:{docs:{},df:0,h:{docs:{},df:0,n:{docs:{},df:0,5:{docs:{},df:0,9:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},p:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}},s:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:3,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1,b:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},k:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,x:{docs:{"https://abridge.netlify.app/overview-math/":{tf:3.605551275463989}},df:1,"(":{docs:{},df:0,b:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{},df:0,"=":{docs:{},df:0,f:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}},t:{docs:{},df:0,r:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}}}}}}}}}},b:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,y:{docs:{},df:0,2:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},y:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}},n:{docs:{},df:0,o:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},l:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},c:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1,"=":{docs:{},df:0,'"':{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}}}}}}},u:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}},r:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2}},df:1,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},s:{docs:{},df:0,t:{docs:{},df:0,_:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,g:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},e:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}}}}},t:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},t:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},y:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1}},df:2}}}}},e:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}},v:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}}},i:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/about/":{tf:1.4142135623730951}},df:1}}}},f:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},g:{docs:{},df:0,h:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:2,h:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:2}},df:3}}}},w:{docs:{},df:0,e:{docs:{},df:0,i:{docs:{},df:0,g:{docs:{},df:0,h:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:3}}}}}}}}},n:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2},k:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}},s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2.23606797749979}},df:1,e:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},o:{docs:{},df:0,a:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:2.23606797749979}},df:3}},c:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}},o:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:2}},w:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,"(":{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}},s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,";":{docs:{},df:0,"!":{docs:{},df:0,d:{docs:{},df:0,o:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,y:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}}}}},"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},"/":{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}},b:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,y:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}}}}},d:{docs:{},df:0,i:{docs:{},df:0,v:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1}}}}}},h:{docs:{},df:0,2:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},e:{docs:{},df:0,a:{docs:{},df:0,d:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}}}},t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}}}}},p:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}}},s:{docs:{},df:0,t:{docs:{},df:0,y:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1}}}}}}}},v:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,o:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}}}}}}},"?":{docs:{},df:0,p:{docs:{},df:0,h:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},a:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1,u:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}},b:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,y:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}}}}},d:{docs:{},df:0,i:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.8284271247461903}},df:1,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:2}}}}}},f:{docs:{},df:0,i:{docs:{},df:0,g:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,f:{docs:{},df:0,i:{docs:{},df:0,g:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}},h:{docs:{},df:0,1:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,";":{docs:{},df:0,"—":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,h:{docs:{},df:0,6:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}}}}}},2:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,b:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}},6:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},e:{docs:{},df:0,a:{docs:{},df:0,d:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}}}},t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}},i:{docs:{},df:0,m:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},o:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}},m:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}}},p:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,p:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}}}}}}}}}}}}}}}},i:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}}}}}}}},s:{docs:{},df:0,c:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:1}}}}},o:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:3.3166247903554}},df:1,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}},t:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,".":{docs:{},df:0,h:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}},y:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1}}}}}}},v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},t:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,e:{docs:{},df:0,x:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}}}}}}}}}}}}}},v:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.7320508075688772}},df:1}}}}}}}}}},u:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},m:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.449489742783178},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,l:{docs:{},df:0,i:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,":":{docs:{},df:0,":":{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,"(":{docs:{},df:0,")":{docs:{},df:0,".":{docs:{},df:0,a:{docs:{},df:0,w:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}},n:{docs:{},df:0,d:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/about/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:6}}}}}},g:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},i:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:2},u:{docs:{},df:0,f:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,k:{docs:{},df:0,s:{docs:{},df:0,w:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,y:{docs:{},df:0,o:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,f:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,d:{docs:{},df:0,h:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,v:{docs:{},df:0,r:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,b:{docs:{},df:0,m:{docs:{},df:0,w:{docs:{},df:0,h:{docs:{},df:0,y:{docs:{},df:0,u:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,k:{docs:{},df:0,i:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{},df:0,s:{docs:{},df:0,u:{docs:{},df:0,b:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,h:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,u:{docs:{},df:0,z:{docs:{},df:0,u:{docs:{},df:0,k:{docs:{},df:0,i:{docs:{},df:0,v:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,v:{docs:{},df:0,o:{docs:{},df:0,s:{docs:{},df:0,u:{docs:{},df:0,b:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,z:{docs:{},df:0,d:{docs:{},df:0,a:{docs:{},df:0,j:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{},df:0,u:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,b:{docs:{},df:0,u:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,x:{docs:{},df:0,u:{docs:{},df:0,s:{docs:{},df:0,g:{docs:{},df:0,m:{docs:{},df:0,c:{docs:{},df:0,p:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,s:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,a:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},r:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,d:{docs:{},df:0,o:{docs:{},df:0,w:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2.23606797749979}},df:2}}}}}},s:{docs:{},df:0,k:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-math/":{tf:2.6457513110645907}},df:1,_:{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,_:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-math/":{tf:2.23606797749979}},df:1}}}}}}}}}},e:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:2.6457513110645907}},df:1}}}}}},x:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.4142135623730951}},df:1}},b:{docs:{},df:0,":":{docs:{},df:0,1:{docs:{},df:0,2:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,p:{docs:{},df:0,x:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}}}}},d:{docs:{},df:0,5:{docs:{},df:0,"(":{docs:{},df:0,u:{docs:{},df:0,n:{docs:{},df:0,i:{docs:{},df:0,q:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,p:{docs:{},df:0,f:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}},e:{docs:{},df:0,a:{docs:{},df:0,s:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}},d:{docs:{},df:0,i:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},m:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}}},n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},s:{docs:{},df:0,s:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},t:{docs:{},df:0,a:{docs:{},df:0,p:{docs:{},df:0,h:{docs:{},df:0,y:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}},i:{docs:{},df:0,l:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},t:{docs:{"https://abridge.netlify.app/about/":{tf:1.4142135623730951}},df:1}},o:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1,r:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},l:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,r:{docs:{},df:0,u:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}},o:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},u:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},v:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},p:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1},4:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}},u:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}},w:{docs:{},df:0,":":{docs:{},df:0,5:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}},y:{docs:{},df:0,v:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,1:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1},2:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}},n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,".":{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}},a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},v:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:1}},b:{docs:{},df:0,s:{docs:{},df:0,p:{docs:{},df:0,";":{docs:{},df:0,s:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:2.449489742783178}},df:1}}}}}}}}},e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,a:{docs:{},df:0,r:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}}}},c:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}}}},e:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}},w:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:3,".":{docs:{},df:0,u:{docs:{},df:0,p:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},x:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},o:{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,p:{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1}},df:1}}}}}}}},c:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},n:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,q:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},s:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},t:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:1}},e:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}},v:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},w:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772}},df:3}},u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,l:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:3.1622776601683795}},df:1}},m:{docs:{},df:0,b:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}},s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},o:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1,b:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}}}}}}},d:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,t:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,q:{docs:{},df:0,u:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}},f:{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},i:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},s:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},g:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}},m:{docs:{},df:0,n:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,m:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},n:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,c:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,c:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{},df:0,"(":{docs:{},df:0,")":{docs:{},df:0,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},p:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:2},"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:5}}}}},r:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}},d:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2}}}},t:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,w:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:2}}}}}}},u:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,e:{docs:{},df:0,r:{docs:{},df:0,m:{docs:{},df:0,o:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}},p:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178},"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:3}}}}},v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:3,9:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1,".":{docs:{},df:0,f:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},m:{docs:{},df:0,p:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},w:{docs:{},df:0,a:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},_:{docs:{},df:0,v:{docs:{},df:0,p:{docs:{},df:0,9:{docs:{},df:0,".":{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,b:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}}},a:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},v:{docs:{},df:0,i:{docs:{},df:0,e:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}},p:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,"=":{docs:{},df:0,4:{docs:{},df:0,5:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1}}},a:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},d:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1},g:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:3}},df:4,"'":{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}},i:{docs:{},df:0,n:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,_:{docs:{},df:0,b:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}}}}}},r:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{},df:0,r:{docs:{},df:0,a:{docs:{},df:0,p:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},m:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}},i:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,i:{docs:{"https://abridge.netlify.app/privacy/":{tf:1.4142135623730951}},df:1,c:{docs:{},df:0,u:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772}},df:1}}}}}},n:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},s:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,w:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.8284271247461903},"https://abridge.netlify.app/overview-rich-content/":{tf:1.7320508075688772}},df:2}}},e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-math/":{tf:2.449489742783178}},df:1,c:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},f:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:2}}}},i:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},s:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/privacy/":{tf:1}},df:1}}}}},h:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},i:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:1,k:{docs:{},df:0,e:{docs:{},df:0,"'":{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},1:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},l:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:1}},n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1},y:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2,e:{docs:{},df:0,r:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}},n:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}},l:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.4142135623730951}},df:1}}}},s:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}}}}},e:{docs:{},df:0,a:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}},i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},p:{docs:{},df:0,g:{docs:{},df:0,s:{docs:{},df:0,q:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}},o:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/privacy/":{tf:1}},df:1}}}},r:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/posts/":{tf:1}},df:3,f:{docs:{},df:0,i:{docs:{},df:0,x:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},w:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},r:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},e:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}},v:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}},i:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},i:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}},n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,"(":{docs:{},df:0,'"':{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,l:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}}},g:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,p:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,y:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,f:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}},s:{docs:{},df:0,q:{docs:{},df:0,u:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}},f:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}},v:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/privacy/":{tf:1.4142135623730951}},df:1}}}}},o:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,d:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},f:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:2}}},g:{docs:{},df:0,r:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},j:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},p:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},v:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2}}}}},u:{docs:{},df:0,b:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}}}},r:{docs:{},df:0,p:{docs:{},df:0,o:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}}},y:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,3:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}},q:{docs:{},df:0,u:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1},i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:1,a:{docs:{},df:0,n:{docs:{},df:0,i:{docs:{},df:0,m:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},t:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},e:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},b:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},c:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}},o:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:1}}}},r:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1},g:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},t:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},i:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},o:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1,c:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1}}}}}}},d:{docs:{},df:0,u:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},r:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},g:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},u:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.23606797749979}},df:1,i:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},n:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-math/":{tf:2.449489742783178}},df:1}}}},p:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.8284271247461903}},df:1}}},l:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},r:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}}},q:{docs:{},df:0,u:{docs:{},df:0,i:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1,e:{docs:{},df:0,_:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,"'":{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{},df:0,m:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,".":{docs:{},df:0,p:{docs:{},df:0,h:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}},r:{docs:{},df:0,i:{docs:{},df:0,b:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},o:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},s:{docs:{},df:0,p:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},u:{docs:{},df:0,l:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1,s:{docs:{},df:0,c:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,e:{docs:{},df:0,".":{docs:{},df:0,f:{docs:{},df:0,i:{docs:{},df:0,r:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}},i:{docs:{},df:0,n:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,t:{docs:{},df:0,b:{docs:{},df:0,e:{docs:{},df:0,f:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}},o:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}},t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.6457513110645907},"https://abridge.netlify.app/overview-rich-content/":{tf:2.23606797749979}},df:2}}}},v:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1}}}}},i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,c:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178},"https://abridge.netlify.app/overview-rich-content/":{tf:3.4641016151377544}},df:2}}},o:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:1},o:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-images/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-math/":{tf:1}},df:3}},u:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,"(":{docs:{},df:0,b:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,2:{docs:{},df:0,8:{docs:{},df:0,0:{docs:{},df:0,".":{docs:{},df:0,h:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},p:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}},t:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}},w:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},u:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,a:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}}}}}}}}},s:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},m:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.8284271247461903},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:2},p:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},p:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},c:{docs:{},df:0,o:{docs:{},df:0,p:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},r:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1}},df:3}}},r:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}},e:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}},c:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},o:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},r:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},t:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-math/":{tf:2.449489742783178}},df:2,_:{docs:{},df:0,n:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,"]":{docs:{},df:0,"/":{docs:{},df:0,_:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,x:{docs:{},df:0,".":{docs:{},df:0,m:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}},e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,n:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}},l:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}},m:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:3}}}},n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,e:{docs:{},df:0,r:{docs:{},df:0,".":{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,"(":{docs:{},df:0,"'":{docs:{},df:0,j:{docs:{},df:0,a:{docs:{},df:0,k:{docs:{},df:0,e:{docs:{},df:0,"@":{docs:{},df:0,e:{docs:{},df:0,x:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,".":{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},t:{docs:{"https://abridge.netlify.app/privacy/":{tf:1.4142135623730951}},df:1,e:{docs:{},df:0,n:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},o:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1},q:{docs:{},df:0,u:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},o:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},r:{docs:{},df:0,i:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}},v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},s:{docs:{},df:0,s:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}}}},t:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-images/":{tf:2},"https://abridge.netlify.app/overview-rich-content/":{tf:1},"https://abridge.netlify.app/privacy/":{tf:1}},df:7,c:{docs:{},df:0,o:{docs:{},df:0,o:{docs:{},df:0,k:{docs:{},df:0,i:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,"'":{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}},u:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}},v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},h:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772},"https://abridge.netlify.app/privacy/":{tf:1.4142135623730951}},df:2}}},i:{docs:{},df:0,f:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,w:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{},df:0,"=":{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}},o:{docs:{},df:0,r:{docs:{},df:0,t:{docs:{},df:0,_:{docs:{},df:0,n:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},c:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-rich-content/":{tf:2.449489742783178}},df:5}}}}},w:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:4}}},i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,t:{docs:{},df:0,i:{docs:{},df:0,b:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},v:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},t:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},e:{docs:{"https://abridge.netlify.app/about/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-abridge/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-math/":{tf:2.23606797749979},"https://abridge.netlify.app/privacy/":{tf:1.4142135623730951}},df:5},i:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},x:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},z:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:4}}},l:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},o:{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},m:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:2,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}},t:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,l:{docs:{},df:0,i:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},o:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,".":{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}}}}}}},f:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,p:{docs:{},df:0,"=":{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}},l:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/privacy/":{tf:1.4142135623730951}},df:1}},u:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2.8284271247461903}},df:2}}}},p:{docs:{},df:0,e:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1},f:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}},n:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}},e:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}},r:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}},q:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1},u:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,x:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},i:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}},r:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-images/":{tf:2}},df:2,"=":{docs:{},df:0,'"':{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}},h:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,p:{docs:{},df:0,s:{docs:{},df:0,":":{docs:{},df:0,"/":{docs:{},df:0,"/":{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,".":{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,f:{docs:{},df:0,y:{docs:{},df:0,".":{docs:{},df:0,a:{docs:{},df:0,p:{docs:{},df:0,p:{docs:{},df:0,"/":{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{},df:0,i:{docs:{},df:0,e:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2.8284271247461903}},df:2}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},i:{docs:{},df:0,m:{docs:{},df:0,g:{docs:{},df:0,"/":{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}},o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,9:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}}},s:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,p:{docs:{},df:0,s:{docs:{},df:0,":":{docs:{},df:0,"/":{docs:{},df:0,"/":{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,".":{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,f:{docs:{},df:0,y:{docs:{},df:0,".":{docs:{},df:0,a:{docs:{},df:0,p:{docs:{},df:0,p:{docs:{},df:0,"/":{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{},df:0,i:{docs:{},df:0,e:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.7320508075688772}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},t:{docs:{},df:0,a:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},r:{docs:{},df:0,t:{docs:{},df:0,_:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}},t:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/about/":{tf:1}},df:1}}},y:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},d:{docs:{},df:0,":":{docs:{},df:0,":":{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},i:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},o:{docs:{},df:0,r:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/privacy/":{tf:1}},df:1}}},r:{docs:{},df:0,"(":{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,"(":{docs:{},df:0,h:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.23606797749979}},df:1}}}}},t:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,f:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.23606797749979}},df:1}}}}}}}}}},i:{docs:{},df:0,n:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:2.8284271247461903}},df:1}}}},u:{docs:{},df:0,f:{docs:{},df:0,f:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}},y:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},u:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,l:{docs:{},df:0,i:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},c:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},p:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,p:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-math/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-rich-content/":{tf:2.8284271247461903}},df:3}}}}},r:{docs:{},df:0,r:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:3}}}}}}},v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1}},df:3}},w:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}},y:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,x:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-math/":{tf:1}},df:5}}}}}},t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,".":{docs:{},df:0,c:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,"!":{docs:{},df:0,0:{docs:{},df:0,")":{docs:{},df:0,")":{docs:{},df:0,".":{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}},i:{docs:{},df:0,n:{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}},a:{docs:{},df:0,b:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2.449489742783178}},df:2},s:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,p:{docs:{},df:0,"=":{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}},g:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-rich-content/":{tf:3.7416573867739413}},df:3},k:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:1}},l:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,c:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},l:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}},m:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,e:{docs:{},df:0,r:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.23606797749979}},df:1,e:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,9:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}}},f:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2}},df:1},l:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},r:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},x:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}}},h:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/about/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-abridge/":{tf:2.449489742783178},"https://abridge.netlify.app/overview-code-blocks/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:5,_:{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},s:{docs:{},df:0,"\\":{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,"\\":{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,"\\":{docs:{},df:0,_:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,x:{docs:{},df:0,".":{docs:{},df:0,m:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}}}}}}}}}}}}}},s:{docs:{},df:0,a:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{},df:0,"\\":{docs:{},df:0,_:{docs:{},df:0,v:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,".":{docs:{},df:0,s:{docs:{},df:0,c:{docs:{},df:0,s:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},i:{docs:{},df:0,r:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/privacy/":{tf:1.4142135623730951}},df:2}}},o:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},r:{docs:{},df:0,e:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},i:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},m:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,".":{docs:{},df:0,c:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}},s:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,e:{docs:{},df:0,p:{docs:{},df:0,"(":{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}},t:{docs:{},df:0,i:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1,e:{docs:{},df:0,"(":{docs:{},df:0,")":{docs:{},df:0,"+":{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}},o:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},s:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}}}},t:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951}},df:3,e:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,c:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}},r:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}},o:{docs:{},df:0,o:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},s:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}}}}}}}},u:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},o:{docs:{},df:0,k:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}},m:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},p:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}},r:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:2}}},i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1,g:{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}},m:{docs:{},df:0,"(":{docs:{},df:0,s:{docs:{},df:0,a:{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,p:{docs:{},df:0,o:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,"(":{docs:{},df:0,"'":{docs:{},df:0,f:{docs:{},df:0,u:{docs:{},df:0,s:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,n:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}},u:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2.449489742783178},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:2},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-math/":{tf:3.1622776601683795}},df:4}}},w:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1}},df:2}},y:{docs:{},df:0,p:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:3,"=":{docs:{},df:0,'"':{docs:{},df:0,a:{docs:{},df:0,u:{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,o:{docs:{},df:0,"/":{docs:{},df:0,f:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},m:{docs:{},df:0,p:{docs:{},df:0,3:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},o:{docs:{},df:0,g:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},w:{docs:{},df:0,a:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}},b:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},i:{docs:{},df:0,m:{docs:{},df:0,g:{docs:{},df:0,"/":{docs:{},df:0,w:{docs:{},df:0,e:{docs:{},df:0,b:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.7320508075688772}},df:1}}}}}}}},m:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{},df:0,"/":{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,x:{docs:{},df:0,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,e:{docs:{},df:0,"^":{docs:{},df:0,"{":{docs:{},df:0,i:{docs:{},df:0,"\\":{docs:{},df:0,p:{docs:{},df:0,i:{docs:{},df:0,"}":{docs:{},df:0,"+":{docs:{},df:0,1:{docs:{},df:0,"=":{docs:{},df:0,0:{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,s:{docs:{},df:0,c:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},";":{docs:{},df:0,m:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,"=":{docs:{},df:0,d:{docs:{},df:0,i:{docs:{},df:0,s:{docs:{},df:0,p:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,y:{docs:{},df:0,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"\\":{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{},df:0,_:{docs:{},df:0,0:{docs:{},df:0,"^":{docs:{},df:0,1:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},v:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,o:{docs:{},df:0,"/":{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}},w:{docs:{},df:0,e:{docs:{},df:0,b:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}}}}}},u:{docs:{},df:0,n:{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}},d:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772}},df:3}}},i:{docs:{},df:0,q:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}},t:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,p:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,y:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}},n:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,"(":{docs:{},df:0,'"':{docs:{},df:0,p:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,y:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}},o:{docs:{},df:0,r:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},p:{docs:{},df:0,d:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1,e:{docs:{},df:0,_:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}}}}},r:{docs:{},df:0,l:{docs:{},df:0,"(":{docs:{},df:0,"'":{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1,s:{docs:{},df:0,".":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}}}}}}}}}},h:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,p:{docs:{},df:0,s:{docs:{},df:0,":":{docs:{},df:0,"/":{docs:{},df:0,"/":{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,g:{docs:{},df:0,e:{docs:{},df:0,".":{docs:{},df:0,n:{docs:{},df:0,e:{docs:{},df:0,t:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,f:{docs:{},df:0,y:{docs:{},df:0,".":{docs:{},df:0,a:{docs:{},df:0,p:{docs:{},df:0,p:{docs:{},df:0,"/":{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,v:{docs:{},df:0,i:{docs:{},df:0,e:{docs:{},df:0,w:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.4142135623730951}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},i:{docs:{},df:0,m:{docs:{},df:0,g:{docs:{},df:0,"/":{docs:{},df:0,f:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,s:{docs:{},df:0,".":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}}}},s:{docs:{"https://abridge.netlify.app/about/":{tf:1},"https://abridge.netlify.app/overview-abridge/":{tf:2},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-images/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-math/":{tf:1},"https://abridge.netlify.app/overview-rich-content/":{tf:3.3166247903554},"https://abridge.netlify.app/privacy/":{tf:1}},df:8,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178},"https://abridge.netlify.app/overview-math/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-rich-content/":{tf:2}},df:3}},e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1,_:{docs:{},df:0,u:{docs:{},df:0,p:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}},r:{docs:{},df:0,"/":{docs:{},df:0,b:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{},df:0,"/":{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,v:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}},t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}},v:{docs:{},df:0,a:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}},u:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2}},r:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1,i:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},e:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,a:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,n:{docs:{},df:0,i:{docs:{},df:0,m:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}},n:{docs:{},df:0,i:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{},df:0,i:{docs:{},df:0,u:{docs:{},df:0,s:{docs:{},df:0,d:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}},r:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:2,f:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},i:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-rich-content/":{tf:3.605551275463989}},df:3,"(":{docs:{},df:0,s:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,r:{docs:{},df:0,c:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,"=":{docs:{},df:0,"[":{docs:{},df:0,'"':{docs:{},df:0,o:{docs:{},df:0,v:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,9:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,_:{docs:{},df:0,a:{docs:{},df:0,v:{docs:{},df:0,1:{docs:{},df:0,".":{docs:{},df:0,m:{docs:{},df:0,p:{docs:{},df:0,4:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},e:{docs:{},df:0,w:{docs:{},df:0,b:{docs:{},df:0,o:{docs:{},df:0,x:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}},m:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1,e:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:2}},df:1}}}},m:{docs:{},df:0,"(":{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,_:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1}},df:1}}}}}}}}}}}},o:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{},df:0,s:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,q:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}},o:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,b:{docs:{},df:0,u:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},r:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},u:{docs:{},df:0,p:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1,i:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,s:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}}}},w:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1.7320508075688772}},df:1,"=":{docs:{},df:0,6:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2.449489742783178}},df:1}}}},a:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-images/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:5}},t:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}}}},v:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}},e:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1,m:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1},p:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}},i:{docs:{},df:0,d:{docs:{},df:0,t:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-images/":{tf:2.6457513110645907},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:3,"=":{docs:{},df:0,'"':{docs:{},df:0,6:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-images/":{tf:2}},df:1}},4:{docs:{},df:0,0:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}}},n:{docs:{},df:0,d:{docs:{},df:0,o:{docs:{},df:0,w:{docs:{},df:0,".":{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}}}}}},t:{docs:{},df:0,h:{docs:{},df:0,i:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772}},df:1}},o:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}},o:{docs:{},df:0,r:{docs:{},df:0,l:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:2}},df:1}},m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}},r:{docs:{},df:0,a:{docs:{},df:0,p:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}},i:{docs:{},df:0,t:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}},x:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.4142135623730951}},df:1,'"':{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,i:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"&":{docs:{},df:0,l:{docs:{},df:0,t:{docs:{},df:0,";":{docs:{},df:0,"/":{docs:{},df:0,b:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,n:{docs:{},df:0,"&":{docs:{},df:0,g:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}},"^":{docs:{},df:0,2:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:1}},e:{docs:{},df:0,r:{docs:{},df:0,u:{docs:{},df:0,m:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},i:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1.4142135623730951}},df:1},m:{docs:{},df:0,l:{docs:{},df:0,n:{docs:{},df:0,s:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,h:{docs:{},df:0,t:{docs:{},df:0,t:{docs:{},df:0,p:{docs:{},df:0,":":{docs:{},df:0,"/":{docs:{},df:0,"/":{docs:{},df:0,w:{docs:{},df:0,w:{docs:{},df:0,w:{docs:{},df:0,".":{docs:{},df:0,w:{docs:{},df:0,3:{docs:{},df:0,".":{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,g:{docs:{},df:0,"/":{docs:{},df:0,2:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,0:{docs:{},df:0,"/":{docs:{},df:0,s:{docs:{},df:0,v:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},"}":{docs:{},df:0,",":{docs:{},df:0,d:{docs:{},df:0,"\\":{docs:{},df:0,x:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}},"\\":{docs:{},df:0,",":{docs:{},df:0,d:{docs:{},df:0,"\\":{docs:{},df:0,x:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}}}},y:{docs:{},df:0,e:{docs:{},df:0,l:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,w:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,t:{docs:{},df:0,o:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}}}}}}}}},n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},o:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-embedded-youtube/":{tf:2}},df:1}}}}},t:{docs:{},df:0,"(":{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,"=":{docs:{},df:0,'"':{docs:{},df:0,t:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,_:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,_:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,r:{docs:{"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:1}}}}}}}}}}}}}}}}},z:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1},o:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/about/":{tf:1.4142135623730951},"https://abridge.netlify.app/overview-abridge/":{tf:2.23606797749979},"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1},"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1.7320508075688772},"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:7}},n:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1.7320508075688772}},df:1}}}}}},title:{root:{docs:{},df:0,a:{docs:{},df:0,b:{docs:{},df:0,r:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}}},b:{docs:{},df:0,l:{docs:{},df:0,o:{docs:{},df:0,c:{docs:{},df:0,k:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}}}}},c:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:1}},n:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/contact/":{tf:1}},df:1}}},e:{docs:{},df:0,n:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}}}}},e:{docs:{},df:0,m:{docs:{},df:0,b:{docs:{},df:0,e:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:2}}}}},g:{docs:{},df:0,u:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}},i:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,g:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}},m:{docs:{},df:0,a:{docs:{},df:0,r:{docs:{},df:0,k:{docs:{},df:0,d:{docs:{},df:0,o:{docs:{},df:0,w:{docs:{},df:0,n:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}}},t:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}}}}},n:{docs:{},df:0,o:{docs:{},df:0,t:{docs:{},df:0,a:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/overview-math/":{tf:1}},df:1}}}}},p:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/privacy/":{tf:1}},df:1}}}},s:{docs:{},df:0,t:{docs:{"https://abridge.netlify.app/posts/":{tf:1}},df:1}}},r:{docs:{},df:0,i:{docs:{},df:0,v:{docs:{},df:0,a:{docs:{},df:0,c:{docs:{},df:0,i:{docs:{"https://abridge.netlify.app/privacy/":{tf:1}},df:1}}}}}}},r:{docs:{},df:0,i:{docs:{},df:0,c:{docs:{},df:0,h:{docs:{"https://abridge.netlify.app/overview-rich-content/":{tf:1}},df:1}}}},s:{docs:{},df:0,h:{docs:{},df:0,o:{docs:{},df:0,r:{docs:{},df:0,t:{docs:{},df:0,c:{docs:{},df:0,o:{docs:{},df:0,d:{docs:{"https://abridge.netlify.app/overview-images/":{tf:1}},df:1}}}}}}},t:{docs:{},df:0,y:{docs:{},df:0,l:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-markdown-and-style/":{tf:1}},df:1}}}}},t:{docs:{},df:0,h:{docs:{},df:0,e:{docs:{},df:0,m:{docs:{},df:0,e:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1},"https://abridge.netlify.app/overview-code-blocks/":{tf:1}},df:2}}}}},v:{docs:{},df:0,i:{docs:{},df:0,d:{docs:{},df:0,e:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1},"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:2}}},m:{docs:{},df:0,e:{docs:{},df:0,o:{docs:{"https://abridge.netlify.app/overview-embedded-vimeo/":{tf:1}},df:1}}}}},y:{docs:{},df:0,o:{docs:{},df:0,u:{docs:{},df:0,t:{docs:{},df:0,u:{docs:{},df:0,b:{docs:{"https://abridge.netlify.app/overview-embedded-youtube/":{tf:1}},df:1}}}}}},z:{docs:{},df:0,o:{docs:{},df:0,l:{docs:{},df:0,a:{docs:{"https://abridge.netlify.app/overview-abridge/":{tf:1}},df:1}}}}}}},documentStore:{save:!0,docs:{"https://abridge.netlify.app/":{body:"",id:"https://abridge.netlify.app/",title:""},"https://abridge.netlify.app/about/":{body:"This site provides a demo for the abridge theme for Zola the static site generator.\nAbridge was created by Jake G (jieiku) to be fast and lightweight, using semantic html, a class-light abridge.css, and No Mandatory JS.\nSome fun facts about the theme:\n\nPerfect score on Google's Lighthouse audit\nOnly ~6 KB of CSS before enabling the SVG CSS icons and syntax highlighting.\nNo mandatory JavaScript.\nNow with SEO!\n\nNearly half of the existing Zola MIT themes were inspiration for features and design of this theme.\nBoth the theme and this site are licensed under the MIT license.\n",id:"https://abridge.netlify.app/about/",title:"About"},"https://abridge.netlify.app/contact/":{body:"",id:"https://abridge.netlify.app/contact/",title:"Contact"},"https://abridge.netlify.app/overview-abridge/":{body:'Abridge is a fast and lightweight Zola theme using semantic html, only ~6kb css before svg icons and syntax highlighting, no mandatory JS, and perfect Lighthouse, YellowLabTools, and Observatory scores.\n\nFor quick setup copy the config.toml from the abridge theme into the root of your zola site, this will give you a base configuration with all config values used.\nYou can then edit or comment out the values in this file as necessary.\nYou should also uncomment out the line #theme = "abridge" in your root zola config.toml file. This tells your root zola site to use the abridge theme in the themes folder.\nYou can set the number of items that appear on the home page by editing themes\\abridge\\content\\_index.md file and adjusting paginate_by = 5\nYou can set the overal page width by editing themes\\abridge\\sass\\_variables.scss file, and adjusting these two lines:\n$mw:50% !default;// max-width\n$mb:1200px !default;// value at which to switch from fluid layout to using max-width\n\n',id:"https://abridge.netlify.app/overview-abridge/",title:"Abridge Zola Theme"},"https://abridge.netlify.app/overview-code-blocks/":{body:'This article shows various Code Blocks allowing to easily compare sublime themes.\nCode Blocks\nCode blocks.. ❤️ with automatic syntax highlighting ✨‍\nSee the docs for options.\nInline Code block\nIf we want, we can also specify inline code which is useful for the small stuff.\nrust\n1//! jelly-actix-web-starter - A starter template for actix-web projects that feels very Django-esque. Avoid the boring stuff and move faster.\n2\n3use jelly::actix_web;\n4use mainlib;\n5use std::io;\n6\n7#[actix_web::main]\n8async fn main() -> io::Result<()> {\n9 mainlib::main().await\n10}\n11\n12let context = Context::new();\n\nTOML\n1base_url = "https://abridge.netlify.app/"\n2title = "Abridge"\n3description = "Abridge is a fast and lightweight Zola theme using semantic html, abridge.css class-light CSS, and No Mandatory JS."\n4default_language = "en"\n5#theme = "abridge"\n6\n7build_search_index = true\n8minify_html = false\n9feed_filename = "atom.xml"\n10taxonomies = [\n11 {name = "categories", feed = true},\n12 {name = "tags", feed = true},\n13]\n\nhtml\n<!doctype html>\n<html lang="en">\n<head>\n <meta charset="utf-8">\n <title>Example HTML5 Document</title>\n</head>\n<body>\n <!--Main Content Area-->\n <p>Test</p>\n</body>\n</html>\n\njavascript\nfunction closeSearch() {//close the search displaying the regular page.\n const e = document.querySelector("main");\n e.innerHTML = window.main\n}\n\nfunction goSearch() {// on enter key or search icon click display results to the page.\n const e = document.querySelector("main");\n window.main || (window.main = e.innerHTML);\n var t = document.getElementById("suggestions"),\n n = ((ResultsClone = t.cloneNode(!0)).id = "results", document.createElement("div")),\n o = \'<h2><button type="button" title="Close Search" onclick="closeSearch()"><i class="svgs x"></i></button> Results For: \'.concat(document.getElementById("searchinput").value, "</h2>");\n return n.innerHTML = o, ResultsClone.insertBefore(n, ResultsClone.firstChild), e.innerHTML = ResultsClone.outerHTML, t.innerHTML = "", document.getElementById("searchinput").value = "", !1\n}! function() {\n // search function code goes here\n}\n\nphp\n<?php\n/**\n * Postfix Admin\n */\nrequire_once(\'common.php\');\n$CONF = Config::getInstance()->getAll();\n\nif ($_SERVER[\'REQUEST_METHOD\'] == "POST") {\n if (!isset($_SESSION[\'PFA_token\'])) {\n die("Invalid token (session timeout; refresh the page and try again?)");\n }\n $fUsername = trim(safepost(\'fUsername\'));\n if ($lang != check_language(false)) { # only set cookie if language selection was changed\n setcookie(\'lang\', $lang, time() + 60*60*24*30); # language cookie, lifetime 30 days\n }\n}\n\n$_SESSION[\'PFA_token\'] = md5(uniqid("pfa" . rand(), true));\n\n/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */\n\njson\n{\n "name": "Abridge Zola Theme",\n "short_name": "Abridge",\n "description": "Fast & Lightweight Zola Theme",\n "start_url": "/index.html",\n "scope": "/",\n "background_color": "#111111",\n "theme_color": "#222222",\n "display": "standalone",\n "icons": [\n {\n "src": "/android-chrome-192x192.png",\n "sizes": "192x192",\n "type": "image/png"\n },\n {\n "src": "/android-chrome-512x512.png",\n "sizes": "512x512",\n "type": "image/png"\n },\n {\n "src": "/android-chrome-192x192m.png",\n "sizes": "192x192",\n "type": "image/png",\n "purpose": "maskable"\n }\n ]\n}\n\nSQL\n-- jelly-actix-web-starter - Creates an accounts table, along with some associated helpers.\n\ncreate or replace function update_timestamp() returns trigger as $$\nbegin\n new.updated = now();\n return new;\nend;\n$$ language \'plpgsql\';\n\ncreate table if not exists accounts (\n id serial primary key,\n name text not null,\n email text not null unique,\n password text not null,\n profile jsonb not null default \'{}\',\n plan integer not null default 0,\n is_active boolean not null default true,\n is_admin boolean not null default false,\n has_verified_email boolean not null default false,\n last_login timestamp with time zone,\n created timestamp with time zone not null default now(),\n updated timestamp with time zone not null default now()\n);\n\ncreate unique index accounts_unique_lower_email_idx on accounts (lower(email));\n\ncreate trigger user_updated before insert or update on accounts\nfor each row execute procedure update_timestamp();\n\nLua\nfunction square(x)\n return x * x\nend\n\nprint(square(2)) -- prints \'4\'\n\nfunction getPlayerInformation()\n playerName = UnitName("player")\n playerLevel = UnitLevel("player")\n specId, specName = GetSpecializationInfo(GetSpecialization())\n\n return "Hey, I\'m " .. playerName .. " (Level " .. playerLevel .. "). I\'m currently in spec " .. specName .. "."\nend\n\nprint(getPlayerInformation())\n\nC\n#include <stdio.h>\nint main() {\n int a;\n /* actual initialization */\n a = 10;\n printf("Hello, World!");\n return 0;\n}\n\nC++\n// Your First C++ Program\n\n#include <iostream>\n\nint main() {\n int a;\n /* actual initialization */\n a = 10;\n std::cout << "Hello World!";\n return 0;\n}\n\nGo\npackage main\n\nimport "fmt"\n\nfunc main() {\n var myvariable1 = 20\n var myvariable2 = "hello world"\n fmt.Println("hello world")\n}\n\nPython\n#!/usr/bin/env python3\nimport smtplib, socket\nfrom influxdb import InfluxDBClient\n\nwhile True:\n send = 1\n later = time.time() + 25200\n iso = time.ctime(later)\n tempF = round(bme280.temperature * 1.8 + 29, 3) #C to F formula is +32, difference is to correct bme280 temperature offset\n humidity = round(bme280.humidity, 3)\n pressure = round(bme280.pressure, 3)\n # serialize data as JSON\n data = [\n {\n "measurement": measurement,\n "tags": {\n "location": location,\n },\n "time": iso,\n "fields": {\n "temperature" : tempF,\n "humidity": humidity,\n "pressure": pressure\n }\n }\n ]\n # Send the JSON data to InfluxDB\n try:\n client.write_points(data)\n except socket.error as e:\n print("Could Not Connect to InfluxDB!")\n if tempF > 90 and humidity > 55:\n emailSubject = "Humidity>55: " + str(int(humidity)) + "%H , Temperature>90: " + str(int(tempF)) + "F"\n emailContent = \'Humidity: \' + str(int(humidity)) + \'%H , Temperature: \' + str(int(tempF)) + \'F <a href="https://metrics.example.com">Dashboard</a>\'\n elif humidity > 55:\n emailSubject = "Humidity>55: " + str(int(humidity)) + "%H"\n emailContent = \'Humidity: \' + str(int(humidity)) + \'%H , Temperature: \' + str(int(tempF)) + \'F <a href="https://metrics.example.com">Dashboard</a>\'\n elif tempF > 90:\n emailSubject = "Temperature>90: " + str(int(tempF)) + "F"\n emailContent = \'Humidity: \' + str(int(humidity)) + \'%H , Temperature: \' + str(int(tempF)) + \'F <a href="https://metrics.example.com">Dashboard</a>\'\n else:\n send = 0\n if send == 1:\n try:\n if time.time() > lastEmailTime or abs(lastTemp-int(tempF)) > 1:\n lastEmailTime = time.time()+emailInterval\n lastTemp = int(tempF)\n sender.sendmail(\'jake@example.com\', emailSubject, emailContent)\n except socket.error as e:\n print("Could Not Connect to SMTP server!")\n time.sleep(interval)\n\n',id:"https://abridge.netlify.app/overview-code-blocks/",title:"Code Blocks and Themes"},"https://abridge.netlify.app/overview-embedded-vimeo/":{body:'Zola has many shortcodes, and new are easily added, this example shows vimeo.\nVimeo\nwith vm(id="id_here")\n\nid: the video id (mandatory)\nclass: a class to add to the <div> surrounding the iframe (optional)\nautoplay: when set to "true", the video autoplays on load (optional)\nloop: when set to "true", the video plays on a loop (optional)\nnoautopause: when set to "true", the video will not autopause (optional)\ntitle - set alt title for the iframe (optional, defaults to "Vimeo")\ncookie - set to "true" if you want tracking cookies, otherwise it defaults to false.\n\n\n\t\n\n',id:"https://abridge.netlify.app/overview-embedded-vimeo/",title:"Embedded Vimeo Videos"},"https://abridge.netlify.app/overview-embedded-youtube/":{body:'Zola has many shortcodes, and new are easily added, this example shows youtube.\nYoutube\nwith yt(id="the_id_here")\n\nid: the video id (mandatory)\nplaylist: the playlist id (optional)\nclass: a class to add to the <div> surrounding the iframe (optional)\nautoplay: when set to "true", the video autoplays on load (optional)\ntitle - set alt title for the iframe (optional, defaults to "Youtube")\ncookie - set to "true" if you want tracking cookies, otherwise it defaults to false.\n\n\n\t\n\n',id:"https://abridge.netlify.app/overview-embedded-youtube/",title:"Embedded Youtube Videos"},"https://abridge.netlify.app/overview-images/":{body:'This post covers the imghover and img shortcodes. Images can also be embedded directly using markdown ![Ferris](ferris.svg), but it is better to use a shortcode so you can explicitly set the width and height, this will help prevent content layout shift which improves user experience and the google lighthouse score.\nimg Shortcode\n\nsrc is the path and filename of the image. (mandatory)\nclass sets a class for the image. (optional)\nalt sets the alt note for the image. (recommended for google lighthouse)\nw is the width of the image. (recommended for google lighthouse)\nh is the height of the image. (recommended for google lighthouse)\n\nUsage (same path)\n{{ img(src="ferris-happy.svg" alt="Ferris is Happy" w=600 h=400) }}\n\nOutput\n \n<img src="ferris-happy.svg" alt="Ferris is Happy" width="600" height="400" />\n\n\n \n\nUsage (relative path ./)\n{{ img(src="./img/ferris-gesture.svg" alt="Ferris says Hello" w=600 h=400) }}\n\nOutput\n \n<img src="img/ferris-gesture.svg" alt="Ferris says Hello" width="600" height="400" />\n\n\n \n\nUsage (root path /)\n{{ img(src="/overview-rich-content/ferris.svg" alt="Ferris the Rustacean" w=600 h=400) }}\n\nOutput\n \n<img src="https://abridge.netlify.app/overview-rich-content/ferris.svg" alt="Ferris the Rustacean" width="600" height="400" />\n\n\n \n\nSVG image directly in code:\n<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 489" width="600" height="489"><g fill="#8f1f1d"><path d="M70 324c1 3 3 4 6 4l24 4 2 5-10 20v5l7 4 24-1 4 4-7 21c0 2 0 4 3 6 1 2 4 2 7 2l24-5 4 4-1 22c-1 2 0 4 3 5h6l23-8 6 3 4 22c0 2 1 3 3 4h7l21-13 6 2 8 20 5 5c3 0 5 0 7-2l18-15h5l13 18c1 2 3 4 6 4l5-3 14-18h6l17 16c1 1 4 2 6 1 3 0 5-1 6-3l9-21 6-1 19 14h7c3 0 5-3 5-5l4-21 6-2 22 9 7-1c2-1 3-2 3-5v-21l5-4 24 6c3 0 5 0 6-2 2-2 3-4 2-6l-4-21 3-5 24 2c4 0 6 0 7-3v-5l-9-21 3-5 25-2 5-5-1-5-14-18c0-1-1-19-12-33v-1c-26-36-106-64-201-65-100-2-184 26-206 64-10 10-12 26-11 26l-15 17c-1 3-2 5-1 7z"/><path d="M565 247c-1-3-12-2-14-3l-38 1-4-7 26-38c1-2 7-7 6-9-3-3-12 1-14 1l-39 7-4-6 22-49c0-3 7-15 5-18-2-2-11 6-13 6l-43 28-4-5 11-43c0-3 7-18 5-19-2-2-9 5-12 6l-38 30-5-4 9-51c0-3 3-18 1-19s-15 13-17 14l-30 38-6-3-3-56c0-3 0-14-3-14-3-1-5 8-8 11l-25 50-7-1-13-57c-1-3-2-12-4-12-4 0-5 10-7 13l-15 56-7 1-22-52c-1-2-4-12-7-12-3 1-2 9-3 12l-7 61-6 3-19-27c-3-1-15-19-18-18-2 1 0 21-1 23l1 40-6 4-36-35c-3-1-7-7-10-5-2 2 0 10 0 13l13 53-4 5-41-26c-2-1-10-7-12-4-2 2 3 4 3 7l22 56-5 6-65-22c-3-1-10-5-12-1-1 2 5 6 6 9l49 53-3 7-47-6c-3 0-9-1-11 1-1 4 6 7 7 9l36 40a116 116 0 0 0 14 46c27 50 110 87 209 87 105 0 193-41 214-95 11-15 13-37 12-38l29-31c2-4 9-9 8-11z"/><path d="m99 289-67 10c-13 3-5 5 0 6 14 2 84 3 85 4zm402 3 67 10c13 4 5 6 0 6-14 2-84 5-86 5z"/></g><path d="M227 293s-24-26-47 0c0 0-18 35 0 52 0 0 30 24 47 0 0 0 21-20 0-52z"/><path fill="#fff" d="M200 302c0 11 6 19 14 19 7 0 12-8 12-19 0-10-5-18-12-18-8 0-14 8-14 18z"/><path d="M360 283s-40-17-52 22c0 0-11 47 33 49 0 0 58-10 19-71z"/><path fill="#fff" d="M339 299c0 10 7 20 14 20 8 0 14-10 14-20s-6-18-14-18c-7 0-14 8-14 18z"/></svg>\n\n\nimghover Shortcode\nThe first image in the src array is the one compared to all the others.\nWhen you hover your mouse over an image it will display the image to compare.\nThis can be used to compare only one image with another by passing only two src in the array.\n\nsrc is an array of paths and filenames for the images. (mandatory)\nw is the width of the image.\nh is the height of the image.\np is the percent size that you want the image to use on the page. (50 is the default)\n\nw and h are used only to calculate the aspect ratio, overall size is set by p\nUsage (same path)\n{{ imghover(src=["ferris.svg", "ferris-gesture.svg", "ferris-happy.svg"] w=600 h=400 p=45) }}\n\nOutput\n \n <div id="same-ferris-gesture"><b>same-ferris-gesture on hover</b></div>\n <div id="same-ferris-gestureimage" title="same-ferris-gesture"> </div> \n <div id="same-ferris-happy"><b>same-ferris-happy on hover</b></div>\n <div id="same-ferris-happyimage" title="same-ferris-happy"> </div>\n\n<style> \n #same-ferris-gestureimage {\n background-image: url(\'ferris.svg\');\n background-size: contain;\n background-repeat: no-repeat;\n width: 45%;\n height: 0;\n padding-top: 30%;\n\n }\n #same-ferris-gestureimage:hover {\n background-image: url(\'ferris-gesture.svg\');\n } \n #same-ferris-happyimage {\n background-image: url(\'ferris.svg\');\n background-size: contain;\n background-repeat: no-repeat;\n width: 45%;\n height: 0;\n padding-top: 30%;\n\n }\n #same-ferris-happyimage:hover {\n background-image: url(\'ferris-happy.svg\');\n }\n</style>\n\n\n \n same-ferris-gesture on hover\n \n same-ferris-happy on hover\n \n\n\nUsage (relative path ./)\n{{ imghover(src=["./img/ferris.svg", "./img/ferris-gesture.svg"] w=600 h=400 p=45) }}\n\nOutput\n \n <div id="rel-ferris-gesture"><b>rel-ferris-gesture on hover</b></div>\n <div id="rel-ferris-gestureimage" title="rel-ferris-gesture"> </div>\n\n<style> \n #rel-ferris-gestureimage {\n background-image: url(\'img/ferris.svg\');\n background-size: contain;\n background-repeat: no-repeat;\n width: 45%;\n height: 0;\n padding-top: 30%;\n\n }\n #rel-ferris-gestureimage:hover {\n background-image: url(\'img/ferris-gesture.svg\');\n }\n</style>\n\n\n \n rel-ferris-gesture on hover\n \n\n\nUsage (root path /)\n{{ imghover(src=["/overview-rich-content/ferris.svg", "/overview-rich-content/ferris-gesture.svg"] w=600 h=400 p=45) }}\n\nOutput\n \n <div id="root-ferris-gesture"><b>root-ferris-gesture on hover</b></div>\n <div id="root-ferris-gestureimage" title="root-ferris-gesture"> </div>\n\n<style> \n #root-ferris-gestureimage {\n background-image: url(\'https://abridge.netlify.app/overview-rich-content/ferris.svg\');\n background-size: contain;\n background-repeat: no-repeat;\n width: 45%;\n height: 0;\n padding-top: 30%;\n\n }\n #root-ferris-gestureimage:hover {\n background-image: url(\'https://abridge.netlify.app/overview-rich-content/ferris-gesture.svg\');\n }\n</style>\n\n\n \n root-ferris-gesture on hover\n \n\n\n',id:"https://abridge.netlify.app/overview-images/",title:"Image Shortcodes"},"https://abridge.netlify.app/overview-markdown-and-style/":{body:'This article offers a sample of basic Markdown syntax that can be used in Zola content files, also it shows if basic HTML elements are decorated with CSS in a Zola theme.\nHeadings\nThe following HTML <h1>—<h6> elements represent six levels of section\nheadings. <h1> is the highest section level while <h6> is the lowest.\nH1\nH2\nH3\nH4\nH5\nH6\nParagraph\nXerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum,\nvoluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma\ndolestendit peritin re plis aut quas inctum laceat est volestemque commosa as\ncus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin\nporecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur?\nQuiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit\nut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda\nveliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore\neost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata\ntiustia prat.\nItatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne\nsapicia is sinveli squiatum, core et que aut hariosam ex eat.\nBlockquotes\nThe blockquote element represents content that is quoted from another source,\noptionally with a citation which must be within a footer or cite element,\nand optionally with in-line changes such as annotations and abbreviations.\nBlockquote no attribution\n\nTiam, ad mint andaepu dandae nostion secatur sequo quae.\nNote that you can use Markdown syntax within a blockquote.\n\nBlockquote with attribution\n\nDon\'t communicate by sharing memory, share memory by communicating.\n— Rob Pike1\n\n\nAll men by nature desire to know.\n― Aristotle2\n\n\nPower comes in response to a need, not a desire.\n— Goku\n\nTables\nTables aren\'t part of the core Markdown spec, but Zola supports them\nout-of-the-box.\nNameAge\nAlice23\nBob27\nCody33\nJohn59\nKerry23\n\nTable with Inline Markdown\nItalicsBoldCodeStrikeThrough\nitalicsboldcodestrikethrough\n\nLarge table within figure tag\nSurround very Large tables with <figure></figure> so they can scroll horizontally.\n\nManufacturerVolkswagenToyotaFordHondaChevroletBMWHyundaiAudiNissanKiaMercedesTeslaMitsubishiSuzukiVolvoSubaruMazdaJaguarBuickLexusGMCPorscheCadillac\nRevenue $B$254$249$127$124$123$113$88$83$74$61$55$54$38$31$30$28$27$22$21$19$17$16$12\n\n\n*revenue values found on search engine and not verified, for figure scroller table demonstration purposes only.*\nFoldable Text\n\n Title 1\n IT\'S A SECRET TO EVERYBODY.\n\n\n Title 2\n Stay awhile, and listen!\n\nCode Blocks\nCode blocks.. ❤️ with automatic syntax highlighting ✨‍\nSee the docs for options.\nCode block with backticks\n<!doctype html>\n<html lang="en">\n<head>\n <meta charset="utf-8">\n <title>Example HTML5 Document</title>\n</head>\n<body>\n <p>Test</p>\n</body>\n</html>\n\nLine Numbers, Highlighting\n1<!doctype html>\n2<html lang="en">\n3<head>\n4 <meta charset="utf-8">\n5 <title>Example HTML5 Document</title>\n6</head>\n7<body>\n8 <p>Test</p>\n9</body>\n10</html>\n\nInline Code block\nIf we want, we can also specify inline code which is useful for the small stuff.\nList Types\nOrdered List\n\nFirst item\nSecond item\nThird item\n\nUnordered List\n\nList item\nAnother item\nAnd another item\n\nNested list\n\nFruit\n\nApple\nOrange\nBanana\n\n\nDairy\n\nMilk\nCheese\n\n\n\nOther Elements — abbr, sub, sup, kbd, mark, link\nGIF is a bitmap image format.\nH2O\nXn + Yn = Zn\nPress CTRL+ALT+Delete to end the\nsession.\nMost salamanders are nocturnal, and hunt for insects, worms, and\nother small creatures.\n\n\n1\nThe above quote is excerpted from Rob Pike\'s talk\nduring Gopherfest, November 18, 2015.\n\n2\nThe quote is the first sentence of Aristotle\'s Metaphysics.\n\nNavs\nSite primary menu is created by nesting the nav under a header tag. Refer to the top of this site for an example.\nIf the nav tag is under the main tag instead of the header tag then the links will have a border:\n\n \n \n < Previous\n Next >\n \n \n\nForms\n\n Name\n \n \n Email Address\n \n \n Message\n \n \n \n Send\n \n \n Fruit\n \n Select a fruit…\n Banana\n Watermelon\n Apple\n Orange\n Mango\n \n \n \n Size\n \n \n Small\n \n \n \n Medium\n \n \n \n Large\n \n \n \n Extra Large\n \n \n \n \n \n \n I agree to the Terms and Conditions\n \n \n \n I agree to share my information with partners\n \n \n \n \n \n \n Publish on my profile\n \n \n \n Publish on my profile my accomplishments\n \n \n \n \n \n \n File browser\n \n \n \n Range slider\n \n \n \n Date\n \n \n \n Time\n \n \n \n Color\n \n \n\n',id:"https://abridge.netlify.app/overview-markdown-and-style/",title:"Markdown and Style Guide"},"https://abridge.netlify.app/overview-math/":{body:'You can use KaTeX to render mathematical notations.\nYou can enable the $\\KaTeX$ support globally, per-section or per-page basis.\nEnable Globally\nTo enable the $\\KaTeX$ support globally, add math = true under [extra] of the config.toml\nat your site root. Now the katex shortcode will be rendered, you can also add math_auto_render = true\nand every section and page of your site will load the KaTeX autorender extension.\n[extra]\nmath = true\nmath_auto_render = false\n\nPer-section Basis\nTo enable the $\\KaTeX$ support in a particular section, add math = true under [extra] in the [SECTION_NAME]/_index.md.\nNow the katex shortcode will be rendered, you can also add math_auto_render = true\nand the section of your site will load the KaTeX autorender extension.\n+++\n[extra]\nmath = true\n+++\n\nPer-page Basis\nTo enable the $\\KaTeX$ support in a particular page, add math = true under [extra] in the page\'s\nfrontmatter. Now the katex shortcode will be rendered, you can also add math_auto_render = true\nand the page of your site will load the KaTeX autorender extension.\n+++\n[extra]\nmath = true\nmath_auto_render = true\n+++\n\nIt is a good practice to enable $\\KaTeX$ support on a per-page basis, since this will only load the\nrequired files on that particular page, without affecting the page load speed of other pages.\nIf your site is not math-heavy, please do NOT enable this feature globally or per-section basis.\nUsage\nWrap any valid $\\KaTeX$ syntax with $...$ for inline\nMathematics and $$...$$ for block Mathematics.\nInline Mathematics\nThis is the most beautiful equation I\'ve ever seen:\nUsage\n{% katex(block=false) %} e^{i\\pi}+1=0 {% end %}\n\nOutput\n<script type="math/tex">e^{i\\pi}+1=0</script>\n\n\n\nBlock Mathematics\nSome Mathematics in display mode is fair enough:\nUsage\n{% katex(block=true) %} \\int_0^1 x^2 dx {% end %}\n\nOutput\n<script type="math/tex;mode=display">\\int_0^1 x^2 dx</script>\n\n\n\nAuto Render Inline Example\n$ e^{i\\pi}+1=0 $\n\n$ e^{i\\pi}+1=0 $\nAuto Render Block Example\n$$\nf(x) = \\int_{-\\infty}^\\infty\\hat f(\\xi)\\,e^{2 \\pi i \\xi x}\\,d\\xi\n$$\n\n$$\nf(x) = \\int_{-\\infty}^\\infty\\hat f(\\xi),e^{2 \\pi i \\xi x},d\\xi\n$$\n',id:"https://abridge.netlify.app/overview-math/",title:"Mathematical Notations"},"https://abridge.netlify.app/overview-rich-content/":{body:'Several custom shortcodes are included to augment CommonMark (courtesy of d3c3nt theme), in addition to those already provided by Zola. video, image, gif, and audio were created to help you take advantage of modern HTML elements in your writing.\nVideo\nThe video shortcode takes a sources parameter (an array of strings)\nand returns a <video> tag. Each string in the sources array should\nbe a path to a video file of a different type (webm, mp4, etc). Each\nindividual source is then converted into a <source> tag, and the\nelement is returned.\nUsage\n{{ video(sources=["over9000_av1.mp4", "over9000_vp9.webm"]) }}\n\nOutput\n<video controls>\n <source src="https://abridge.netlify.app/overview-rich-content/over9000_av1.mp4" type="video/mp4" />\n <source src="https://abridge.netlify.app/overview-rich-content/over9000_vp9.webm" type="video/webm" />\n Your browser doesn\'t support the video tag and/or the video formats in use here – sorry!\n</video>\n\n\n\n \n \n Your browser doesn\'t support the video tag and/or the video formats in use here – sorry!\n\nImage\nThe image shortcode returns a <picture> tag and accepts three\nparameters: sources (an array of strings), fallback_path, and\nfallback_alt (both strings).\nEach string in the sources array should be a path to an image file of\na different type (webp, png, jpg, etc). fpath and\nfalt are used to create an <img> tag for the browser to fall\nback on if the other formats aren\'t yet supported, fw and fh set the width and height of the fallback\nUsage\n{{ image(sources=["over9000-960.webp", "over9000-640.webp", "over9000-400.webp"], fpath="over9000-640.webp", fw=640, fh=480, falt="ITS OVER 9000!") }}\n\nOutput\n<picture>\n <source srcset="https://abridge.netlify.app/overview-rich-content/over9000-960.webp" type="img/webp" />\n <source srcset="https://abridge.netlify.app/overview-rich-content/over9000-640.webp" type="img/webp" />\n <source srcset="https://abridge.netlify.app/overview-rich-content/over9000-400.webp" type="img/webp" />\n <img src="over9000-640.webp" alt="ITS OVER 9000!" width="640" height="480" />\n</picture>\n\n\n\n \n \n \n \n\nGIF\nThe gif shortcode is exactly the same as the video shortcode\n– it takes an array of strings called sources and returns a\n<video> tag. The only difference is in the outermost tag, which has\nfour additional properties: autoplay, loop, muted, playsinline.\nUsing the <video> tag in place of gifs allows for reduced file sizes,\nwhich is especially important in regions where internet is slower or\nless reliable.\nUsage\n{{ gif(sources=["over9000_av1.mp4", "over9000_vp9.webm"]) }}\n\nOutput\n<video autoplay loop muted playsinline>\n <source src="https://abridge.netlify.app/overview-rich-content/over9000_av1.mp4" type="video/mp4" />\n <source src="https://abridge.netlify.app/overview-rich-content/over9000_vp9.webm" type="video/webm" />\n Your browser doesn\'t support the video tag, which I use in place of .gifs, and/or the video formats in use here – sorry!\n</video>\n\n\n\n \n \n Your browser doesn\'t support the video tag, which I use in place of .gifs, and/or the video formats in use here – sorry!\n\nAudio\nThe audio shortcode takes a sources array of strings and returns an\n<audio> tag. Each string in the sources array should be a path to an\naudio file of a different type (ogg, mp3, flac, wav, etc).\nThe browser will play the first type it supports, so placing them in order of size smallest to largest will use the least bandwidth if that is your goal.\nUsage\n{{ audio(sources=["over9000.ogg", "over9000.mp3", "over9000.flac", "over9000.wav"]) }}\n\nOutput\n<audio controls>\n <source src="https://abridge.netlify.app/overview-rich-content/over9000.ogg" type="audio/ogg" />\n <source src="https://abridge.netlify.app/overview-rich-content/over9000.mp3" type="audio/mp3" />\n <source src="https://abridge.netlify.app/overview-rich-content/over9000.flac" type="audio/flac" />\n <source src="https://abridge.netlify.app/overview-rich-content/over9000.wav" type="audio/wav" />\n Your browser doesn\'t support the audio tag and/or the audio formats in use here – sorry!\n</audio>\n\n\n\n \n \n Your browser doesn\'t support the audio tag and/or the audio formats in use here – sorry!\n\n',id:"https://abridge.netlify.app/overview-rich-content/",title:"Rich Content"},"https://abridge.netlify.app/pages/":{body:"",id:"https://abridge.netlify.app/pages/",title:""},"https://abridge.netlify.app/posts/":{body:"",id:"https://abridge.netlify.app/posts/",title:"posts"},"https://abridge.netlify.app/privacy/":{body:"Privacy\n\nThis site does not set or use cookies.\nThis site does not store data in the browser to be shared, sent, or sold to third-parties.\nNo personal information is shared, sent, or sold to third-parties.\n\nEffective Date: 1st Jan 2022\n",id:"https://abridge.netlify.app/privacy/",title:"Privacy Policy"}},docInfo:{"https://abridge.netlify.app/":{body:0,title:0},"https://abridge.netlify.app/about/":{body:63,title:0},"https://abridge.netlify.app/contact/":{body:0,title:1},"https://abridge.netlify.app/overview-abridge/":{body:96,title:3},"https://abridge.netlify.app/overview-code-blocks/":{body:627,title:3},"https://abridge.netlify.app/overview-embedded-vimeo/":{body:59,title:3},"https://abridge.netlify.app/overview-embedded-youtube/":{body:50,title:3},"https://abridge.netlify.app/overview-images/":{body:953,title:2},"https://abridge.netlify.app/overview-markdown-and-style/":{body:488,title:3},"https://abridge.netlify.app/overview-math/":{body:203,title:2},"https://abridge.netlify.app/overview-rich-content/":{body:375,title:2},"https://abridge.netlify.app/pages/":{body:0,title:0},"https://abridge.netlify.app/posts/":{body:0,title:1},"https://abridge.netlify.app/privacy/":{body:26,title:2}},length:14},lang:"English"},function(){function b(d){var e=new b.Index;return e.pipeline.add(b.trimmer,b.stopWordFilter,b.stemmer),d&&d.call(e,e),e}var r,n,d,e,p,l,v,h,g,y,w,m,u,k,x,S,_,I,T,$,E,C,F,q,o;b.version="0.9.5",((lunr=b).utils={}).warn=(o=this,function(d){o.console&&console.warn&&console.warn(d)}),b.utils.toString=function(d){return null==d?"":d.toString()},(b.EventEmitter=function(){this.events={}}).prototype.addListener=function(){var d=Array.prototype.slice.call(arguments),e=d.pop();if("function"!=typeof e)throw new TypeError("last argument must be a function");d.forEach(function(d){this.hasHandler(d)||(this.events[d]=[]),this.events[d].push(e)},this)},b.EventEmitter.prototype.removeListener=function(d,e){this.hasHandler(d)&&-1!==(e=this.events[d].indexOf(e))&&(this.events[d].splice(e,1),0==this.events[d].length&&delete this.events[d])},b.EventEmitter.prototype.emit=function(d){var e;this.hasHandler(d)&&(e=Array.prototype.slice.call(arguments,1),this.events[d].forEach(function(d){d.apply(void 0,e)},this))},b.EventEmitter.prototype.hasHandler=function(d){return d in this.events},(b.tokenizer=function(d){return arguments.length&&null!=d?Array.isArray(d)?(e=(e=d.filter(function(d){return null!=d})).map(function(d){return b.utils.toString(d).toLowerCase()}),o=[],e.forEach(function(d){d=d.split(b.tokenizer.seperator);o=o.concat(d)},this),o):d.toString().trim().toLowerCase().split(b.tokenizer.seperator):[];var e,o}).defaultSeperator=/[\s\-]+/,b.tokenizer.seperator=b.tokenizer.defaultSeperator,b.tokenizer.setSeperator=function(d){null!=d&&"object"==typeof d&&(b.tokenizer.seperator=d)},b.tokenizer.resetSeperator=function(){b.tokenizer.seperator=b.tokenizer.defaultSeperator},b.tokenizer.getSeperator=function(){return b.tokenizer.seperator},(b.Pipeline=function(){this._queue=[]}).registeredFunctions={},b.Pipeline.registerFunction=function(d,e){e in b.Pipeline.registeredFunctions&&b.utils.warn("Overwriting existing registered function: "+e),d.label=e,b.Pipeline.registeredFunctions[e]=d},b.Pipeline.getRegisteredFunction=function(d){return d in b.Pipeline.registeredFunctions!=1?null:b.Pipeline.registeredFunctions[d]},b.Pipeline.warnIfFunctionNotRegistered=function(d){d.label&&d.label in this.registeredFunctions||b.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",d)},b.Pipeline.load=function(d){var o=new b.Pipeline;return d.forEach(function(d){var e=b.Pipeline.getRegisteredFunction(d);if(!e)throw new Error("Cannot load un-registered function: "+d);o.add(e)}),o},b.Pipeline.prototype.add=function(){Array.prototype.slice.call(arguments).forEach(function(d){b.Pipeline.warnIfFunctionNotRegistered(d),this._queue.push(d)},this)},b.Pipeline.prototype.after=function(d,e){b.Pipeline.warnIfFunctionNotRegistered(e);d=this._queue.indexOf(d);if(-1===d)throw new Error("Cannot find existingFn");this._queue.splice(d+1,0,e)},b.Pipeline.prototype.before=function(d,e){b.Pipeline.warnIfFunctionNotRegistered(e);d=this._queue.indexOf(d);if(-1===d)throw new Error("Cannot find existingFn");this._queue.splice(d,0,e)},b.Pipeline.prototype.remove=function(d){d=this._queue.indexOf(d);-1!==d&&this._queue.splice(d,1)},b.Pipeline.prototype.run=function(d){for(var e=[],o=d.length,t=this._queue.length,s=0;si[t]&&t++:(e.add(c[o]),o++,t++);return e},lunr.SortedSet.prototype.clone=function(){var d=new lunr.SortedSet;return d.elements=this.toArray(),d.length=d.elements.length,d},lunr.SortedSet.prototype.union=function(d){for(var e,d=this.length>=d.length?(e=this,d):(e=d,this),o=e.clone(),t=0,s=d.toArray();t",a=o.querySelector("a"),t=o.querySelector("span:first-child"),d=o.querySelector("span:nth-child(2)"),a.href=e.ref,t.textContent=e.doc.title,d.innerHTML=function(d,e){var o=e.map(function(d){return elasticlunr.stemmer(d.toLowerCase())}),t=!1,s=0,f=[],c=d.toLowerCase().split(". ");for(h in c){var i,a=c[h].split(/[\s\n]/),r=8;for(i in a){if(0<(u=a[i]).length){for(var n in o)elasticlunr.stemmer(u).startsWith(o[n])&&(r=40,t=!0);f.push([u,r,s]),r=2}s=s+u.length+1}s+=1}if(0===f.length)return void 0!==d.length&&300b&&(b=p[h],g=h);for(var y=[],w=f[g][2],h=g;h"),w=u[2]+u[0].length;40!==u[1]&&12<=u[0].length&&!/^[\x00-\xff]+$/.test(u[0])?(m=substringByByte(d.substring(u[2],w),12),y.push(m)):y.push(d.substring(u[2],w)),40===u[1]&&y.push("
                                                              ")}return y.push("…"),y.join("")}(e.doc.body,i),suggestions.appendChild(o))});for(;f.length>c;)suggestions.removeChild(f[0])},!0),suggestions.addEventListener("click",function(){for(;suggestions.lastChild;)suggestions.removeChild(suggestions.lastChild);return!1},!0),document.body.contains(document.goSearch)&&(document.goSearch.onsubmit=function(){return goSearchNow()})}(); \ No newline at end of file diff --git a/search_bundle_stork.min.js b/search_bundle_stork.min.js new file mode 100644 index 000000000..5a86067f1 --- /dev/null +++ b/search_bundle_stork.min.js @@ -0,0 +1 @@ +var stork;function loadStork(){var e=document.querySelector("meta[name='base']").getAttribute("content");"/"==e.slice(-1)&&(e=e.slice(0,-1)),stork.initialize(e+"/stork.wasm").then(()=>{console.log("Finished downloading WASM")}).catch(e=>{console.error(e)}),stork.register("stork",e+"/stork.st")}(()=>{"use strict";var n={214:(e,t,o)=>{let u;o.r(t),o.d(t,{default:()=>v,wasm_register_index:()=>function(e,t){try{var n=u.__wbindgen_add_to_stack_pointer(-16),r=f(e,u.__wbindgen_malloc,u.__wbindgen_realloc),o=c,s=function(e){var t=(0,u.__wbindgen_malloc)(+e.length);return d().set(e,+t),c=e.length,t}(t),i=c,a=(u.wasm_register_index(n,r,o,s,i),g()[n/4+0]),l=g()[n/4+1];return m(a,l)}finally{u.__wbindgen_add_to_stack_pointer(16),u.__wbindgen_free(a,l)}},wasm_search:()=>function(e,t){try{var n=u.__wbindgen_add_to_stack_pointer(-16),r=f(e,u.__wbindgen_malloc,u.__wbindgen_realloc),o=c,s=f(t,u.__wbindgen_malloc,u.__wbindgen_realloc),i=c,a=(u.wasm_search(n,r,o,s,i),g()[n/4+0]),l=g()[n/4+1];return m(a,l)}finally{u.__wbindgen_add_to_stack_pointer(16),u.__wbindgen_free(a,l)}},wasm_stork_version:()=>function(){try{var e=u.__wbindgen_add_to_stack_pointer(-16),t=(u.wasm_stork_version(e),g()[e/4+0]),n=g()[e/4+1];return m(t,n)}finally{u.__wbindgen_add_to_stack_pointer(16),u.__wbindgen_free(t,n)}}});const s=new Array(32).fill(void 0);function i(e){return s[e]}s.push(void 0,null,!0,!1);let a=s.length,c=0,n=null;function d(){return n=null!==n&&n.buffer===u.memory.buffer?n:new Uint8Array(u.memory.buffer)}let l=new TextEncoder("utf-8");const h="function"==typeof l.encodeInto?function(e,t){return l.encodeInto(e,t)}:function(e,t){var n=l.encode(e);return t.set(n),{read:e.length,written:n.length}};function f(e,t,n){if(void 0===n){const n=l.encode(e),r=t(n.length);return d().subarray(r,r+n.length).set(n),c=n.length,r}let r=e.length,o=t(r);const s=d();let i=0;for(;i{Object.defineProperty(l,"__esModule",{value:!0}),l.calculateOverriddenConfig=l.defaultConfig=void 0;var u=t(445),c=t(466);l.defaultConfig={showProgress:!0,printIndexInfo:!1,showScores:!1,showCloseButton:!0,minimumQueryLength:3,forceOverwrite:!1,resultNoun:{singular:"file",plural:"files"},onQueryUpdate:void 0,onResultSelected:void 0,onResultsHidden:void 0,onInputCleared:void 0,transformResultUrl:function(e){return e}},l.calculateOverriddenConfig=function(e){var t,n=(0,c.difference)(Object.keys(e),Object.keys(l.defaultConfig));if(0{Object.defineProperty(t,"__esModule",{value:!0}),t.existsBeyondContainerBounds=t.setText=t.clear=t.add=t.create=void 0,t.create=function(e,t){e=document.createElement(e);return t.classNames&&e.setAttribute("class",t.classNames.join(" ")),e},t.add=function(e,t,n){n.insertAdjacentElement(t,e)},t.clear=function(e){for(;e&&e.firstChild;)e.removeChild(e.firstChild)},t.setText=function(e,t){t=document.createTextNode(t);e&&e.firstChild?e.replaceChild(t,e.firstChild):e&&e.appendChild(t)},t.existsBeyondContainerBounds=function(e,t){e=e.getBoundingClientRect(),t=t.getBoundingClientRect();return e.bottom>t.bottom||e.top{Object.defineProperty(t,"__esModule",{value:!0}),t.Entity=void 0;var r=n(139),o=n(771),s=n(214),i=n(445);function a(e,t,n){var r=this;this._state="initialized",this.downloadProgress=0,this.results=[],this.totalResultCount=0,this.eventListenerFunctions={},this.highlightedResult=0,this.resultsVisible=!1,this.hoverSelectEnabled=!0,this.setDownloadProgress=function(e){r.state="loading",r.downloadProgress=e,r.config.showProgress&&r.render()},this.name=e,this.url=t,this.config=n}Object.defineProperty(a.prototype,"state",{get:function(){return this._state},set:function(e){this._state=e,this.render()},enumerable:!1,configurable:!0}),a.prototype.getCurrentMessage=function(){if(!this.domManager)return null;var e=this.domManager.getQuery();return"error"===this.state?"Error! Check the browser console.":"ready"!=this.state?"Loading...":(null==e?void 0:e.length){Object.defineProperty(t,"__esModule",{value:!0}),t.EntityDom=void 0;var a=n(227),i=n(9),o={results:[],resultsVisible:!1,showScores:!1,message:null,showProgress:!1,progress:1,state:"ready"};function r(n,e){var r=this,e=(this.scrollAnchorPoint="end",this.entity=e,[{selector:'input[data-stork="'.concat(n,'"]'),elementName:"input"},{selector:'div[data-stork="'.concat(n,'-output"]'),elementName:"output"}].map(function(e){var t=document.querySelector(e.selector);if(t)return t;throw new Error('Could not register search box "'.concat(n,'": ').concat(e.elementName," element not found. Make sure an element matches the query selector `").concat(e.selector,"`"))})),t=e[0],e=e[1];this.elements={input:t,output:e,list:(0,a.create)("ul",{classNames:["stork-results"]}),attribution:(0,a.create)("div",{classNames:["stork-attribution"]}),progress:(0,a.create)("div",{classNames:["stork-progress"]}),message:(0,a.create)("div",{classNames:["stork-message"]}),closeButton:(0,a.create)("button",{classNames:["stork-close-button"]})},this.elements.input.removeEventListener("input",this.entity.eventListenerFunctions.inputInputEvent),this.elements.input.removeEventListener("keydown",this.entity.eventListenerFunctions.inputKeydownEvent),this.entity.eventListenerFunctions={inputInputEvent:function(e){r.handleInputEvent(e)},inputKeydownEvent:function(e){r.handleKeyDownEvent(e)}},this.elements.input.addEventListener("input",this.entity.eventListenerFunctions.inputInputEvent),this.elements.input.addEventListener("keydown",this.entity.eventListenerFunctions.inputKeydownEvent),null!=(t=this.elements.list)&&t.addEventListener("mousemove",function(){r.hoverSelectEnabled=!0}),this.elements.attribution.innerHTML='Powered by Stork',this.elements.closeButton.innerHTML='\n\n\n\n\n\n\n\n',this.entity.config.showProgress&&(0,a.add)(this.elements.progress,"afterend",this.elements.input),null!=(e=this.elements.closeButton)&&e.addEventListener("click",function(){r.elements.input.value="",r.elements.input.focus(),r.render(o);var e=[r.entity.config.onInputCleared,r.entity.config.onResultsHidden],t=e[0],e=e[1];t&&t(),e&&e()})}r.prototype.clearDom=function(){var e;(0,a.clear)(this.elements.output),(0,a.clear)(this.elements.list),null!=(e=this.elements.closeButton)&&e.remove(),this.elements.output.classList.remove("stork-output-visible")},r.prototype.render=function(r){var e,o=this,t=this.elements.input.value;if(this.clearDom(),(this.lastRenderState=r).showProgress&&((e=function(){switch(r.state){case"ready":case"error":return 1;case"initialized":case"loading":return.9*r.progress+.05}}())<1?(this.elements.progress.style.width="".concat(100*e,"%"),this.elements.progress.style.opacity="1"):(this.elements.progress.style.width="100%",this.elements.progress.style.opacity="0")),"error"===r.state&&this.elements.input.classList.add("stork-error"),0{Object.defineProperty(t,"__esModule",{value:!0}),t.loadIndexFromUrl=void 0,t.loadIndexFromUrl=function(e,r){var t=new XMLHttpRequest;t.addEventListener("load",function(e){var t=e.target,n=t.status,t=t.response;0!==n?n<200||299{Object.defineProperty(t,"__esModule",{value:!0}),t.highlight=void 0,t.highlight=function(e,t){function n(e,t,n){return e.substr(0,t)+n+e.substr(t)}for(var r=0,o=0,s=t;o',l="";e=n(e,i.beginning+r,a),r+=a.length,e=n(e,i.end+r,l),r+=l.length}return e}},9:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.resultToListItem=void 0;var r=n(112);t.resultToListItem=function(e,t){var n=document.createElement("template");return n.innerHTML='\n
                                                            • \n \n
                                                              \n

                                                              ').concat((0,r.highlight)(e.entry.title,e.title_highlight_ranges||[]),"

                                                              \n ").concat(t.showScores?"".concat(e.score,""):"","\n
                                                              \n ").concat(0':"","\n ").concat(e.excerpts.map(function(e){return'

                                                              \n ...'.concat((0,r.highlight)(e.text,e.highlight_ranges||[]),"...\n

                                                              \n ").concat(t.showScores?"".concat(e.score,""):"","\n
                                                              ")}).join(""),"\n ").concat(0":"","\n
                                                              \n
                                                            • "),n.content.firstElementChild}},139:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.resolveSearch=void 0;var o=n(214),s=n(445);t.resolveSearch=function(e,t){var n=null,r=null;try{n=(0,o.wasm_search)(e,t),r=JSON.parse(n)}catch(e){throw new s.default("Could not parse data from wasm_search. If you see this, please file a bug: https://jil.im/storkbug "+n)}if(!r)throw new s.default("Data was an empty object");if(r.error)throw new s.default("Could not perform search: the WASM binary failed to return search results.\n You might not be serving your search index properly.\n If you think this is an error, please file a bug: https://jil.im/storkbug\n \n The WASM binary came back with:\n ".concat(r.error));return r}},445:function(e,t){var r,n,o=this&&this.__extends||(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),o=(Object.defineProperty(t,"__esModule",{value:!0}),n=Error,o(s,n),s);function s(e){e=n.call(this,e)||this;return e.name="StorkError",e}t.default=o},466:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.plural=t.difference=t.htmlToElement=void 0,t.htmlToElement=function(e){var t=document.createElement("template");return e=e.trim(),t.innerHTML=e,t.content.firstChild},t.difference=function(e,t){var e=new Set(e),n=new Set(t),t=new Set(Array.from(e).filter(function(e){return!n.has(e)}));return Array.from(t)},t.plural=function(e,t,n){return 1==e?t:n}},34:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.validateIndexParams=void 0;var r=n(445);t.validateIndexParams=function(e,t){return"string"!=typeof e?new r.default("Index registration name must be a string."):"string"!=typeof t?new r.default("URL must be a string."):null}},258:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.debug=t.loadWasm=t.runAfterWasmLoaded=void 0;var r=n(214),o=n(445),s="https://files.stork-search.net/releases/v".concat("1.5.0","/stork.wasm"),i=null,a=null,l=[],u=[],c=(t.loadWasm=function(e){if(a)return a;var t=(e=void 0===e?null:e)||s,e=(i=t,(0,r.default)(t).then(function(){return c(),t}).catch(function(){throw d(),new o.default("Error while loading WASM at ".concat(t))}));return a=e},t.runAfterWasmLoaded=function(e,t){return a?(a.then(function(){return e()}).catch(function(){return t()}),a):(l.push(e),u.push(t),null)},function(){l.forEach(function(e){e()}),l=[]}),d=function(){u.forEach(function(e){e()}),u=[]};t.debug=function(){return{wasmSourceUrl:i,wasmLoadPromise:a,queueLength:l.length}}}},r={};function o(e){var t=r[e];if(void 0!==t)return t.exports;t=r[e]={exports:{}};return n[e].call(t.exports,t,t.exports,o),t.exports}o.d=(e,t)=>{for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.g.importScripts&&(e=o.g.location+"");var e,t=o.g.document;if(e||!t||(e=t.currentScript?t.currentScript.src:e)||(t=t.getElementsByTagName("script")).length&&(e=t[t.length-1].src),!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),o.p=e;t=o(480);stork=t})(),loadStork(); \ No newline at end of file diff --git a/search_bundle_tinysearch.min.js b/search_bundle_tinysearch.min.js new file mode 100644 index 000000000..bb74dd44f --- /dev/null +++ b/search_bundle_tinysearch.min.js @@ -0,0 +1 @@ +function closeSearchNow(){const e=document.querySelector("main");e.innerHTML=window.main}function goSearchNow(){const e=document.querySelector("main");window.main||(window.main=e.innerHTML);var t=document.getElementById("suggestions"),n=t.cloneNode(!0),o=(n.id="results",document.createElement("div")),a='

                                                              Results For: '.concat(document.getElementById("searchinput").value,"

                                                              ");return o.innerHTML=a,n.insertBefore(o,n.firstChild),e.innerHTML=n.outerHTML,t.innerHTML="",document.getElementById("searchinput").value="",document.body.contains(document.closeSearch)&&(document.closeSearch.onsubmit=function(){closeSearchNow()}),!1}async function lazyLoad(){var e=document.querySelector("meta[name='base']").getAttribute("content");await init((e="/"==e.slice(-1)?e.slice(0,-1):e)+"/tinysearch_engine_bg.wasm")}var loaded=!(window.onload=function(){document.body.contains(document.goSearch)&&(document.goSearch.onsubmit=function(){return goSearchNow()})});function closeAllLists(e){for(var t=document.getElementById("suggestions");t.firstChild;)t.removeChild(t.firstChild)}function markTerm(e,t){return e.replace(new RegExp("(^|)("+t+")(|$)","ig"),"$1$2$3")}function autocomplete(e){e.addEventListener("input",function(e){var t=this.value;if(closeAllLists(),!t)return!1;for(var n=document.getElementById("suggestions"),o=search(t,99),a=0;a",r=s.querySelector("a"),c=s.querySelector("span:first-child"),i=s.querySelector("span:nth-child(2)"),r.href=u[1]+"?q="+encodeURIComponent(t),c.innerHTML=markTerm(u[0],t),i.innerHTML=markTerm(u[2],t),n.appendChild(s)}})}loaded||(lazyLoad(),loaded=!0,document.body.contains(document.goSearch)&&(document.goSearch.onsubmit=function(){return goSearchNow()}));var searchinput=document.getElementById("searchinput");function suggestionFocus(t){191===t.keyCode&&"INPUT"!==document.activeElement.tagName&&"TEXTAREA"!==document.activeElement.tagName&&(t.preventDefault(),searchinput.focus(),suggestions.classList.remove("d-none")),27===t.keyCode&&(searchinput.blur(),suggestions.classList.add("d-none"),closeAllLists());const n=suggestions.querySelectorAll("a");if(!suggestions.classList.contains("d-none")&&0!==n.length){const a=[...n];var o=a.indexOf(document.activeElement);let e=0;38===t.keyCode?(t.preventDefault(),e=0