From 557014ffa2b3b5746cfc9c2a6c9de4bad8e33e88 Mon Sep 17 00:00:00 2001 From: null Date: Thu, 21 Jan 2021 15:52:04 +0100 Subject: [PATCH] Build to /public in preparation for self-hosting --- mkdocs.yml | 1 + public/404.html | 919 ++++ public/CNAME | 1 + public/accepting-monero/overview/index.html | 995 ++++ public/assets/images/favicon.png | Bin 0 -> 1870 bytes .../assets/javascripts/bundle.83e5331e.min.js | 2 + .../javascripts/bundle.83e5331e.min.js.map | 1 + .../javascripts/lunr/min/lunr.ar.min.js | 1 + .../javascripts/lunr/min/lunr.da.min.js | 18 + .../javascripts/lunr/min/lunr.de.min.js | 18 + .../javascripts/lunr/min/lunr.du.min.js | 18 + .../javascripts/lunr/min/lunr.es.min.js | 18 + .../javascripts/lunr/min/lunr.fi.min.js | 18 + .../javascripts/lunr/min/lunr.fr.min.js | 18 + .../javascripts/lunr/min/lunr.hu.min.js | 18 + .../javascripts/lunr/min/lunr.it.min.js | 18 + .../javascripts/lunr/min/lunr.ja.min.js | 1 + .../javascripts/lunr/min/lunr.jp.min.js | 1 + .../javascripts/lunr/min/lunr.multi.min.js | 1 + .../javascripts/lunr/min/lunr.nl.min.js | 18 + .../javascripts/lunr/min/lunr.no.min.js | 18 + .../javascripts/lunr/min/lunr.pt.min.js | 18 + .../javascripts/lunr/min/lunr.ro.min.js | 18 + .../javascripts/lunr/min/lunr.ru.min.js | 18 + .../lunr/min/lunr.stemmer.support.min.js | 1 + .../javascripts/lunr/min/lunr.sv.min.js | 18 + .../javascripts/lunr/min/lunr.tr.min.js | 18 + .../javascripts/lunr/min/lunr.vi.min.js | 1 + public/assets/javascripts/lunr/tinyseg.min.js | 1 + .../assets/javascripts/vendor.93c04032.min.js | 16 + .../javascripts/vendor.93c04032.min.js.map | 1 + .../javascripts/worker/search.8c7e0a7e.min.js | 59 + .../worker/search.8c7e0a7e.min.js.map | 1 + .../assets/stylesheets/main.15aa0b43.min.css | 3 + .../stylesheets/main.15aa0b43.min.css.map | 1 + .../stylesheets/palette.75751829.min.css | 3 + .../stylesheets/palette.75751829.min.css.map | 1 + .../asymmetric/edwards25519/index.html | 1204 +++++ .../asymmetric/introduction/index.html | 1018 ++++ .../asymmetric/key-image/index.html | 1098 +++++ .../asymmetric/private-key/index.html | 1165 +++++ .../asymmetric/public-key/index.html | 1090 +++++ public/cryptography/base58/index.html | 1054 ++++ public/cryptography/introduction/index.html | 1005 ++++ public/cryptography/keccak-256/index.html | 1102 +++++ public/cryptography/prng/index.html | 1077 +++++ public/extra.css | 2 + public/images/monero-dir.png | Bin 0 -> 20052 bytes public/images/monero.svg | 1 + public/images/sheets-icon.png | Bin 0 -> 29698 bytes public/index.html | 1035 ++++ public/infrastructure/monero-pulse/index.html | 1208 +++++ public/infrastructure/networks/index.html | 1152 +++++ .../tor-onion-p2p-seed-nodes/index.html | 1188 +++++ .../download-monero-binaries/index.html | 1078 +++++ .../index.html | 1300 +++++ .../index.html | 1352 ++++++ .../interacting/monero-config-file/index.html | 1211 +++++ .../monero-wallet-cli-reference/index.html | 2147 +++++++++ .../monero-wallet-gui-reference/index.html | 1209 +++++ .../monero-wallet-rpc-reference/index.html | 4263 +++++++++++++++++ .../interacting/monerod-reference/index.html | 2309 +++++++++ public/interacting/overview/index.html | 1302 +++++ .../verify-monero-binaries/index.html | 1121 +++++ public/multisignature/index.html | 1216 +++++ public/overrides.css | 10 + public/proof-of-work/cryptonight/index.html | 1403 ++++++ .../pow-in-cryptocurrencies/index.html | 1083 +++++ public/proof-of-work/random-x/index.html | 1002 ++++ public/proof-of-work/what-is-pow/index.html | 1107 +++++ .../integrated-address/index.html | 1151 +++++ public/public-address/main-address/index.html | 936 ++++ .../standard-address/index.html | 1154 +++++ public/public-address/subaddress/index.html | 1339 ++++++ .../index.html | 936 ++++ .../open-node-tor-onion/index.html | 1486 ++++++ public/search/search_index.json | 1 + public/sitemap.xml | 139 + public/sitemap.xml.gz | Bin 0 -> 559 bytes public/technical-specs/index.html | 1366 ++++++ public/todo/bulletproofs/index.html | 961 ++++ public/todo/confidential-transactions.txt | 18 + .../todo/confidential-transactions/index.html | 954 ++++ .../monero-wallet-cli__remaining_commands.txt | 21 + public/todo/p2p/index.html | 936 ++++ public/todo/pedersen-commitment/index.html | 957 ++++ .../risks-of-using-remote-node/index.html | 977 ++++ public/todo/stealth-address/index.html | 1082 +++++ public/todo/tx/index.html | 957 ++++ 89 files changed, 55164 insertions(+) create mode 100644 public/404.html create mode 100644 public/CNAME create mode 100644 public/accepting-monero/overview/index.html create mode 100644 public/assets/images/favicon.png create mode 100644 public/assets/javascripts/bundle.83e5331e.min.js create mode 100644 public/assets/javascripts/bundle.83e5331e.min.js.map create mode 100644 public/assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 public/assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 public/assets/javascripts/lunr/tinyseg.min.js create mode 100644 public/assets/javascripts/vendor.93c04032.min.js create mode 100644 public/assets/javascripts/vendor.93c04032.min.js.map create mode 100644 public/assets/javascripts/worker/search.8c7e0a7e.min.js create mode 100644 public/assets/javascripts/worker/search.8c7e0a7e.min.js.map create mode 100644 public/assets/stylesheets/main.15aa0b43.min.css create mode 100644 public/assets/stylesheets/main.15aa0b43.min.css.map create mode 100644 public/assets/stylesheets/palette.75751829.min.css create mode 100644 public/assets/stylesheets/palette.75751829.min.css.map create mode 100644 public/cryptography/asymmetric/edwards25519/index.html create mode 100644 public/cryptography/asymmetric/introduction/index.html create mode 100644 public/cryptography/asymmetric/key-image/index.html create mode 100644 public/cryptography/asymmetric/private-key/index.html create mode 100644 public/cryptography/asymmetric/public-key/index.html create mode 100644 public/cryptography/base58/index.html create mode 100644 public/cryptography/introduction/index.html create mode 100644 public/cryptography/keccak-256/index.html create mode 100644 public/cryptography/prng/index.html create mode 100644 public/extra.css create mode 100644 public/images/monero-dir.png create mode 100644 public/images/monero.svg create mode 100644 public/images/sheets-icon.png create mode 100644 public/index.html create mode 100644 public/infrastructure/monero-pulse/index.html create mode 100644 public/infrastructure/networks/index.html create mode 100644 public/infrastructure/tor-onion-p2p-seed-nodes/index.html create mode 100644 public/interacting/download-monero-binaries/index.html create mode 100644 public/interacting/monero-blockchain-export-reference/index.html create mode 100644 public/interacting/monero-blockchain-import-reference/index.html create mode 100644 public/interacting/monero-config-file/index.html create mode 100644 public/interacting/monero-wallet-cli-reference/index.html create mode 100644 public/interacting/monero-wallet-gui-reference/index.html create mode 100644 public/interacting/monero-wallet-rpc-reference/index.html create mode 100644 public/interacting/monerod-reference/index.html create mode 100644 public/interacting/overview/index.html create mode 100644 public/interacting/verify-monero-binaries/index.html create mode 100644 public/multisignature/index.html create mode 100644 public/overrides.css create mode 100644 public/proof-of-work/cryptonight/index.html create mode 100644 public/proof-of-work/pow-in-cryptocurrencies/index.html create mode 100644 public/proof-of-work/random-x/index.html create mode 100644 public/proof-of-work/what-is-pow/index.html create mode 100644 public/public-address/integrated-address/index.html create mode 100644 public/public-address/main-address/index.html create mode 100644 public/public-address/standard-address/index.html create mode 100644 public/public-address/subaddress/index.html create mode 100644 public/r/accepting-monero-comparison-matrix/index.html create mode 100644 public/running-node/open-node-tor-onion/index.html create mode 100644 public/search/search_index.json create mode 100644 public/sitemap.xml create mode 100644 public/sitemap.xml.gz create mode 100644 public/technical-specs/index.html create mode 100644 public/todo/bulletproofs/index.html create mode 100644 public/todo/confidential-transactions.txt create mode 100644 public/todo/confidential-transactions/index.html create mode 100644 public/todo/monero-wallet-cli__remaining_commands.txt create mode 100644 public/todo/p2p/index.html create mode 100644 public/todo/pedersen-commitment/index.html create mode 100644 public/todo/risks-of-using-remote-node/index.html create mode 100644 public/todo/stealth-address/index.html create mode 100644 public/todo/tx/index.html diff --git a/mkdocs.yml b/mkdocs.yml index e6a69dd..ae2601c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,6 +3,7 @@ site_name: Monero Documentation site_description: 'Unofficial Monero Documentation' site_author: "Piotr 'Qertoip' Włodarek" site_url: 'https://monerodocs.org' +site_dir: 'public' nav: - Home: 'index.md' diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000..e8683d3 --- /dev/null +++ b/public/404.html @@ -0,0 +1,919 @@ + + + + + + + + + + + + + + + + + + + + + Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + +
+ +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+ +

404 - Not found

+ + +
+
+
+
+ + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/public/CNAME b/public/CNAME new file mode 100644 index 0000000..f75ef87 --- /dev/null +++ b/public/CNAME @@ -0,0 +1 @@ +monerodocs.org \ No newline at end of file diff --git a/public/accepting-monero/overview/index.html b/public/accepting-monero/overview/index.html new file mode 100644 index 0000000..8c5b529 --- /dev/null +++ b/public/accepting-monero/overview/index.html @@ -0,0 +1,995 @@ + + + + + + + + + + + + + + + + + + + + + + + Accepting Monero for Businesses - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + +
+ +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + +
+
+
+ + +
+
+ + + + + + + +

Accepting Monero for Businesses

+

This is for businesses that want to accept Monero in an automated way, including:

+
    +
  • merchants
  • +
  • service providers
  • +
  • exchanges
  • +
+

We prepared a comparison of available venues to accept Monero, as of 2019-01-28:

+

Accepting Monero as a Business - Comparison Matrix

+ + + + + + + + + +
+
+
+
+ + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/public/assets/images/favicon.png b/public/assets/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf13b9f9d978896599290a74f77d5dbe7d1655c GIT binary patch literal 1870 zcmV-U2eJ5xP)Gc)JR9QMau)O=X#!i9;T z37kk-upj^(fsR36MHs_+1RCI)NNu9}lD0S{B^g8PN?Ww(5|~L#Ng*g{WsqleV}|#l zz8@ri&cTzw_h33bHI+12+kK6WN$h#n5cD8OQt`5kw6p~9H3()bUQ8OS4Q4HTQ=1Ol z_JAocz`fLbT2^{`8n~UAo=#AUOf=SOq4pYkt;XbC&f#7lb$*7=$na!mWCQ`dBQsO0 zLFBSPj*N?#u5&pf2t4XjEGH|=pPQ8xh7tpx;US5Cx_Ju;!O`ya-yF`)b%TEt5>eP1ZX~}sjjA%FJF?h7cX8=b!DZl<6%Cv z*G0uvvU+vmnpLZ2paivG-(cd*y3$hCIcsZcYOGh{$&)A6*XX&kXZd3G8m)G$Zz-LV z^GF3VAW^Mdv!)4OM8EgqRiz~*Cji;uzl2uC9^=8I84vNp;ltJ|q-*uQwGp2ma6cY7 z;`%`!9UXO@fr&Ebapfs34OmS9^u6$)bJxrucutf>`dKPKT%%*d3XlFVKunp9 zasduxjrjs>f8V=D|J=XNZp;_Zy^WgQ$9WDjgY=z@stwiEBm9u5*|34&1Na8BMjjgf3+SHcr`5~>oz1Y?SW^=K z^bTyO6>Gar#P_W2gEMwq)ot3; zREHn~U&Dp0l6YT0&k-wLwYjb?5zGK`W6S2v+K>AM(95m2C20L|3m~rN8dprPr@t)5lsk9Hu*W z?pS990s;Ez=+Rj{x7p``4>+c0G5^pYnB1^!TL=(?HLHZ+HicG{~4F1d^5Awl_2!1jICM-!9eoLhbbT^;yHcefyTAaqRcY zmuctDopPT!%k+}x%lZRKnzykr2}}XfG_ne?nRQO~?%hkzo;@RN{P6o`&mMUWBYMTe z6i8ChtjX&gXl`nvrU>jah)2iNM%JdjqoaeaU%yVn!^70x-flljp6Q5tK}5}&X8&&G zX3fpb3E(!rH=zVI_9Gjl45w@{(ITqngWFe7@9{mX;tO25Z_8 zQHEpI+FkTU#4xu>RkN>b3Tnc3UpWzPXWm#o55GKF09j^Mh~)K7{QqbO_~(@CVq! zS<8954|P8mXN2MRs86xZ&Q4EfM@JB94b=(YGuk)s&^jiSF=t3*oNK3`rD{H`yQ?d; ztE=laAUoZx5?RC8*WKOj`%LXEkgDd>&^Q4M^z`%u0rg-It=hLCVsq!Z%^6eB-OvOT zFZ28TN&cRmgU}Elrnk43)!>Z1FCPL2K$7}gwzIc48NX}#!A1BpJP?#v5wkNprhV** z?Cpalt1oH&{r!o3eSKc&ap)iz2BTn_VV`4>9M^b3;(YY}4>#ML6{~(4mH+?%07*qo IM6N<$f(jP3KmY&$ literal 0 HcmV?d00001 diff --git a/public/assets/javascripts/bundle.83e5331e.min.js b/public/assets/javascripts/bundle.83e5331e.min.js new file mode 100644 index 0000000..af4ac07 --- /dev/null +++ b/public/assets/javascripts/bundle.83e5331e.min.js @@ -0,0 +1,2 @@ +!function(e,t){for(var c in t)e[c]=t[c]}(window,function(e){function t(t){for(var a,o,i=t[0],s=t[1],b=t[2],p=0,f=[];pObject(r.a)(new ResizeObserver(e=>{for(const t of e)P.next(t)}))).pipe(Object(f.a)(e=>o.a.pipe(Object(C.a)(e)).pipe(Object(z.a)(()=>e.disconnect()))),Object(p.a)({bufferSize:1,refCount:!0}));function H(e){return U.pipe(Object(d.a)(t=>t.observe(e)),Object(f.a)(t=>P.pipe(Object(m.a)(({target:t})=>t===e),Object(z.a)(()=>t.unobserve(e)),Object(g.a)(({contentRect:e})=>({width:e.width,height:e.height})))),Object(C.a)(function(e){return{width:e.offsetWidth,height:e.offsetHeight}}(e)))}var q=c(71);var I=c(58);function N(e,t=location){return e.host===t.host&&/^(?:\/[\w-]+)*(?:\/?|\.html)$/i.test(e.pathname)}function D(e,t=location){return e.pathname===t.pathname&&e.hash.length>0}function Y(){return new I.a(new URL(location.href))}function F(){return location.hash.substring(1)}function J(e){const t=A("a");t.href=e,t.addEventListener("click",e=>e.stopPropagation()),t.click()}var K=c(5);function W(e){const t=matchMedia(e);return new K.a(e=>{t.addListener(t=>e.next(t.matches))}).pipe(Object(C.a)(t.matches),Object(p.a)({bufferSize:1,refCount:!0}))}const B={drawer:S("[data-md-toggle=drawer]"),search:S("[data-md-toggle=search]")};function Q(e,t){B[e].checked!==t&&B[e].click()}function X(e){const t=B[e];return Object(b.a)(t,"change").pipe(Object(g.a)(()=>t.checked),Object(C.a)(t.checked))}function V(){return{x:Math.max(0,pageXOffset),y:Math.max(0,pageYOffset)}}function G({x:e,y:t}){window.scrollTo(e||0,t||0)}function Z(){return{width:innerWidth,height:innerHeight}}function ee(e,{header$:t,viewport$:c}){const a=c.pipe(Object($.a)("size")),n=Object(i.a)([a,t]).pipe(Object(g.a)(()=>({x:e.offsetLeft,y:e.offsetTop})));return Object(i.a)([t,c,n]).pipe(Object(g.a)(([{height:e},{offset:t,size:c},{x:a,y:n}])=>({offset:{x:t.x-a,y:t.y-n+e},size:c})))}var te=c(60),ce=c(61);var ae=c(19),ne=c(75),re=c(43);let oe;function ie(e){return oe.pipe(Object(f.a)(t=>void 0!==t[e]?Object(r.a)(t[e]):ae.a),Object(re.a)())}var se=c(39),be=c(76);function ue({document$:e,viewport$:t}){return Object(se.a)(Object(f.a)(c=>{const a=function(e,{document$:t}){return t.pipe(Object(g.a)(()=>{const t=getComputedStyle(e);return["sticky","-webkit-sticky"].includes(t.position)}),Object(re.a)(),Object(f.a)(t=>t?H(e).pipe(Object(g.a)(({height:e})=>({sticky:!0,height:e}))):Object(r.a)({sticky:!1,height:0})),Object(p.a)({bufferSize:1,refCount:!0}))}(c,{document$:e}),n=ie("main").pipe(Object(g.a)(e=>E("h1, h2, h3, h4, h5, h6",e)),Object(m.a)(e=>void 0!==e),Object(be.a)(ie("header-title")),Object(f.a)(([e,c])=>ee(e,{header$:a,viewport$:t}).pipe(Object(g.a)(({offset:{y:t}})=>t>=e.offsetHeight?"page":"site"),Object(re.a)(),function(e){return Object(se.a)(Object(h.a)(s.a),Object(d.a)(t=>{!function(e,t){e.setAttribute("data-md-state",t?"active":"")}(e,"page"===t)}),Object(z.a)(()=>{!function(e){e.removeAttribute("data-md-state")}(e)}))}(c))),Object(C.a)("site"));return Object(i.a)([a,n]).pipe(Object(g.a)(([e,t])=>Object.assign({type:t},e)))}))}var pe=c(9);function fe({header$:e,viewport$:t}){const c=new L.a;return ie("header").pipe(Object(f.a)(e=>{return c.pipe(Object($.a)("active"),(t=e,Object(se.a)(Object(h.a)(s.a),Object(d.a)(({active:e})=>{!function(e,t){e.setAttribute("data-md-state",t?"shadow":"")}(t,e)}),Object(z.a)(()=>{!function(e){e.removeAttribute("data-md-state")}(t)}))));var t})).subscribe(pe.a),Object(se.a)(Object(f.a)(c=>function(e,{header$:t,viewport$:c}){const a=t.pipe(Object(g.a)(({height:e})=>e),Object(re.a)()),n=a.pipe(Object(f.a)(()=>H(e).pipe(Object(g.a)(({height:t})=>({top:e.offsetTop,bottom:e.offsetTop+t})),Object($.a)("bottom"))));return Object(i.a)([a,n,c]).pipe(Object(g.a)(([e,{top:t,bottom:c},{offset:{y:a},size:{height:n}}])=>({offset:t-e,height:n=Math.max(0,n-Math.max(0,t-a,e)-Math.max(0,n+a-c)),active:t-e<=a})),Object(re.a)((e,t)=>e.offset===t.offset&&e.height===t.height&&e.active===t.active))}(c,{header$:e,viewport$:t})),Object(d.a)(e=>c.next(e)),Object(z.a)(()=>c.complete()))}function le(e){e.style.top=""}function de(e,{main$:t,viewport$:c}){const a=e.parentElement.offsetTop-e.parentElement.parentElement.offsetTop;return Object(i.a)([t,c]).pipe(Object(g.a)(([{offset:e,height:t},{offset:{y:c}}])=>({height:t=t+Math.min(a,Math.max(0,c-e))-a,lock:c>=e+a})),Object(re.a)((e,t)=>e.height===t.height&&e.lock===t.lock))}function Oe(e,{header$:t}){return Object(se.a)(Object(h.a)(s.a),Object(j.a)(t),Object(d.a)(([{height:t,lock:c},{height:a}])=>{!function(e,t){const c=e.firstElementChild;c.style.height=t-2*c.offsetTop+"px"}(e,t),c?function(e,t){e.style.top=t+"px"}(e,a):le(e)}),Object(g.a)(([e])=>e),Object(z.a)(()=>{le(e),function(e){e.firstElementChild.style.height=""}(e)}))}var je=c(64);c(44);function he(e){return e.split(/"([^"]+)"/g).map((e,t)=>1&t?e.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):e).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").trim()}var me=c(20);function ge(e,t){if("string"==typeof t||"number"==typeof t)e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(const c of t)ge(e,c)}function ve(e,t,...c){const a=document.createElement(e);if(t)for(const e of Object.keys(t))"boolean"!=typeof t[e]?a.setAttribute(e,t[e]):t[e]&&a.setAttribute(e,"");for(const e of c)ge(a,e);return a}let $e;function ye(e,t){if(void 0===$e){const e=S("#__lang");$e=JSON.parse(e.textContent)}if(void 0===$e[e])throw new ReferenceError("Invalid translation: "+e);return void 0!==t?$e[e].replace("#",t.toString()):$e[e]}function we(e){if(e>999){return((e+1e-6)/1e3).toFixed(+((e-950)%1e3>99))+"k"}return e.toString()}var xe;function Ee(e){return e.type===xe.READY}function Se(e){return e.type===xe.QUERY}function ke(e){return e.type===xe.RESULT}function _e({config:e,docs:t,index:c}){1===e.lang.length&&"en"===e.lang[0]&&(e.lang=[ye("search.config.lang")]),"[\\s\\-]+"===e.separator&&(e.separator=ye("search.config.separator"));return{config:e,docs:t,index:c,pipeline:ye("search.config.pipeline").split(/\s*,\s*/).filter(Boolean)}}function Ae(e,{index$:t,base$:c}){const a=new Worker(e),n=new L.a,r=function(e,{tx$:t}){const c=Object(b.a)(e,"message").pipe(Object(g.a)(({data:e})=>e));return t.pipe(Object(te.a)(()=>c,{leading:!0,trailing:!0}),Object(d.a)(t=>e.postMessage(t)),Object(ce.a)(c),Object(q.a)())}(a,{tx$:n}).pipe(Object(j.a)(c),Object(g.a)(([e,t])=>{if(ke(e))for(const c of e.data)for(const e of c)e.location=`${t}/${e.location}`;return e}),Object(q.a)());return t.pipe(Object(g.a)(e=>({type:xe.SETUP,data:_e(e)})),Object(h.a)(me.b)).subscribe(n.next.bind(n)),{tx$:n,rx$:r}}!function(e){e[e.SETUP=0]="SETUP",e[e.READY=1]="READY",e[e.QUERY=2]="QUERY",e[e.RESULT=3]="RESULT"}(xe||(xe={}));var Te,Ce=c(37);function Re(e,t){const c=t&Te.PARENT,a=t&Te.TEASER,n=Object.keys(e.terms).filter(t=>!e.terms[t]).map(e=>[ve("del",null,e)," "]).flat().slice(0,-1);return ve("a",{href:e.location,class:"md-search-result__link",tabIndex:-1},ve("article",{class:["md-search-result__article",...c?["md-search-result__article--document"]:[]].join(" "),"data-md-score":e.score.toFixed(2)},c>0&&ve("div",{class:"md-search-result__icon md-icon"}),ve("h1",{class:"md-search-result__title"},e.title),a>0&&e.text.length>0&&ve("p",{class:"md-search-result__teaser"},function(e,t){let c=t;if(e.length>c){for(;" "!==e[c]&&--c>0;);return e.substring(0,c)+"..."}return e}(e.text,320)),a>0&&n.length>0&&ve("p",{class:"md-search-result__terms"},ye("search.result.term.missing"),": ",n)))}function Me(e,t=1/0){const c=[...e],a=c.findIndex(e=>!e.location.includes("#")),[n]=c.splice(a,1);let r=c.findIndex(e=>e.scoreRe(e,Te.TEASER)),...i.length?[ve("details",{class:"md-search-result__more"},ve("summary",{tabIndex:-1},i.length>0&&1===i.length?ye("search.result.more.one"):ye("search.result.more.other",i.length)),i.map(e=>Re(e,Te.TEASER)))]:[]];return ve("li",{class:"md-search-result__item"},s)}function Le(e){return ve("ul",{class:"md-source__facts"},e.map(e=>ve("li",{class:"md-source__fact"},e)))}function ze({document$:e,dialog$:t}){if(!Ce.isSupported())return o.a;e.subscribe(()=>{_("pre > code").forEach((e,t)=>{const c=e.parentElement;var a;c.id="__code_"+t,c.insertBefore((a=c.id,ve("button",{class:"md-clipboard md-icon",title:ye("clipboard.copy"),"data-clipboard-target":`#${a} > code`})),e)})});const c=new K.a(e=>{new Ce(".md-clipboard").on("success",t=>e.next(t))}).pipe(Object(q.a)());return c.pipe(Object(d.a)(e=>e.clearSelection()),Object(x.a)(ye("clipboard.copied"))).subscribe(t),c}!function(e){e[e.TEASER=1]="TEASER",e[e.PARENT=2]="PARENT"}(Te||(Te={}));var Pe=c(65),Ue=c(77);function He(e,{document$:t,viewport$:c,location$:a}){"scrollRestoration"in history&&(history.scrollRestoration="manual"),Object(b.a)(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"});const i=E('link[rel="shortcut icon"]');void 0!==i&&(i.href=i.href);const s=Object(b.a)(document.body,"click").pipe(Object(m.a)(e=>!(e.metaKey||e.ctrlKey)),Object(f.a)(t=>{if(t.target instanceof HTMLElement){const c=t.target.closest("a");if(c&&!c.target&&N(c)&&e.includes(c.href))return D(c)||t.preventDefault(),Object(r.a)(c)}return o.a}),Object(g.a)(e=>({url:new URL(e.href)})),Object(q.a)());s.subscribe(()=>{Q("search",!1)});const p=s.pipe(Object(m.a)(({url:e})=>!D(e)),Object(q.a)()),d=Object(b.a)(window,"popstate").pipe(Object(m.a)(e=>null!==e.state),Object(g.a)(e=>({url:new URL(location.href),offset:e.state})),Object(q.a)());Object(u.a)(p,d).pipe(Object(re.a)((e,t)=>e.url.href===t.url.href),Object(g.a)(({url:e})=>e)).subscribe(a);const O=a.pipe(Object($.a)("pathname"),Object(Pe.a)(1),Object(f.a)(e=>Object(n.a)(fetch(e.href,{credentials:"same-origin"}).then(e=>e.text())).pipe(Object(l.a)(()=>(function(e){location.href=e.href}(e),o.a)))),Object(q.a)());p.pipe(Object(je.a)(O)).subscribe(({url:e})=>{history.pushState({},"",e.toString())});const j=new DOMParser;O.pipe(Object(g.a)(e=>j.parseFromString(e,"text/html"))).subscribe(t);Object(u.a)(p,d).pipe(Object(je.a)(t)).subscribe(({url:e,offset:t})=>{e.hash&&!t?J(e.hash):G(t||{y:0})}),t.pipe(Object(Pe.a)(1)).subscribe(({title:e,head:t})=>{document.title=e;for(const e of['link[rel="canonical"]','meta[name="author"]','meta[name="description"]']){const c=E(e,t),a=E(e,document.head);void 0!==c&&void 0!==a&&T(a,c)}document.dispatchEvent(new CustomEvent("DOMContentSwitch"))}),c.pipe(Object(Ue.a)(250),Object($.a)("offset")).subscribe(({offset:e})=>{history.replaceState(e,"")}),Object(u.a)(s,d).pipe(Object(v.a)(2,1),Object(m.a)(([e,t])=>e.url.pathname===t.url.pathname&&!D(t.url)),Object(g.a)(([,e])=>e)).subscribe(({offset:e})=>{G(e||{y:0})})}function qe(){const e=Object(b.a)(window,"keydown").pipe(Object(m.a)(e=>!(e.metaKey||e.ctrlKey)),Object(g.a)(e=>({type:e.key,claim(){e.preventDefault(),e.stopPropagation()}})),Object(q.a)()).pipe(Object(g.a)(e=>{return Object.assign({mode:(t="search",B[t].checked?"search":"global")},e);var t}),Object(m.a)(({mode:e})=>{if("global"===e){const e=k();if(void 0!==e)return!function(e){switch(e.tagName){case"INPUT":case"SELECT":case"TEXTAREA":return!0;default:return e.isContentEditable}}(e)}return!0}),Object(q.a)());return e.pipe(Object(m.a)(({mode:e})=>"search"===e),Object(j.a)(ie("search-query"),ie("search-result"))).subscribe(([e,t,c])=>{const a=k();switch(e.type){case"Enter":a===t&&e.claim();break;case"Escape":case"Tab":Q("search",!1),R(t,!1);break;case"ArrowUp":case"ArrowDown":if(void 0===a)R(t);else{const n=[t,..._(":not(details) > [href], summary, details[open] [href]",c)],r=Math.max(0,(Math.max(0,n.indexOf(a))+n.length+("ArrowUp"===e.type?-1:1))%n.length);R(n[r])}e.claim();break;default:t!==k()&&R(t)}}),e.pipe(Object(m.a)(({mode:e})=>"global"===e),Object(j.a)(ie("search-query"))).subscribe(([e,t])=>{switch(e.type){case"f":case"s":case"/":R(t),function(e){if(!(e instanceof HTMLInputElement))throw new Error("Not implemented");e.select()}(t),e.claim();break;case"p":case",":const c=E("[href][rel=prev]");void 0!==c&&c.click();break;case"n":case".":const a=E("[href][rel=next]");void 0!==a&&a.click()}}),e}function Ie(e){e.placeholder=ye("search.placeholder")}function Ne(e,{transform:t}={}){const c=t||he,a=Object(u.a)(Object(b.a)(e,"keyup"),Object(b.a)(e,"focus").pipe(Object(O.a)(1))).pipe(Object(g.a)(()=>c(e.value)),Object(C.a)(c(e.value)),Object(re.a)()),n=function(e){return Object(u.a)(Object(b.a)(e,"focus"),Object(b.a)(e,"blur")).pipe(Object(g.a)(({type:e})=>"focus"===e),Object(C.a)(e===k()))}(e);return Object(i.a)([a,n]).pipe(Object(g.a)(([e,t])=>({value:e,focus:t})))}function De({tx$:e},t={}){return Object(se.a)(Object(f.a)(c=>{const a=Ne(c,t);return a.pipe(Object($.a)("value"),Object(g.a)(({value:e})=>({type:xe.QUERY,data:e}))).subscribe(e.next.bind(e)),a.pipe(Object($.a)("focus")).subscribe(({focus:e})=>{e&&Q("search",e)}),a.pipe(function(e){return Object(se.a)(Object(d.a)(({focus:t})=>{t?function(e,t){e.placeholder=t}(e,""):Ie(e)}),Object(z.a)(()=>{Ie(e)}))}(c))}))}function Ye(){return Object(se.a)(Object(f.a)(e=>function(e){return Object(b.a)(e,"click").pipe(Object(x.a)(void 0))}(e).pipe(Object(ce.a)(ie("search-query")),Object(d.a)(R),Object(x.a)(void 0))),Object(C.a)(void 0))}function Fe(e,t){e.appendChild(t)}function Je(e,{query$:t,ready$:c,fetch$:a}){const n=S(".md-search-result__list",e),r=S(".md-search-result__meta",e);return Object(se.a)(Object(j.a)(t,c),Object(g.a)(([e,t])=>(t.value?function(e,t){switch(t){case 0:e.textContent=ye("search.result.none");break;case 1:e.textContent=ye("search.result.one");break;default:e.textContent=ye("search.result.other",t)}}(r,e.length):function(e){e.textContent=ye("search.result.placeholder")}(r),e)),Object(f.a)(t=>{const c=[...t.map(([e])=>e.score),0];return a.pipe(Object(h.a)(s.a),Object(ne.a)(a=>{const r=e.parentElement;for(;a16)););return a},0),Object(x.a)(t),Object(z.a)(()=>{!function(e){e.innerHTML=""}(n)}))}))}function Ke({rx$:e},{query$:t}){return Object(se.a)(Object(f.a)(c=>{const a=c.parentElement,n=e.pipe(Object(m.a)(Ee),Object(x.a)(!0)),r=function(e){return Object(u.a)(Object(b.a)(e,"scroll"),Object(b.a)(window,"resize")).pipe(Object(g.a)(()=>M(e)),Object(C.a)(M(e)))}(a).pipe(Object(g.a)(({y:e})=>e>=a.scrollHeight-a.offsetHeight-16),Object(re.a)(),Object(m.a)(Boolean));return e.pipe(Object(m.a)(ke),Object(g.a)(({data:e})=>e),Je(c,{query$:t,ready$:n,fetch$:r}),Object(C.a)([]))}))}function We({header$:e,viewport$:t,screen$:c}){return Object(se.a)(Object(f.a)(a=>c.pipe(Object(f.a)(c=>c?ee(a,{header$:e,viewport$:t}).pipe(Object(g.a)(({offset:{y:e}})=>({hidden:e>=10})),Object($.a)("hidden"),function(e){return Object(se.a)(Object(h.a)(s.a),Object(d.a)(({hidden:t})=>{!function(e,t){e.setAttribute("data-md-state",t?"hidden":"")}(e,t)}),Object(z.a)(()=>{!function(e){e.removeAttribute("data-md-state")}(e)}))}(a)):Object(r.a)({hidden:!0})))))}function Be(e){e.removeAttribute("data-md-state")}function Qe(e){e.classList.remove("md-nav__link--active")}function Xe({header$:e,main$:t,viewport$:c,tablet$:a}){return Object(se.a)(Object(f.a)(n=>a.pipe(Object(f.a)(a=>{if(a){const a=_(".md-nav__link",n),r=de(n,{main$:t,viewport$:c}).pipe(Oe(n,{header$:e})),o=function(e,{header$:t,viewport$:c}){const a=new Map;for(const t of e){const e=E(`[id="${decodeURIComponent(t.hash.substring(1))}"]`);void 0!==e&&a.set(t,e)}const n=t.pipe(Object(g.a)(e=>24+e.height));return H(document.body).pipe(Object($.a)("height"),Object(g.a)(()=>{let e=[];return[...a].reduce((t,[c,n])=>{for(;e.length;){if(!(a.get(e[e.length-1]).tagName>=n.tagName))break;e.pop()}let r=n.offsetTop;for(;!r&&n.parentElement;)r=(n=n.parentElement).offsetTop;return t.set([...e=[...e,c]].reverse(),r)},new Map)}),Object(f.a)(e=>Object(i.a)([n,c]).pipe(Object(ne.a)(([e,t],[c,{offset:{y:a}}])=>{for(;t.length;){const[,n]=t[0];if(!(n-c=a))break;t=[e.pop(),...t]}return[e,t]},[[],[...e]]),Object(re.a)((e,t)=>e[0]===t[0]&&e[1]===t[1])))).pipe(Object(g.a)(([e,t])=>({prev:e.map(([e])=>e),next:t.map(([e])=>e)})),Object(C.a)({prev:[],next:[]}),Object(v.a)(2,1),Object(g.a)(([e,t])=>e.prev.length{for(const[e]of t)Qe(e),Be(e);e.forEach(([t],c)=>{!function(e,t){e.classList.toggle("md-nav__link--active",t)}(t,c===e.length-1),function(e,t){e.setAttribute("data-md-state",t?"blur":"")}(t,!0)})}),Object(z.a)(()=>{for(const t of e)Qe(t),Be(t)}))}(a));return Object(i.a)([r,o]).pipe(Object(g.a)(([e,t])=>({sidebar:e,anchors:t})))}return Object(r.a)({})}))))}var Ve=c(68);var Ge=c(69);function Ze(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}var et=c(70);function tt(e){const[t]=e.match(/(git(?:hub|lab))/i)||[];switch(t.toLowerCase()){case"github":const[,t,c]=e.match(/^.+github\.com\/([^\/]+)\/?([^\/]+)?/i);return function(e,t){const c=void 0!==t?`https://api.github.com/repos/${e}/${t}`:"https://api.github.com/users/"+e;return Object(n.a)(fetch(c)).pipe(Object(m.a)(e=>200===e.status),Object(f.a)(e=>e.json()),Object(g.a)(e=>{if(void 0!==t){const{stargazers_count:t,forks_count:c}=e;return[we(t)+" Stars",we(c)+" Forks"]}{const{public_repos:t}=e;return[we(t)+" Repositories"]}}),Object(et.a)([]),Object(q.a)())}(t,c);case"gitlab":const[,a,r]=e.match(/^.+?([^\/]*gitlab[^\/]+)\/(.+?)\/?$/i);return function(e,t){const c=`https://${e}/api/v4/projects/${encodeURIComponent(t)}`;return Object(n.a)(fetch(c)).pipe(Object(m.a)(e=>200===e.status),Object(f.a)(e=>e.json()),Object(g.a)(({star_count:e,forks_count:t})=>[we(e)+" Stars",we(t)+" Forks"]),Object(et.a)([]),Object(q.a)())}(a,r);default:return o.a}}function ct({document$:e}){e.pipe(Object(g.a)(()=>S(".md-source[href]")),Object(f.a)(({href:e})=>{return t=""+function(e){let t=0;for(let c=0,a=e.length;ctt(e),Object(a.a)(()=>{const e=sessionStorage.getItem(t);if(e)return Object(r.a)(JSON.parse(e));{const e=c();return e.subscribe(e=>{try{sessionStorage.setItem(t,JSON.stringify(e))}catch(e){}}),e}});var t,c}),Object(m.a)(e=>e.length>0),Object(l.a)(()=>o.a)).subscribe(e=>{for(const t of _(".md-source__repository"))t.hasAttribute("data-md-state")||(t.setAttribute("data-md-state","done"),t.appendChild(Le(e)))})}function at(e,t){e.setAttribute("data-md-state","lock"),e.style.top=`-${t}px`}function nt(e){const t=-1*parseInt(e.style.top,10);e.removeAttribute("data-md-state"),e.style.top="",t&&window.scrollTo(0,t)}function rt(e){if(!function(e){return"object"==typeof e&&"string"==typeof e.base&&"object"==typeof e.features&&"object"==typeof e.search}(e))throw new SyntaxError("Invalid configuration: "+JSON.stringify(e));const t=function(){const e=new w.a;return Object(b.a)(document,"DOMContentLoaded").pipe(Object(x.a)(document)).subscribe(e),e}(),c=Y(),S=function(e,{location$:t}){return t.pipe(Object(y.a)(1),Object(g.a)(({href:t})=>new URL(e,t).toString().replace(/\/$/,"")),Object(p.a)({bufferSize:1,refCount:!0}))}(e.base,{location$:c}),k=Object(b.a)(window,"hashchange").pipe(Object(g.a)(F),Object(C.a)(F()),Object(m.a)(e=>e.length>0),Object(q.a)()),R=Object(i.a)([Object(u.a)(Object(b.a)(window,"scroll",{passive:!0}),Object(b.a)(window,"resize",{passive:!0})).pipe(Object(g.a)(V),Object(C.a)(V())),Object(b.a)(window,"resize",{passive:!0}).pipe(Object(g.a)(Z),Object(C.a)(Z()))]).pipe(Object(g.a)(([e,t])=>({offset:e,size:t})),Object(p.a)({bufferSize:1,refCount:!0})),M=W("(min-width: 960px)"),z=W("(min-width: 1220px)");!function(e,{document$:t}){oe=t.pipe(Object(g.a)(t=>e.reduce((e,c)=>{const a=E(`[data-md-component=${c}]`,t);return Object.assign(Object.assign({},e),void 0!==a?{[c]:a}:{})},{})),Object(ne.a)((t,c)=>{for(const a of e)switch(a){case"announce":case"header-title":case"container":case"skip":a in t&&void 0!==t[a]&&(T(t[a],c[a]),t[a]=c[a]);break;default:void 0!==c[a]?t[a]=E(`[data-md-component=${a}]`):delete t[a]}return t}),Object(p.a)({bufferSize:1,refCount:!0}))}(["announce","container","header","header-title","main","navigation","search","search-query","search-reset","search-result","skip","tabs","toc"],{document$:t});const P=qe();matchMedia("(hover)").matches&&function({document$:e,viewport$:t}){const c=e.pipe(Object(g.a)(()=>_("pre > code"))),a=t.pipe(Object($.a)("size"));Object(i.a)([c,a]).subscribe(([e])=>{for(const t of e)t.scrollWidth>t.clientWidth?t.setAttribute("tabindex","0"):t.removeAttribute("tabindex")})}({document$:t,viewport$:R}),function({document$:e,hash$:t}){const c=e.pipe(Object(g.a)(()=>_("details")));Object(u.a)(W("print").pipe(Object(m.a)(Boolean)),Object(b.a)(window,"beforeprint")).pipe(Object(ce.a)(c)).subscribe(e=>{for(const t of e)t.setAttribute("open","")}),t.pipe(Object(g.a)(e=>E(`[id="${e}"]`)),Object(m.a)(e=>void 0!==e),Object(d.a)(e=>{const t=e.closest("details");t&&!t.open&&t.setAttribute("open","")})).subscribe(e=>e.scrollIntoView())}({document$:t,hash$:k}),function({document$:e}){e.pipe(Object(Pe.a)(1),Object(j.a)(ie("container")),Object(g.a)(([,e])=>_("script",e))).pipe(Object(f.a)(e=>Object(r.a)(...e)),Object(Ve.a)(e=>{const t=A("script");return e.src?(t.src=e.src,T(e,t),new K.a(e=>{t.onload=()=>e.complete()})):(t.textContent=e.textContent,T(e,t),ae.a)})).subscribe(pe.a)}({document$:t}),ct({document$:t}),function({document$:e}){const t=A("table");e.pipe(Object(g.a)(()=>_("table:not([class])"))).subscribe(e=>{for(const c of e)T(c,t),T(t,ve("div",{class:"md-typeset__scrollwrap"},ve("div",{class:"md-typeset__table"},c)))})}({document$:t}),function({document$:e}){const t=e.pipe(Object(g.a)(()=>_("[data-md-scrollfix]")),Object(p.a)({bufferSize:1,refCount:!0}));t.subscribe(e=>{for(const t of e)t.removeAttribute("data-md-scrollfix")}),Object(Ge.a)(Ze,t,o.a).pipe(Object(f.a)(e=>Object(u.a)(...e.map(e=>Object(b.a)(e,"touchstart").pipe(Object(x.a)(e)))))).subscribe(e=>{const t=e.scrollTop;0===t?e.scrollTop=1:t+e.offsetHeight===e.scrollHeight&&(e.scrollTop=t-1)})}({document$:t});const U=function({duration:e}={}){const t=new L.a,c=A("div");return c.classList.add("md-dialog","md-typeset"),t.pipe(Object(f.a)(t=>Object(r.a)(document.body).pipe(Object(g.a)(e=>e.appendChild(c)),Object(h.a)(s.a),Object(O.a)(1),Object(d.a)(e=>{e.innerHTML=t,e.setAttribute("data-md-state","open")}),Object(O.a)(e||2e3),Object(d.a)(e=>e.removeAttribute("data-md-state")),Object(O.a)(400),Object(d.a)(e=>{e.innerHTML="",e.remove()})))).subscribe(pe.a),t}(),H=ze({document$:t,dialog$:U}),I=ie("header").pipe(ue({document$:t,viewport$:R}),Object(p.a)({bufferSize:1,refCount:!0})),D=ie("main").pipe(fe({header$:I,viewport$:R}),Object(p.a)({bufferSize:1,refCount:!0})),B=ie("navigation").pipe(function({header$:e,main$:t,viewport$:c,screen$:a}){return Object(se.a)(Object(f.a)(n=>a.pipe(Object(f.a)(a=>a?de(n,{main$:t,viewport$:c}).pipe(Oe(n,{header$:e}),Object(g.a)(e=>({sidebar:e}))):Object(r.a)({})))))}({header$:I,main$:D,viewport$:R,screen$:z}),Object(p.a)({bufferSize:1,refCount:!0})),G=ie("toc").pipe(Xe({header$:I,main$:D,viewport$:R,tablet$:M}),Object(p.a)({bufferSize:1,refCount:!0})),ee=ie("tabs").pipe(We({header$:I,viewport$:R,screen$:z}),Object(p.a)({bufferSize:1,refCount:!0})),te=ie("search").pipe(Object(f.a)(()=>Object(a.a)(()=>{const t=e.search&&e.search.index?e.search.index:void 0,c=void 0!==t?Object(n.a)(t):S.pipe(Object(f.a)(e=>fetch(e+"/search/search_index.json",{credentials:"same-origin"}).then(e=>e.json())));return Object(r.a)(Ae(e.search.worker,{base$:S,index$:c}))}))).pipe(Object(f.a)(t=>{const c=ie("search-query").pipe(De(t,{transform:e.search.transform}),Object(p.a)({bufferSize:1,refCount:!0})),a=ie("search-reset").pipe(Ye(),Object(p.a)({bufferSize:1,refCount:!0})),n=ie("search-result").pipe(Ke(t,{query$:c}),Object(p.a)({bufferSize:1,refCount:!0}));return ie("search").pipe(function({rx$:e,tx$:t},{query$:c,reset$:a,result$:n}){return Object(se.a)(Object(f.a)(()=>{const r=e.pipe(Object(m.a)(Ee),Object(x.a)("ready"),Object(C.a)("waiting"));return t.pipe(Object(m.a)(Se),Object(je.a)(r),Object(y.a)(1)).subscribe(t.next.bind(t)),Object(i.a)([r,c,n,a]).pipe(Object(g.a)(([e,t,c])=>({status:e,query:t,result:c})))}))}(t,{query$:c,reset$:a,result$:n}))}),Object(l.a)(()=>(ie("search").subscribe(e=>e.hidden=!0),o.a)),Object(p.a)({bufferSize:1,refCount:!0}));if(k.pipe(Object(d.a)(()=>Q("search",!1)),Object(O.a)(125)).subscribe(e=>J("#"+e)),Object(i.a)([X("search"),M]).pipe(Object(j.a)(R),Object(f.a)(([[e,c],{offset:{y:a}}])=>{const n=e&&!c;return t.pipe(Object(O.a)(n?400:100),Object(h.a)(s.a),Object(d.a)(({body:e})=>n?at(e,a):nt(e)))})).subscribe(),Object(b.a)(document.body,"click").pipe(Object(m.a)(e=>!(e.metaKey||e.ctrlKey)),Object(m.a)(e=>{if(e.target instanceof HTMLElement){const t=e.target.closest("a");if(t&&N(t))return!0}return!1})).subscribe(()=>{Q("drawer",!1)}),e.features.includes("navigation.instant")&&"file:"!==location.protocol){const e=new DOMParser;S.pipe(Object(f.a)(t=>Object(n.a)(fetch(t+"/sitemap.xml").then(e=>e.text()).then(t=>e.parseFromString(t,"text/xml")))),Object(j.a)(S),Object(g.a)(([e,t])=>{const c=_("loc",e).map(e=>e.textContent);if(c.length>1){const[e,a]=c.sort((e,t)=>e.length-t.length);let n=0;if(e===a)n=e.length;else for(;e.charAt(n)===a.charAt(n);)n++;for(let a=0;a{He(e,{document$:t,location$:c,viewport$:R})})}t.subscribe(()=>{const e=_("[data-md-state=indeterminate]");for(const t of e)t.dataset.mdState="",t.indeterminate=!0,t.checked=!1}),e.features.includes("header.autohide")&&R.pipe(Object(g.a)(({offset:e})=>e.y),Object(v.a)(2,1),Object(g.a)(([e,t])=>[eR.pipe(Object(g.a)(({offset:e})=>e.y),Object(m.a)(e=>e>400),Object(g.a)(e=>Math.abs(t-e)),Object(m.a)(e=>e>100),Object(g.a)(()=>e),Object(y.a)(1)))).subscribe(e=>{const t=E("[data-md-component=header]");null==t||t.setAttribute("data-md-state",e?"hidden":"shadow")});const re={document$:t,location$:c,viewport$:R,header$:I,main$:D,navigation$:B,search$:te,tabs$:ee,toc$:G,clipboard$:H,keyboard$:P,dialog$:U};return Object(u.a)(...Object.values(re)).subscribe(),re}document.documentElement.classList.remove("no-js"),document.documentElement.classList.add("js"),navigator.userAgent.match(/(iPad|iPhone|iPod)/g)&&document.documentElement.classList.add("ios")}})); +//# sourceMappingURL=bundle.83e5331e.min.js.map \ No newline at end of file diff --git a/public/assets/javascripts/bundle.83e5331e.min.js.map b/public/assets/javascripts/bundle.83e5331e.min.js.map new file mode 100644 index 0000000..ee9abce --- /dev/null +++ b/public/assets/javascripts/bundle.83e5331e.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/assets/javascripts/browser/element/_/index.ts","webpack:///./src/assets/javascripts/browser/element/focus/index.ts","webpack:///./src/assets/javascripts/browser/element/offset/index.ts","webpack:///./src/assets/javascripts/browser/element/size/index.ts","webpack:///./src/assets/javascripts/browser/location/_/index.ts","webpack:///./src/assets/javascripts/browser/location/hash/index.ts","webpack:///./src/assets/javascripts/browser/media/index.ts","webpack:///./src/assets/javascripts/browser/toggle/index.ts","webpack:///./src/assets/javascripts/browser/viewport/offset/index.ts","webpack:///./src/assets/javascripts/browser/viewport/size/index.ts","webpack:///./src/assets/javascripts/browser/viewport/_/index.ts","webpack:///./src/assets/javascripts/components/_/index.ts","webpack:///./src/assets/javascripts/components/header/_/index.ts","webpack:///./src/assets/javascripts/components/header/react/index.ts","webpack:///./src/assets/javascripts/components/header/set/index.ts","webpack:///./src/assets/javascripts/components/main/_/index.ts","webpack:///./src/assets/javascripts/components/main/react/index.ts","webpack:///./src/assets/javascripts/components/main/set/index.ts","webpack:///./src/assets/javascripts/components/shared/sidebar/set/index.ts","webpack:///./src/assets/javascripts/components/shared/sidebar/react/index.ts","webpack:///./src/assets/javascripts/integrations/search/query/transform/index.ts","webpack:///./src/assets/javascripts/utilities/jsx/index.ts","webpack:///./src/assets/javascripts/utilities/string/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/message/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/_/index.ts","webpack:///./src/assets/javascripts/browser/worker/index.ts","webpack:///./src/assets/javascripts/templates/search/index.tsx","webpack:///./src/assets/javascripts/templates/source/index.tsx","webpack:///./src/assets/javascripts/integrations/clipboard/index.ts","webpack:///./src/assets/javascripts/templates/clipboard/index.tsx","webpack:///./src/assets/javascripts/integrations/instant/index.ts","webpack:///./src/assets/javascripts/integrations/keyboard/index.ts","webpack:///./src/assets/javascripts/browser/keyboard/index.ts","webpack:///./src/assets/javascripts/browser/element/select/index.ts","webpack:///./src/assets/javascripts/components/search/query/set/index.ts","webpack:///./src/assets/javascripts/components/search/query/react/index.ts","webpack:///./src/assets/javascripts/components/search/query/_/index.ts","webpack:///./src/assets/javascripts/components/search/reset/_/index.ts","webpack:///./src/assets/javascripts/components/search/reset/react/index.ts","webpack:///./src/assets/javascripts/components/search/result/set/index.ts","webpack:///./src/assets/javascripts/components/search/result/react/index.ts","webpack:///./src/assets/javascripts/components/search/result/_/index.ts","webpack:///./src/assets/javascripts/components/tabs/_/index.ts","webpack:///./src/assets/javascripts/components/tabs/react/index.ts","webpack:///./src/assets/javascripts/components/tabs/set/index.ts","webpack:///./src/assets/javascripts/components/toc/anchor/set/index.ts","webpack:///./src/assets/javascripts/components/toc/_/index.ts","webpack:///./src/assets/javascripts/components/toc/anchor/react/index.ts","webpack:///./src/assets/javascripts/patches/scrollfix/index.ts","webpack:///./src/assets/javascripts/patches/source/index.ts","webpack:///./src/assets/javascripts/patches/source/github/index.ts","webpack:///./src/assets/javascripts/patches/source/gitlab/index.ts","webpack:///./src/assets/javascripts/utilities/rxjs/index.ts","webpack:///./src/assets/javascripts/index.ts","webpack:///./src/assets/javascripts/utilities/config/index.ts","webpack:///./src/assets/javascripts/browser/document/index.ts","webpack:///./src/assets/javascripts/browser/location/base/index.ts","webpack:///./src/assets/javascripts/patches/code/index.ts","webpack:///./src/assets/javascripts/patches/details/index.ts","webpack:///./src/assets/javascripts/patches/script/index.ts","webpack:///./src/assets/javascripts/patches/table/index.ts","webpack:///./src/assets/javascripts/templates/table/index.tsx","webpack:///./src/assets/javascripts/integrations/dialog/index.ts","webpack:///./src/assets/javascripts/components/navigation/index.ts","webpack:///./src/assets/javascripts/components/search/_/index.ts"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","0","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","window","oldJsonpFunction","slice","getElement","selector","node","document","querySelector","undefined","getElementOrThrow","el","ReferenceError","getActiveElement","activeElement","HTMLElement","getElements","Array","from","querySelectorAll","createElement","tagName","replaceElement","source","target","replaceWith","setElementFocus","focus","blur","getElementOffset","x","scrollLeft","y","scrollTop","entry$","Subject","observer$","defer","of","ResizeObserver","entries","entry","next","pipe","switchMap","resize","startWith","finalize","disconnect","shareReplay","bufferSize","refCount","watchElementSize","tap","observer","observe","filter","unobserve","map","contentRect","width","height","offsetWidth","offsetHeight","getElementSize","isLocalLocation","url","ref","location","host","test","pathname","isAnchorLocation","hash","watchLocation","BehaviorSubject","URL","href","getLocationHash","substring","setLocationHash","addEventListener","ev","stopPropagation","click","watchMedia","query","media","matchMedia","Observable","subscriber","addListener","matches","drawer","search","setToggle","checked","watchToggle","fromEvent","getViewportOffset","Math","max","pageXOffset","pageYOffset","setViewportOffset","scrollTo","getViewportSize","innerWidth","innerHeight","watchViewportAt","header$","viewport$","size$","distinctUntilKeyChanged","offset$","combineLatest","offsetLeft","offsetTop","offset","size","components$","useComponent","components","distinctUntilChanged","mountHeader","document$","styles","getComputedStyle","includes","position","sticky","watchHeader","type$","main","hx","zipWith","title","observeOn","animationFrame","type","setAttribute","setHeaderTitleActive","removeAttribute","resetHeaderTitleActive","applyHeaderType","header","mountMain","main$","active","setHeaderShadow","resetHeaderShadow","subscribe","noop","adjust$","border$","top","bottom","a","b","watchMain","complete","resetSidebarOffset","style","watchSidebar","adjust","parentElement","min","lock","applySidebar","withLatestFrom","scrollwrap","firstElementChild","setSidebarHeight","setSidebarOffset","sidebar","resetSidebarHeight","defaultTransform","split","terms","index","replace","join","trim","appendChild","child","innerHTML","toString","Node","isArray","h","tag","attributes","children","attr","keys","lang","translate","JSON","parse","textContent","round","toFixed","SearchMessageType","isSearchReadyMessage","message","READY","isSearchQueryMessage","QUERY","isSearchResultMessage","RESULT","setupSearchIndex","config","docs","separator","pipeline","Boolean","setupSearchWorker","index$","base$","worker","Worker","tx$","rx$","throttle","leading","trailing","postMessage","switchMapTo","share","watchWorker","base","SETUP","Flag","renderSearchDocument","flag","parent","PARENT","teaser","TEASER","missing","flat","class","tabIndex","score","text","truncate","renderSearchResult","threshold","Infinity","findIndex","doc","article","best","more","section","renderSource","facts","fact","setupClipboard","dialog$","forEach","block","id","insertBefore","clipboard$","on","clearSelection","mapTo","setupInstantLoading","urls","location$","history","scrollRestoration","favicon","state$","body","metaKey","ctrlKey","closest","preventDefault","push$","pop$","state","merge","prev","ajax$","skip","fetch","credentials","then","res","catchError","setLocation","sample","pushState","dom","DOMParser","response","parseFromString","head","dispatchEvent","CustomEvent","debounceTime","replaceState","bufferCount","setupKeyboard","keyboard$","isContentEditable","isSusceptibleToKeyboard","claim","els","indexOf","HTMLInputElement","Error","select","setElementSelection","resetSearchQueryPlaceholder","placeholder","watchSearchQuery","transform","fn","value$","delay","focus$","watchElementFocus","mountSearchQuery","options","query$","setSearchQueryPlaceholder","applySearchQuery","mountSearchReset","watchSearchReset","addToSearchResultList","applySearchResult","ready$","fetch$","list","meta","setSearchResultMeta","resetSearchResultMeta","thresholds","scan","container","scrollHeight","resetSearchResultList","mountSearchResult","watchElementOffset","mountTabs","screen$","screen","hidden","setTabsHidden","resetTabsHidden","applyTabs","resetAnchorBlur","resetAnchorActive","classList","remove","mountTableOfContents","tablet$","tablet","sidebar$","anchors$","table","Map","decodeURIComponent","set","path","reduce","anchor","pop","reverse","watchAnchorList","toggle","setAnchorActive","setAnchorBlur","applyAnchorList","anchors","isAppleDevice","navigator","userAgent","fetchSourceFacts","match","toLowerCase","user","repo","status","json","stargazers_count","forks_count","public_repos","defaultIfEmpty","fetchSourceFactsFromGitHub","slug","project","encodeURIComponent","star_count","fetchSourceFactsFromGitLab","patchSource","len","charCodeAt","factory","sessionStorage","getItem","setItem","stringify","err","hasAttribute","setScrollLock","resetScrollLock","parseInt","initialize","features","isConfig","SyntaxError","ReplaySubject","watchDocument","take","watchLocationBase","hash$","passive","names","setupComponents","els$","scrollWidth","clientWidth","patchCodeBlocks","details","open","scrollIntoView","patchDetails","concatMap","script","src","onload","patchScripts","sentinel","patchTables","iif","patchScrollfix","duration","dialog","add","setupDialog","navigation$","mountNavigation","toc$","tabs$","search$","reset$","result$","status$","mountSearch","protocol","sort","charAt","toggles","dataset","mdState","indeterminate","direction","y0","y1","abs","hide","values","documentElement"],"mappings":"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","file":"assets/javascripts/bundle.83e5331e.min.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t0: 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([49,1]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve an element matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @return Element or nothing\n */\nexport function getElement(\n selector: string, node: ParentNode = document\n): T | undefined {\n return node.querySelector(selector) || undefined\n}\n\n/**\n * Retrieve an element matching a query selector or throw a reference error\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @return Element\n */\nexport function getElementOrThrow(\n selector: string, node: ParentNode = document\n): T {\n const el = getElement(selector, node)\n if (typeof el === \"undefined\")\n throw new ReferenceError(\n `Missing element: expected \"${selector}\" to be present`\n )\n return el\n}\n\n/**\n * Retrieve the currently active element\n *\n * @return Element or nothing\n */\nexport function getActiveElement(): HTMLElement | undefined {\n return document.activeElement instanceof HTMLElement\n ? document.activeElement\n : undefined\n}\n\n/**\n * Retrieve all elements matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @return Elements\n */\nexport function getElements(\n selector: string, node: ParentNode = document\n): T[] {\n return Array.from(node.querySelectorAll(selector))\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Create an element\n *\n * @template T - Tag name type\n *\n * @param tagName - Tag name\n *\n * @return Element\n */\nexport function createElement(\n tagName: T\n): HTMLElementTagNameMap[T] {\n return document.createElement(tagName)\n}\n\n/**\n * Replace an element with another element\n *\n * @param source - Source element\n * @param target - Target element\n */\nexport function replaceElement(\n source: HTMLElement, target: Node\n): void {\n source.replaceWith(target)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\nimport { getActiveElement } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set element focus\n *\n * @param el - Element\n * @param value - Whether the element should be focused\n */\nexport function setElementFocus(\n el: HTMLElement, value: boolean = true\n): void {\n if (value)\n el.focus()\n else\n el.blur()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element focus\n *\n * @param el - Element\n *\n * @return Element focus observable\n */\nexport function watchElementFocus(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(el, \"focus\"),\n fromEvent(el, \"blur\")\n )\n .pipe(\n map(({ type }) => type === \"focus\"),\n startWith(el === getActiveElement())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementOffset {\n x: number /* Horizontal offset */\n y: number /* Vertical offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element offset\n *\n * @param el - Element\n *\n * @return Element offset\n */\nexport function getElementOffset(el: HTMLElement): ElementOffset {\n return {\n x: el.scrollLeft,\n y: el.scrollTop\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element offset\n *\n * @param el - Element\n *\n * @return Element offset observable\n */\nexport function watchElementOffset(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(el, \"scroll\"),\n fromEvent(window, \"resize\")\n )\n .pipe(\n map(() => getElementOffset(el)),\n startWith(getElementOffset(el))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n NEVER,\n Observable,\n Subject,\n defer,\n of\n} from \"rxjs\"\nimport {\n filter,\n finalize,\n map,\n shareReplay,\n startWith,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementSize {\n width: number /* Element width */\n height: number /* Element height */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Resize observer entry subject\n */\nconst entry$ = new Subject()\n\n/**\n * Resize observer observable\n *\n * This observable will create a `ResizeObserver` on the first subscription\n * and will automatically terminate it when there are no more subscribers.\n * It's quite important to centralize observation in a single `ResizeObserver`,\n * as the performance difference can be quite dramatic, as the link shows.\n *\n * @see https://bit.ly/3iIYfEm - Google Groups on performance\n */\nconst observer$ = defer(() => of(\n new ResizeObserver(entries => {\n for (const entry of entries)\n entry$.next(entry)\n })\n))\n .pipe(\n switchMap(resize => NEVER.pipe(startWith(resize))\n .pipe(\n finalize(() => resize.disconnect())\n )\n ),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element size\n *\n * @param el - Element\n *\n * @return Element size\n */\nexport function getElementSize(el: HTMLElement): ElementSize {\n return {\n width: el.offsetWidth,\n height: el.offsetHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element size\n *\n * This function returns an observable that will subscribe to a single internal\n * instance of `ResizeObserver` upon subscription, and emit resize events until\n * termination. Note that this function should not be called with the same\n * element twice, as the first unsubscription will terminate observation.\n *\n * @param el - Element\n *\n * @return Element size observable\n */\nexport function watchElementSize(\n el: HTMLElement\n): Observable {\n return observer$\n .pipe(\n tap(observer => observer.observe(el)),\n switchMap(observer => entry$\n .pipe(\n filter(({ target }) => target === el),\n finalize(() => observer.unobserve(el)),\n map(({ contentRect }) => ({\n width: contentRect.width,\n height: contentRect.height\n }))\n )\n ),\n startWith(getElementSize(el))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { BehaviorSubject, Subject } from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location\n *\n * This function will return a `URL` object (and not `Location`) in order to\n * normalize typings across the application. Furthermore, locations need to be\n * tracked without setting them and `Location` is a singleton which represents\n * the current location.\n *\n * @return URL\n */\nexport function getLocation(): URL {\n return new URL(location.href)\n}\n\n/**\n * Set location\n *\n * @param url - URL to change to\n */\nexport function setLocation(url: URL): void {\n location.href = url.href\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Check whether a URL is a local link or a file (except `.html`)\n *\n * @param url - URL or HTML anchor element\n * @param ref - Reference URL\n *\n * @return Test result\n */\nexport function isLocalLocation(\n url: URL | HTMLAnchorElement,\n ref: URL | Location = location\n): boolean {\n return url.host === ref.host\n && /^(?:\\/[\\w-]+)*(?:\\/?|\\.html)$/i.test(url.pathname)\n}\n\n/**\n * Check whether a URL is an anchor link on the current page\n *\n * @param url - URL or HTML anchor element\n * @param ref - Reference URL\n *\n * @return Test result\n */\nexport function isAnchorLocation(\n url: URL | HTMLAnchorElement,\n ref: URL | Location = location\n): boolean {\n return url.pathname === ref.pathname\n && url.hash.length > 0\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location\n *\n * @return Location subject\n */\nexport function watchLocation(): Subject {\n return new BehaviorSubject(getLocation())\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { filter, map, share, startWith } from \"rxjs/operators\"\n\nimport { createElement } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location hash\n *\n * @return Location hash\n */\nexport function getLocationHash(): string {\n return location.hash.substring(1)\n}\n\n/**\n * Set location hash\n *\n * Setting a new fragment identifier via `location.hash` will have no effect\n * if the value doesn't change. When a new fragment identifier is set, we want\n * the browser to target the respective element at all times, which is why we\n * use this dirty little trick.\n *\n * @param hash - Location hash\n */\nexport function setLocationHash(hash: string): void {\n const el = createElement(\"a\")\n el.href = hash\n el.addEventListener(\"click\", ev => ev.stopPropagation())\n el.click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location hash\n *\n * @return Location hash observable\n */\nexport function watchLocationHash(): Observable {\n return fromEvent(window, \"hashchange\")\n .pipe(\n map(getLocationHash),\n startWith(getLocationHash()),\n filter(hash => hash.length > 0),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\nimport { shareReplay, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch media query\n *\n * @param query - Media query\n *\n * @return Media observable\n */\nexport function watchMedia(query: string): Observable {\n const media = matchMedia(query)\n return new Observable(subscriber => {\n media.addListener(ev => subscriber.next(ev.matches))\n })\n .pipe(\n startWith(media.matches),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\nimport { getElementOrThrow } from \"../element\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle\n */\nexport type Toggle =\n | \"drawer\" /* Toggle for drawer */\n | \"search\" /* Toggle for search */\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle map\n */\nconst toggles: Record = {\n drawer: getElementOrThrow(`[data-md-toggle=drawer]`),\n search: getElementOrThrow(`[data-md-toggle=search]`)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve the value of a toggle\n *\n * @param name - Toggle\n *\n * @return Toggle value\n */\nexport function getToggle(name: Toggle): boolean {\n return toggles[name].checked\n}\n\n/**\n * Set toggle\n *\n * Simulating a click event seems to be the most cross-browser compatible way\n * of changing the value while also emitting a `change` event. Before, Material\n * used `CustomEvent` to programmatically change the value of a toggle, but this\n * is a much simpler and cleaner solution which doesn't require a polyfill.\n *\n * @param name - Toggle\n * @param value - Toggle value\n */\nexport function setToggle(name: Toggle, value: boolean): void {\n if (toggles[name].checked !== value)\n toggles[name].click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch toggle\n *\n * @param name - Toggle\n *\n * @return Toggle value observable\n */\nexport function watchToggle(name: Toggle): Observable {\n const el = toggles[name]\n return fromEvent(el, \"change\")\n .pipe(\n map(() => el.checked),\n startWith(el.checked)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport offset\n */\nexport interface ViewportOffset {\n x: number /* Horizontal offset */\n y: number /* Vertical offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport offset\n *\n * On iOS Safari, viewport offset can be negative due to overflow scrolling.\n * As this may induce strange behaviors downstream, we'll just limit it to 0.\n *\n * @return Viewport offset\n */\nexport function getViewportOffset(): ViewportOffset {\n return {\n x: Math.max(0, pageXOffset),\n y: Math.max(0, pageYOffset)\n }\n}\n\n/**\n * Set viewport offset\n *\n * @param offset - Viewport offset\n */\nexport function setViewportOffset(\n { x, y }: Partial\n): void {\n window.scrollTo(x || 0, y || 0)\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport offset\n *\n * @return Viewport offset observable\n */\nexport function watchViewportOffset(): Observable {\n return merge(\n fromEvent(window, \"scroll\", { passive: true }),\n fromEvent(window, \"resize\", { passive: true })\n )\n .pipe(\n map(getViewportOffset),\n startWith(getViewportOffset())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport size\n */\nexport interface ViewportSize {\n width: number /* Viewport width */\n height: number /* Viewport height */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport size\n *\n * @return Viewport size\n */\nexport function getViewportSize(): ViewportSize {\n return {\n width: innerWidth,\n height: innerHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport size\n *\n * @return Viewport size observable\n */\nexport function watchViewportSize(): Observable {\n return fromEvent(window, \"resize\", { passive: true })\n .pipe(\n map(getViewportSize),\n startWith(getViewportSize())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, combineLatest } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n map,\n shareReplay\n} from \"rxjs/operators\"\n\nimport { Header } from \"components\"\n\nimport {\n ViewportOffset,\n watchViewportOffset\n} from \"../offset\"\nimport {\n ViewportSize,\n watchViewportSize\n} from \"../size\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport\n */\nexport interface Viewport {\n offset: ViewportOffset /* Viewport offset */\n size: ViewportSize /* Viewport size */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch at options\n */\ninterface WatchAtOptions {\n header$: Observable
/* Header observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport\n *\n * @return Viewport observable\n */\nexport function watchViewport(): Observable {\n return combineLatest([\n watchViewportOffset(),\n watchViewportSize()\n ])\n .pipe(\n map(([offset, size]) => ({ offset, size })),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n\n/**\n * Watch viewport relative to element\n *\n * @param el - Element\n * @param options - Options\n *\n * @return Viewport observable\n */\nexport function watchViewportAt(\n el: HTMLElement, { header$, viewport$ }: WatchAtOptions\n): Observable {\n const size$ = viewport$\n .pipe(\n distinctUntilKeyChanged(\"size\")\n )\n\n /* Compute element offset */\n const offset$ = combineLatest([size$, header$])\n .pipe(\n map((): ViewportOffset => ({\n x: el.offsetLeft,\n y: el.offsetTop\n }))\n )\n\n /* Compute relative viewport, return hot observable */\n return combineLatest([header$, viewport$, offset$])\n .pipe(\n map(([{ height }, { offset, size }, { x, y }]) => ({\n offset: {\n x: offset.x - x,\n y: offset.y - y + height\n },\n size\n }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { EMPTY, Observable, of } from \"rxjs\"\nimport {\n distinctUntilChanged,\n map,\n scan,\n shareReplay,\n switchMap\n} from \"rxjs/operators\"\n\nimport { getElement, replaceElement } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Component\n */\nexport type Component =\n | \"announce\" /* Announcement bar */\n | \"container\" /* Container */\n | \"header\" /* Header */\n | \"header-title\" /* Header title */\n | \"main\" /* Main area */\n | \"navigation\" /* Navigation */\n | \"search\" /* Search */\n | \"search-query\" /* Search input */\n | \"search-reset\" /* Search reset */\n | \"search-result\" /* Search results */\n | \"skip\" /* Skip link */\n | \"tabs\" /* Tabs */\n | \"toc\" /* Table of contents */\n\n/**\n * Component map\n */\nexport type ComponentMap = {\n [P in Component]?: HTMLElement\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Component map observable\n */\nlet components$: Observable\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up bindings to components with given names\n *\n * This function will maintain bindings to the elements identified by the given\n * names in-between document switches and update the elements in-place.\n *\n * @param names - Component names\n * @param options - Options\n */\nexport function setupComponents(\n names: Component[], { document$ }: WatchOptions\n): void {\n components$ = document$\n .pipe(\n\n /* Build component map */\n map(document => names.reduce((components, name) => {\n const el = getElement(`[data-md-component=${name}]`, document)\n return {\n ...components,\n ...typeof el !== \"undefined\" ? { [name]: el } : {}\n }\n }, {})),\n\n /* Re-compute component map on document switch */\n scan((prev, next) => {\n for (const name of names) {\n switch (name) {\n\n /* Top-level components: update */\n case \"announce\":\n case \"header-title\":\n case \"container\":\n case \"skip\":\n if (name in prev && typeof prev[name] !== \"undefined\") {\n replaceElement(prev[name]!, next[name]!)\n prev[name] = next[name]\n }\n break\n\n /* All other components: rebind */\n default:\n if (typeof next[name] !== \"undefined\")\n prev[name] = getElement(`[data-md-component=${name}]`)\n else\n delete prev[name]\n }\n }\n return prev\n }),\n\n /* Convert to hot observable */\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n\n/**\n * Retrieve a component\n *\n * The returned observable will only re-emit if the element changed, i.e. if\n * it was replaced from a document which was switched to.\n *\n * @template T - Element type\n *\n * @param name - Component name\n *\n * @return Component observable\n */\nexport function useComponent(\n name: Component\n): Observable {\n return components$\n .pipe(\n switchMap(components => (\n typeof components[name] !== \"undefined\"\n ? of(components[name] as T)\n : EMPTY\n )),\n distinctUntilChanged()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, combineLatest, pipe } from \"rxjs\"\nimport {\n distinctUntilChanged,\n filter,\n map,\n startWith,\n switchMap,\n zipWith\n} from \"rxjs/operators\"\n\nimport {\n Viewport,\n getElement,\n watchViewportAt\n} from \"browser\"\n\nimport { useComponent } from \"../../_\"\nimport {\n applyHeaderType,\n watchHeader\n} from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Header type\n */\nexport type HeaderType =\n | \"site\" /* Header shows site title */\n | \"page\" /* Header shows page title */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Header\n */\nexport interface Header {\n type: HeaderType /* Header type */\n sticky: boolean /* Header stickyness */\n height: number /* Header visible height */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n document$: Observable /* Document observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount header from source observable\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountHeader(\n { document$, viewport$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => {\n const header$ = watchHeader(el, { document$ })\n\n /* Compute whether the header should switch to page header */\n const type$ = useComponent(\"main\")\n .pipe(\n map(main => getElement(\"h1, h2, h3, h4, h5, h6\", main)!),\n filter(hx => typeof hx !== \"undefined\"),\n zipWith(useComponent(\"header-title\")),\n switchMap(([hx, title]) => watchViewportAt(hx, { header$, viewport$ })\n .pipe(\n map(({ offset: { y } }) => {\n return y >= hx.offsetHeight ? \"page\" : \"site\"\n }),\n distinctUntilChanged(),\n applyHeaderType(title)\n )\n ),\n startWith(\"site\")\n )\n\n /* Combine into single observable */\n return combineLatest([header$, type$])\n .pipe(\n map(([header, type]): Header => ({ type, ...header }))\n )\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n of,\n pipe\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n finalize,\n map,\n observeOn,\n shareReplay,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { watchElementSize } from \"browser\"\n\nimport { Header, HeaderType } from \"../_\"\nimport {\n resetHeaderTitleActive,\n setHeaderTitleActive\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch header\n *\n * @param el - Header element\n *\n * @return Header observable\n */\nexport function watchHeader(\n el: HTMLElement, { document$ }: WatchOptions\n): Observable> {\n return document$\n .pipe(\n map(() => {\n const styles = getComputedStyle(el)\n return [\n \"sticky\", /* Modern browsers */\n \"-webkit-sticky\" /* Safari */\n ].includes(styles.position)\n }),\n distinctUntilChanged(),\n switchMap(sticky => {\n if (sticky) {\n return watchElementSize(el)\n .pipe(\n map(({ height }) => ({\n sticky: true,\n height\n }))\n )\n } else {\n return of({\n sticky: false,\n height: 0\n })\n }\n }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply header title type\n *\n * @param el - Header title element\n *\n * @return Operator function\n */\nexport function applyHeaderType(\n el: HTMLElement\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n tap(type => {\n setHeaderTitleActive(el, type === \"page\")\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n resetHeaderTitleActive(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set header title active\n *\n * @param el - Header title element\n * @param value - Whether the title is shown\n */\nexport function setHeaderTitleActive(\n el: HTMLElement, value: boolean\n): void {\n el.setAttribute(\"data-md-state\", value ? \"active\" : \"\")\n}\n\n/**\n * Reset header title active\n *\n * @param el - Header title element\n */\nexport function resetHeaderTitleActive(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n OperatorFunction,\n Subject,\n noop,\n pipe\n} from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n finalize,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { Viewport } from \"browser\"\n\nimport { useComponent } from \"../../_\"\nimport { Header } from \"../../header\"\nimport {\n applyHeaderShadow,\n watchMain\n} from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Main area\n */\nexport interface Main {\n offset: number /* Main area top offset */\n height: number /* Main area visible height */\n active: boolean /* Scrolled past top offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n header$: Observable
/* Header observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount main area from source observable\n *\n * The header must be connected to the main area observable outside of the\n * operator function, as the header will persist in-between document switches\n * while the main area is replaced. However, the header observable must be\n * passed to this function, so we connect both via a long-living subject.\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountMain(\n { header$, viewport$ }: MountOptions\n): OperatorFunction {\n const main$ = new Subject
()\n\n /* Connect to main area observable via long-living subject */\n useComponent(\"header\")\n .pipe(\n switchMap(header => main$\n .pipe(\n distinctUntilKeyChanged(\"active\"),\n applyHeaderShadow(header)\n )\n )\n )\n .subscribe(noop)\n\n /* Return operator */\n return pipe(\n switchMap(el => watchMain(el, { header$, viewport$ })),\n tap(main => main$.next(main)),\n finalize(() => main$.complete())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n combineLatest,\n pipe\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { Viewport, watchElementSize } from \"browser\"\n\nimport { Header } from \"../../header\"\nimport { Main } from \"../_\"\nimport {\n resetHeaderShadow,\n setHeaderShadow\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n header$: Observable
/* Header observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch main area\n *\n * This function returns an observable that computes the visual parameters of\n * the main area which depends on the viewport vertical offset and height, as\n * well as the height of the header element, if the header is fixed.\n *\n * @param el - Main area element\n * @param options - Options\n *\n * @return Main area observable\n */\nexport function watchMain(\n el: HTMLElement, { header$, viewport$ }: WatchOptions\n): Observable
{\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n map(({ height }) => height),\n distinctUntilChanged()\n )\n\n /* Compute the main area's top and bottom borders */\n const border$ = adjust$\n .pipe(\n switchMap(() => watchElementSize(el)\n .pipe(\n map(({ height }) => ({\n top: el.offsetTop,\n bottom: el.offsetTop + height\n })),\n distinctUntilKeyChanged(\"bottom\")\n )\n )\n )\n\n /* Compute the main area's offset, visible height and if we scrolled past */\n return combineLatest([adjust$, border$, viewport$])\n .pipe(\n map(([header, { top, bottom }, { offset: { y }, size: { height } }]) => {\n height = Math.max(0, height\n - Math.max(0, top - y, header)\n - Math.max(0, height + y - bottom)\n )\n return {\n offset: top - header,\n height,\n active: top - header <= y\n }\n }),\n distinctUntilChanged
((a, b) => {\n return a.offset === b.offset\n && a.height === b.height\n && a.active === b.active\n })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply header shadow\n *\n * @param el - Header element\n *\n * @return Operator function\n */\nexport function applyHeaderShadow(\n el: HTMLElement\n): MonoTypeOperatorFunction
{\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n tap(({ active }) => {\n setHeaderShadow(el, active)\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n resetHeaderShadow(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set header shadow\n *\n * @param el - Header element\n * @param value - Whether the shadow is shown\n */\nexport function setHeaderShadow(\n el: HTMLElement, value: boolean\n): void {\n el.setAttribute(\"data-md-state\", value ? \"shadow\" : \"\")\n}\n\n/**\n * Reset header shadow\n *\n * @param el - Header element\n */\nexport function resetHeaderShadow(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set sidebar offset\n *\n * @param el - Sidebar element\n * @param value - Sidebar offset\n */\nexport function setSidebarOffset(\n el: HTMLElement, value: number\n): void {\n el.style.top = `${value}px`\n}\n\n/**\n * Reset sidebar offset\n *\n * @param el - Sidebar element\n */\nexport function resetSidebarOffset(\n el: HTMLElement\n): void {\n el.style.top = \"\"\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set sidebar height\n *\n * This function doesn't set the height of the actual sidebar, but of its first\n * child – the `.md-sidebar__scrollwrap` element in order to mitigiate jittery\n * sidebars when the footer is scrolled into view. At some point we switched\n * from `absolute` / `fixed` positioning to `sticky` positioning, which greatly\n * reduced jitter in some browsers (respectively Firefox and Safari) when\n * scrolling from the top. However, top-aligned sticky positioning means that\n * the sidebar snaps to the bottom when the end of the container is reached.\n * This is what leads to the mentioned jitter, as the sidebar's height may be\n * updated to slowly.\n *\n * By setting the height of the sidebar to zero (while preserving `padding`),\n * and the height on its first element, this behaviour can be mitigiated. We\n * must assume that the top- and bottom offset (`padding`) are equal, as the\n * `offsetBottom` value is `undefined`.\n *\n * @param el - Sidebar element\n * @param value - Sidebar height\n */\nexport function setSidebarHeight(\n el: HTMLElement, value: number\n): void {\n const scrollwrap = el.firstElementChild as HTMLElement\n scrollwrap.style.height = `${value - 2 * scrollwrap.offsetTop}px`\n}\n\n/**\n * Reset sidebar height\n *\n * @param el - Sidebar element\n */\nexport function resetSidebarHeight(\n el: HTMLElement\n): void {\n const scrollwrap = el.firstElementChild as HTMLElement\n scrollwrap.style.height = \"\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n combineLatest,\n pipe\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n finalize,\n map,\n observeOn,\n tap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport { Viewport } from \"browser\"\n\nimport { Header } from \"../../../header\"\nimport { Main } from \"../../../main\"\nimport { Sidebar } from \"../_\"\nimport {\n resetSidebarHeight,\n resetSidebarOffset,\n setSidebarHeight,\n setSidebarOffset\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n main$: Observable
/* Main area observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/**\n * Apply options\n */\ninterface ApplyOptions {\n header$: Observable
/* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch sidebar\n *\n * This function returns an observable that computes the visual parameters of\n * the sidebar which depends on the vertical viewport offset, as well as the\n * height of the main area. When the page is scrolled beyond the header, the\n * sidebar is locked and fills the remaining space.\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @return Sidebar observable\n */\nexport function watchSidebar(\n el: HTMLElement, { main$, viewport$ }: WatchOptions\n): Observable {\n const adjust = el.parentElement!.offsetTop\n - el.parentElement!.parentElement!.offsetTop\n\n /* Compute the sidebar's available height and if it should be locked */\n return combineLatest([main$, viewport$])\n .pipe(\n map(([{ offset, height }, { offset: { y } }]) => {\n height = height\n + Math.min(adjust, Math.max(0, y - offset))\n - adjust\n return {\n height,\n lock: y >= offset + adjust\n }\n }),\n distinctUntilChanged((a, b) => {\n return a.height === b.height\n && a.lock === b.lock\n })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply sidebar\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @return Operator function\n */\nexport function applySidebar(\n el: HTMLElement, { header$ }: ApplyOptions\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n withLatestFrom(header$),\n tap(([{ height, lock }, { height: offset }]) => {\n setSidebarHeight(el, height)\n\n /* Set offset in locked state depending on header height */\n if (lock)\n setSidebarOffset(el, offset)\n else\n resetSidebarOffset(el)\n }),\n\n /* Re-map to sidebar */\n map(([sidebar]) => sidebar),\n\n /* Reset on complete or error */\n finalize(() => {\n resetSidebarOffset(el)\n resetSidebarHeight(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search transformation function\n *\n * @param value - Query value\n *\n * @return Transformed query value\n */\nexport type SearchTransformFn = (value: string) => string\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Default transformation function\n *\n * 1. Search for terms in quotation marks and prepend a `+` modifier to denote\n * that the resulting document must contain all terms, converting the query\n * to an `AND` query (as opposed to the default `OR` behavior). While users\n * may expect terms enclosed in quotation marks to map to span queries, i.e.\n * for which order is important, `lunr` doesn't support them, so the best\n * we can do is to convert the terms to an `AND` query.\n *\n * 2. Replace control characters which are not located at the beginning of the\n * query or preceded by white space, or are not followed by a non-whitespace\n * character or are at the end of the query string. Furthermore, filter\n * unmatched quotation marks.\n *\n * 3. Trim excess whitespace from left and right.\n *\n * @param query - Query value\n *\n * @return Transformed query value\n */\nexport function defaultTransform(query: string): string {\n return query\n .split(/\"([^\"]+)\"/g) /* => 1 */\n .map((terms, index) => index & 1\n ? terms.replace(/^\\b|^(?![^\\x00-\\x7F]|$)|\\s+/g, \" +\")\n : terms\n )\n .join(\"\")\n .replace(/\"|(?:^|\\s+)[*+\\-:^~]+(?=\\s+|$)/g, \"\") /* => 2 */\n .trim() /* => 3 */\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n// tslint:disable no-null-keyword\n\nimport { JSX as JSXInternal } from \"preact\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * HTML attributes\n */\ntype Attributes =\n & JSXInternal.HTMLAttributes\n & JSXInternal.SVGAttributes\n & Record\n\n/**\n * Child element\n */\ntype Child =\n | HTMLElement\n | Text\n | string\n | number\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Append a child node to an element\n *\n * @param el - Element\n * @param child - Child node(s)\n */\nfunction appendChild(el: HTMLElement, child: Child | Child[]): void {\n\n /* Handle primitive types (including raw HTML) */\n if (typeof child === \"string\" || typeof child === \"number\") {\n el.innerHTML += child.toString()\n\n /* Handle nodes */\n } else if (child instanceof Node) {\n el.appendChild(child)\n\n /* Handle nested children */\n } else if (Array.isArray(child)) {\n for (const node of child)\n appendChild(el, node)\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * JSX factory\n *\n * @param tag - HTML tag\n * @param attributes - HTML attributes\n * @param children - Child elements\n *\n * @return Element\n */\nexport function h(\n tag: string, attributes: Attributes | null, ...children: Child[]\n): HTMLElement {\n const el = document.createElement(tag)\n\n /* Set attributes, if any */\n if (attributes)\n for (const attr of Object.keys(attributes))\n if (typeof attributes[attr] !== \"boolean\")\n el.setAttribute(attr, attributes[attr])\n else if (attributes[attr])\n el.setAttribute(attr, \"\")\n\n /* Append child nodes */\n for (const child of children)\n appendChild(el, child)\n\n /* Return element */\n return el\n}\n\n/* ----------------------------------------------------------------------------\n * Namespace\n * ------------------------------------------------------------------------- */\n\nexport declare namespace h {\n namespace JSX {\n type Element = HTMLElement\n type IntrinsicElements = JSXInternal.IntrinsicElements\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { getElementOrThrow } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Translation keys\n */\ntype TranslateKey =\n | \"clipboard.copy\" /* Copy to clipboard */\n | \"clipboard.copied\" /* Copied to clipboard */\n | \"search.config.lang\" /* Search language */\n | \"search.config.pipeline\" /* Search pipeline */\n | \"search.config.separator\" /* Search separator */\n | \"search.placeholder\" /* Search */\n | \"search.result.placeholder\" /* Type to start searching */\n | \"search.result.none\" /* No matching documents */\n | \"search.result.one\" /* 1 matching document */\n | \"search.result.other\" /* # matching documents */\n | \"search.result.more.one\" /* 1 more on this page */\n | \"search.result.more.other\" /* # more on this page */\n | \"search.result.term.missing\" /* Missing */\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Translations\n */\nlet lang: Record\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Translate the given key\n *\n * @param key - Key to be translated\n * @param value - Value to be replaced\n *\n * @return Translation\n */\nexport function translate(\n key: TranslateKey, value?: string | number\n): string {\n if (typeof lang === \"undefined\") {\n const el = getElementOrThrow(\"#__lang\")\n lang = JSON.parse(el.textContent!)\n }\n if (typeof lang[key] === \"undefined\") {\n throw new ReferenceError(`Invalid translation: ${key}`)\n }\n return typeof value !== \"undefined\"\n ? lang[key].replace(\"#\", value.toString())\n : lang[key]\n}\n\n/**\n * Truncate a string after the given number of characters\n *\n * This is not a very reasonable approach, since the summaries kind of suck.\n * It would be better to create something more intelligent, highlighting the\n * search occurrences and making a better summary out of it, but this note was\n * written three years ago, so who knows if we'll ever fix it.\n *\n * @param value - Value to be truncated\n * @param n - Number of characters\n *\n * @return Truncated value\n */\nexport function truncate(value: string, n: number): string {\n let i = n\n if (value.length > i) {\n while (value[i] !== \" \" && --i > 0); // tslint:disable-line\n return `${value.substring(0, i)}...`\n }\n return value\n}\n\n/**\n * Round a number for display with source facts\n *\n * This is a reverse engineered version of GitHub's weird rounding algorithm\n * for stars, forks and all other numbers. While all numbers below `1,000` are\n * returned as-is, bigger numbers are converted to fixed numbers:\n *\n * - `1,049` => `1k`\n * - `1,050` => `1.1k`\n * - `1,949` => `1.9k`\n * - `1,950` => `2k`\n *\n * @param value - Original value\n *\n * @return Rounded value\n */\nexport function round(value: number): string {\n if (value > 999) {\n const digits = +((value - 950) % 1000 > 99)\n return `${((value + 0.000001) / 1000).toFixed(digits)}k`\n } else {\n return value.toString()\n }\n}\n\n/**\n * Simple hash function\n *\n * @see https://bit.ly/2wsVjJ4 - Original source\n *\n * @param value - Value to be hashed\n *\n * @return Hash as 32bit integer\n */\nexport function hash(value: string): number {\n let h = 0\n for (let i = 0, len = value.length; i < len; i++) {\n h = ((h << 5) - h) + value.charCodeAt(i)\n h |= 0 // Convert to 32bit integer\n }\n return h\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndex, SearchResult } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search message type\n */\nexport const enum SearchMessageType {\n SETUP, /* Search index setup */\n READY, /* Search index ready */\n QUERY, /* Search query */\n RESULT /* Search results */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message containing the data necessary to setup the search index\n */\nexport interface SearchSetupMessage {\n type: SearchMessageType.SETUP /* Message type */\n data: SearchIndex /* Message data */\n}\n\n/**\n * A message indicating the search index is ready\n */\nexport interface SearchReadyMessage {\n type: SearchMessageType.READY /* Message type */\n}\n\n/**\n * A message containing a search query\n */\nexport interface SearchQueryMessage {\n type: SearchMessageType.QUERY /* Message type */\n data: string /* Message data */\n}\n\n/**\n * A message containing results for a search query\n */\nexport interface SearchResultMessage {\n type: SearchMessageType.RESULT /* Message type */\n data: SearchResult[] /* Message data */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message exchanged with the search worker\n */\nexport type SearchMessage =\n | SearchSetupMessage\n | SearchReadyMessage\n | SearchQueryMessage\n | SearchResultMessage\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Type guard for search setup messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchSetupMessage(\n message: SearchMessage\n): message is SearchSetupMessage {\n return message.type === SearchMessageType.SETUP\n}\n\n/**\n * Type guard for search ready messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchReadyMessage(\n message: SearchMessage\n): message is SearchReadyMessage {\n return message.type === SearchMessageType.READY\n}\n\n/**\n * Type guard for search query messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchQueryMessage(\n message: SearchMessage\n): message is SearchQueryMessage {\n return message.type === SearchMessageType.QUERY\n}\n\n/**\n * Type guard for search result messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchResultMessage(\n message: SearchMessage\n): message is SearchResultMessage {\n return message.type === SearchMessageType.RESULT\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject, asyncScheduler } from \"rxjs\"\nimport {\n map,\n observeOn,\n share,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport { WorkerHandler, watchWorker } from \"browser\"\nimport { translate } from \"utilities\"\n\nimport { SearchIndex, SearchIndexPipeline } from \"../../_\"\nimport {\n SearchMessage,\n SearchMessageType,\n SearchSetupMessage,\n isSearchResultMessage\n} from \"../message\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n index$: Observable /* Search index observable */\n base$: Observable /* Location base observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search index\n *\n * @param data - Search index\n *\n * @return Search index\n */\nfunction setupSearchIndex(\n { config, docs, index }: SearchIndex\n): SearchIndex {\n\n /* Override default language with value from translation */\n if (config.lang.length === 1 && config.lang[0] === \"en\")\n config.lang = [translate(\"search.config.lang\")]\n\n /* Override default separator with value from translation */\n if (config.separator === \"[\\\\s\\\\-]+\")\n config.separator = translate(\"search.config.separator\")\n\n /* Set pipeline from translation */\n const pipeline = translate(\"search.config.pipeline\")\n .split(/\\s*,\\s*/)\n .filter(Boolean) as SearchIndexPipeline\n\n /* Return search index after defaulting */\n return { config, docs, index, pipeline }\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search web worker\n *\n * This function will create a web worker to set up and query the search index\n * which is done using `lunr`. The index must be passed as an observable to\n * enable hacks like _localsearch_ via search index embedding as JSON.\n *\n * @param url - Worker URL\n * @param options - Options\n *\n * @return Worker handler\n */\nexport function setupSearchWorker(\n url: string, { index$, base$ }: SetupOptions\n): WorkerHandler {\n const worker = new Worker(url)\n\n /* Create communication channels and resolve relative links */\n const tx$ = new Subject()\n const rx$ = watchWorker(worker, { tx$ })\n .pipe(\n withLatestFrom(base$),\n map(([message, base]) => {\n if (isSearchResultMessage(message)) {\n for (const result of message.data)\n for (const document of result)\n document.location = `${base}/${document.location}`\n }\n return message\n }),\n share()\n )\n\n /* Set up search index */\n index$\n .pipe(\n map(data => ({\n type: SearchMessageType.SETUP,\n data: setupSearchIndex(data)\n })),\n observeOn(asyncScheduler)\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Return worker handler */\n return { tx$, rx$ }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject, fromEvent } from \"rxjs\"\nimport {\n map,\n share,\n switchMapTo,\n tap,\n throttle\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Worker message\n */\nexport interface WorkerMessage {\n type: unknown /* Message type */\n data?: unknown /* Message data */\n}\n\n/**\n * Worker handler\n *\n * @template T - Message type\n */\nexport interface WorkerHandler<\n T extends WorkerMessage\n> {\n tx$: Subject /* Message transmission subject */\n rx$: Observable /* Message receive observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n *\n * @template T - Worker message type\n */\ninterface WatchOptions {\n tx$: Observable /* Message transmission observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch a web worker\n *\n * This function returns an observable that will send all values emitted by the\n * message observable to the web worker. Web worker communication is expected\n * to be bidirectional (request-response) and synchronous. Messages that are\n * emitted during a pending request are throttled, the last one is emitted.\n *\n * @param worker - Web worker\n * @param options - Options\n *\n * @return Worker message observable\n */\nexport function watchWorker(\n worker: Worker, { tx$ }: WatchOptions\n): Observable {\n\n /* Intercept messages from worker-like objects */\n const rx$ = fromEvent(worker, \"message\")\n .pipe(\n map(({ data }) => data)\n )\n\n /* Send and receive messages, return hot observable */\n return tx$\n .pipe(\n throttle(() => rx$, { leading: true, trailing: true }),\n tap(message => worker.postMessage(message)),\n switchMapTo(rx$),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n SearchDocument,\n SearchMetadata,\n SearchResult\n} from \"integrations/search\"\nimport { h, translate, truncate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Render flag\n */\nconst enum Flag {\n TEASER = 1, /* Render teaser */\n PARENT = 2 /* Render as parent */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper function\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search document\n *\n * @param section - Search document\n * @param flag - Render flags\n *\n * @return Element\n */\nfunction renderSearchDocument(\n document: SearchDocument & SearchMetadata, flag: Flag\n) {\n const parent = flag & Flag.PARENT\n const teaser = flag & Flag.TEASER\n\n /* Render missing query terms */\n const missing = Object.keys(document.terms)\n .filter(key => !document.terms[key])\n .map(key => [{key}, \" \"])\n .flat()\n .slice(0, -1)\n\n /* Render article or section, depending on flags */\n const url = document.location\n return (\n \n \n {parent > 0 &&
}\n

{document.title}

\n {teaser > 0 && document.text.length > 0 &&\n

\n {truncate(document.text, 320)}\n

\n }\n {teaser > 0 && missing.length > 0 &&\n

\n {translate(\"search.result.term.missing\")}: {...missing}\n

\n }\n \n
\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search result\n *\n * @param result - Search result\n * @param threshold - Score threshold\n *\n * @return Element\n */\nexport function renderSearchResult(\n result: SearchResult, threshold: number = Infinity\n) {\n const docs = [...result]\n\n /* Find and extract parent article */\n const parent = docs.findIndex(doc => !doc.location.includes(\"#\"))\n const [article] = docs.splice(parent, 1)\n\n /* Determine last index above threshold */\n let index = docs.findIndex(doc => doc.score < threshold)\n if (index === -1)\n index = docs.length\n\n /* Partition sections */\n const best = docs.slice(0, index)\n const more = docs.slice(index)\n\n /* Render children */\n const children = [\n renderSearchDocument(article, Flag.PARENT | +(!parent && index === 0)),\n ...best.map(section => renderSearchDocument(section, Flag.TEASER)),\n ...more.length ? [\n
\n \n {more.length > 0 && more.length === 1\n ? translate(\"search.result.more.one\")\n : translate(\"search.result.more.other\", more.length)\n }\n \n {...more.map(section => renderSearchDocument(section, Flag.TEASER))}\n
\n ] : []\n ]\n\n /* Render search result */\n return (\n
  • \n {children}\n
  • \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SourceFacts } from \"patches/source\"\nimport { h } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render source facts\n *\n * @param facts - Source facts\n *\n * @return Element\n */\nexport function renderSource(\n facts: SourceFacts\n) {\n return (\n
      \n {facts.map(fact => (\n
    • {fact}
    • \n ))}\n
    \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport * as ClipboardJS from \"clipboard\"\nimport { NEVER, Observable, Subject } from \"rxjs\"\nimport { mapTo, share, tap } from \"rxjs/operators\"\n\nimport { getElements } from \"browser\"\nimport { renderClipboardButton } from \"templates\"\nimport { translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n document$: Observable /* Document observable */\n dialog$: Subject /* Dialog subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up clipboard\n *\n * This function implements the Clipboard.js integration and injects a button\n * into all code blocks when the document changes.\n *\n * @param options - Options\n *\n * @return Clipboard observable\n */\nexport function setupClipboard(\n { document$, dialog$ }: SetupOptions\n): Observable {\n if (!ClipboardJS.isSupported())\n return NEVER\n\n /* Inject 'copy-to-clipboard' buttons */\n document$.subscribe(() => {\n const blocks = getElements(\"pre > code\")\n blocks.forEach((block, index) => {\n const parent = block.parentElement!\n parent.id = `__code_${index}`\n parent.insertBefore(\n renderClipboardButton(parent.id),\n block\n )\n })\n })\n\n /* Initialize clipboard */\n const clipboard$ = new Observable(subscriber => {\n new ClipboardJS(\".md-clipboard\").on(\"success\", ev => subscriber.next(ev))\n })\n .pipe(\n share()\n )\n\n /* Display notification for clipboard event */\n clipboard$\n .pipe(\n tap(ev => ev.clearSelection()),\n mapTo(translate(\"clipboard.copied\"))\n )\n .subscribe(dialog$)\n\n /* Return clipboard */\n return clipboard$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h, translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a 'copy-to-clipboard' button\n *\n * @param id - Unique identifier\n *\n * @return Element\n */\nexport function renderClipboardButton(id: string) {\n return (\n code`}\n >\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, Subject, from, fromEvent, merge, of } from \"rxjs\"\nimport {\n bufferCount,\n catchError,\n debounceTime,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n map,\n sample,\n share,\n skip,\n switchMap\n} from \"rxjs/operators\"\n\nimport {\n Viewport,\n ViewportOffset,\n getElement,\n isAnchorLocation,\n isLocalLocation,\n replaceElement,\n setLocation,\n setLocationHash,\n setToggle,\n setViewportOffset\n} from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * History state\n */\ninterface State {\n url: URL /* State URL */\n offset?: ViewportOffset /* State viewport offset */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n document$: Subject /* Document subject */\n location$: Subject /* Location subject */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up instant loading\n *\n * When fetching, theoretically, we could use `responseType: \"document\"`, but\n * since all MkDocs links are relative, we need to make sure that the current\n * location matches the document we just loaded. Otherwise any relative links\n * in the document could use the old location.\n *\n * This is the reason why we need to synchronize history events and the process\n * of fetching the document for navigation changes (except `popstate` events):\n *\n * 1. Fetch document via `XMLHTTPRequest`\n * 2. Set new location via `history.pushState`\n * 3. Parse and emit fetched document\n *\n * For `popstate` events, we must not use `history.pushState`, or the forward\n * history will be irreversibly overwritten. In case the request fails, the\n * location change is dispatched regularly.\n *\n * @param options - Options\n */\nexport function setupInstantLoading(\n urls: string[], { document$, viewport$, location$ }: SetupOptions\n): void {\n\n /* Disable automatic scroll restoration */\n if (\"scrollRestoration\" in history)\n history.scrollRestoration = \"manual\"\n\n /* Hack: ensure that reloads restore viewport offset */\n fromEvent(window, \"beforeunload\")\n .subscribe(() => {\n history.scrollRestoration = \"auto\"\n })\n\n /* Hack: ensure absolute favicon link to omit 404s on document switch */\n const favicon = getElement(`link[rel=\"shortcut icon\"]`)\n if (typeof favicon !== \"undefined\")\n favicon.href = favicon.href // tslint:disable-line no-self-assignment\n\n /* Intercept link clicks and convert to state change */\n const state$ = fromEvent(document.body, \"click\")\n .pipe(\n filter(ev => !(ev.metaKey || ev.ctrlKey)),\n switchMap(ev => {\n if (ev.target instanceof HTMLElement) {\n const el = ev.target.closest(\"a\")\n if (\n el && !el.target &&\n isLocalLocation(el) &&\n urls.includes(el.href)\n ) {\n if (!isAnchorLocation(el))\n ev.preventDefault()\n return of(el)\n }\n }\n return NEVER\n }),\n map(el => ({ url: new URL(el.href) })),\n share()\n )\n\n /* Always close search on link click */\n state$.subscribe(() => {\n setToggle(\"search\", false)\n })\n\n /* Filter state changes to dispatch */\n const push$ = state$\n .pipe(\n filter(({ url }) => !isAnchorLocation(url)),\n share()\n )\n\n /* Intercept popstate events (history back and forward) */\n const pop$ = fromEvent(window, \"popstate\")\n .pipe(\n filter(ev => ev.state !== null),\n map(ev => ({\n url: new URL(location.href),\n offset: ev.state\n })),\n share()\n )\n\n /* Emit location change */\n merge(push$, pop$)\n .pipe(\n distinctUntilChanged((prev, next) => prev.url.href === next.url.href),\n map(({ url }) => url)\n )\n .subscribe(location$)\n\n /* Fetch document on location change */\n const ajax$ = location$\n .pipe(\n distinctUntilKeyChanged(\"pathname\"),\n skip(1),\n switchMap(url => from(fetch(url.href, {\n credentials: \"same-origin\"\n }).then(res => res.text()))\n .pipe(\n catchError(() => {\n setLocation(url)\n return NEVER\n })\n )\n ),\n share()\n )\n\n /* Set new location as soon as the document was fetched */\n push$\n .pipe(\n sample(ajax$)\n )\n .subscribe(({ url }) => {\n history.pushState({}, \"\", url.toString())\n })\n\n /* Parse and emit document */\n const dom = new DOMParser()\n ajax$\n .pipe(\n map(response => dom.parseFromString(response, \"text/html\"))\n )\n .subscribe(document$)\n\n /* Intercept instant loading */\n const instant$ = merge(push$, pop$)\n .pipe(\n sample(document$)\n )\n\n // TODO: this must be combined with search scroll restoration on mobile\n instant$.subscribe(({ url, offset }) => {\n if (url.hash && !offset) {\n setLocationHash(url.hash)\n } else {\n setViewportOffset(offset || { y: 0 })\n }\n })\n\n /* Replace document metadata */\n document$\n .pipe(\n skip(1) // Skip initial\n )\n .subscribe(({ title, head }) => {\n document.title = title\n\n /* Replace meta tags */\n for (const selector of [\n `link[rel=\"canonical\"]`,\n `meta[name=\"author\"]`,\n `meta[name=\"description\"]`\n ]) {\n const next = getElement(selector, head)\n const prev = getElement(selector, document.head)\n if (\n typeof next !== \"undefined\" &&\n typeof prev !== \"undefined\"\n ) {\n replaceElement(prev, next)\n }\n }\n\n /* Finished, dispatch document switch event */\n document.dispatchEvent(new CustomEvent(\"DOMContentSwitch\"))\n })\n\n /* Debounce update of viewport offset */\n viewport$\n .pipe(\n debounceTime(250),\n distinctUntilKeyChanged(\"offset\")\n )\n .subscribe(({ offset }) => {\n history.replaceState(offset, \"\")\n })\n\n /* Set viewport offset from history */\n merge(state$, pop$)\n .pipe(\n bufferCount(2, 1),\n filter(([prev, next]) => {\n return prev.url.pathname === next.url.pathname\n && !isAnchorLocation(next.url)\n }),\n map(([, state]) => state)\n )\n .subscribe(({ offset }) => {\n setViewportOffset(offset || { y: 0 })\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\nimport {\n filter,\n map,\n share,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n Key,\n getActiveElement,\n getElement,\n getElements,\n getToggle,\n isSusceptibleToKeyboard,\n setElementFocus,\n setElementSelection,\n setToggle,\n watchKeyboard\n} from \"browser\"\nimport { useComponent } from \"components\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Keyboard mode\n */\nexport type KeyboardMode =\n | \"global\" /* Global */\n | \"search\" /* Search is open */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Keyboard\n */\nexport interface Keyboard extends Key {\n mode: KeyboardMode /* Keyboard mode */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up keyboard\n *\n * This function will set up the keyboard handlers and ensure that keys are\n * correctly propagated. Currently there are two modes:\n *\n * - `global`: This mode is active when the search is closed. It is intended\n * to assign hotkeys to specific functions of the site. Currently the search,\n * previous and next page can be triggered.\n *\n * - `search`: This mode is active when the search is open. It maps certain\n * navigational keys to offer search results that can be entirely navigated\n * through keyboard input.\n *\n * The keyboard observable is returned and can be used to monitor the keyboard\n * in order toassign further hotkeys to custom functions.\n *\n * @return Keyboard observable\n */\nexport function setupKeyboard(): Observable {\n const keyboard$ = watchKeyboard()\n .pipe(\n map(key => ({\n mode: getToggle(\"search\") ? \"search\" : \"global\",\n ...key\n })),\n filter(({ mode }) => {\n if (mode === \"global\") {\n const active = getActiveElement()\n if (typeof active !== \"undefined\")\n return !isSusceptibleToKeyboard(active)\n }\n return true\n }),\n share()\n )\n\n /* Set up search keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"search\"),\n withLatestFrom(\n useComponent(\"search-query\"),\n useComponent(\"search-result\")\n )\n )\n .subscribe(([key, query, result]) => {\n const active = getActiveElement()\n switch (key.type) {\n\n /* Enter: prevent form submission */\n case \"Enter\":\n if (active === query)\n key.claim()\n break\n\n /* Escape or Tab: close search */\n case \"Escape\":\n case \"Tab\":\n setToggle(\"search\", false)\n setElementFocus(query, false)\n break\n\n /* Vertical arrows: select previous or next search result */\n case \"ArrowUp\":\n case \"ArrowDown\":\n if (typeof active === \"undefined\") {\n setElementFocus(query)\n } else {\n const els = [query, ...getElements(\n \":not(details) > [href], summary, details[open] [href]\",\n result\n )]\n const i = Math.max(0, (\n Math.max(0, els.indexOf(active)) + els.length + (\n key.type === \"ArrowUp\" ? -1 : +1\n )\n ) % els.length)\n setElementFocus(els[i])\n }\n\n /* Prevent scrolling of page */\n key.claim()\n break\n\n /* All other keys: hand to search query */\n default:\n if (query !== getActiveElement())\n setElementFocus(query)\n }\n })\n\n /* Set up global keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\"),\n withLatestFrom(useComponent(\"search-query\"))\n )\n .subscribe(([key, query]) => {\n switch (key.type) {\n\n /* Open search and select query */\n case \"f\":\n case \"s\":\n case \"/\":\n setElementFocus(query)\n setElementSelection(query)\n key.claim()\n break\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getElement(\"[href][rel=prev]\")\n if (typeof prev !== \"undefined\")\n prev.click()\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getElement(\"[href][rel=next]\")\n if (typeof next !== \"undefined\")\n next.click()\n break\n }\n })\n\n /* Return keyboard */\n return keyboard$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { filter, map, share } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Key\n */\nexport interface Key {\n type: string /* Key type */\n claim(): void /* Key claim */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether an element may receive keyboard input\n *\n * @param el - Element\n *\n * @return Test result\n */\nexport function isSusceptibleToKeyboard(el: HTMLElement): boolean {\n switch (el.tagName) {\n\n /* Form elements */\n case \"INPUT\":\n case \"SELECT\":\n case \"TEXTAREA\":\n return true\n\n /* Everything else */\n default:\n return el.isContentEditable\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch keyboard\n *\n * @return Keyboard observable\n */\nexport function watchKeyboard(): Observable {\n return fromEvent(window, \"keydown\")\n .pipe(\n filter(ev => !(ev.metaKey || ev.ctrlKey)),\n map(ev => ({\n type: ev.key,\n claim() {\n ev.preventDefault()\n ev.stopPropagation()\n }\n })),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set element text selection\n *\n * @param el - Element\n */\nexport function setElementSelection(\n el: HTMLElement\n): void {\n if (el instanceof HTMLInputElement)\n el.select()\n else\n throw new Error(\"Not implemented\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set search query placeholder\n *\n * @param el - Search query element\n * @param value - Placeholder\n */\nexport function setSearchQueryPlaceholder(\n el: HTMLInputElement, value: string\n): void {\n el.placeholder = value\n}\n\n/**\n * Reset search query placeholder\n *\n * @param el - Search query element\n */\nexport function resetSearchQueryPlaceholder(\n el: HTMLInputElement\n): void {\n el.placeholder = translate(\"search.placeholder\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n combineLatest,\n fromEvent,\n merge,\n pipe\n} from \"rxjs\"\nimport {\n delay,\n distinctUntilChanged,\n finalize,\n map,\n startWith,\n tap\n} from \"rxjs/operators\"\n\nimport { watchElementFocus } from \"browser\"\nimport { SearchTransformFn, defaultTransform } from \"integrations\"\n\nimport { SearchQuery } from \"../_\"\nimport {\n resetSearchQueryPlaceholder,\n setSearchQueryPlaceholder\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n transform?: SearchTransformFn /* Transformation function */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch search query\n *\n * Note that the focus event which triggers re-reading the current query value\n * is delayed by `1ms` so the input's empty state is allowed to propagate.\n *\n * @param el - Search query element\n * @param options - Options\n *\n * @return Search query observable\n */\nexport function watchSearchQuery(\n el: HTMLInputElement, { transform }: WatchOptions = {}\n): Observable {\n const fn = transform || defaultTransform\n\n /* Intercept keyboard events */\n const value$ = merge(\n fromEvent(el, \"keyup\"),\n fromEvent(el, \"focus\").pipe(delay(1))\n )\n .pipe(\n map(() => fn(el.value)),\n startWith(fn(el.value)),\n distinctUntilChanged()\n )\n\n /* Intercept focus events */\n const focus$ = watchElementFocus(el)\n\n /* Combine into single observable */\n return combineLatest([value$, focus$])\n .pipe(\n map(([value, focus]) => ({ value, focus }))\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply search query\n *\n * @param el - Search query element\n *\n * @return Operator function\n */\nexport function applySearchQuery(\n el: HTMLInputElement\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Hide placeholder when search is focused */\n tap(({ focus }) => {\n if (focus) {\n setSearchQueryPlaceholder(el, \"\")\n } else {\n resetSearchQueryPlaceholder(el)\n }\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n resetSearchQueryPlaceholder(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { OperatorFunction, pipe } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n map,\n switchMap\n} from \"rxjs/operators\"\n\nimport { WorkerHandler, setToggle } from \"browser\"\nimport {\n SearchMessage,\n SearchMessageType,\n SearchQueryMessage,\n SearchTransformFn\n} from \"integrations\"\n\nimport {\n applySearchQuery,\n watchSearchQuery\n} from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search query\n */\nexport interface SearchQuery {\n value: string /* Query value */\n focus: boolean /* Query focus */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n transform?: SearchTransformFn /* Transformation function */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search query from source observable\n *\n * @param handler - Worker handler\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountSearchQuery(\n { tx$ }: WorkerHandler, options: MountOptions = {}\n): OperatorFunction {\n return pipe(\n switchMap(el => {\n const query$ = watchSearchQuery(el, options)\n\n /* Subscribe worker to search query */\n query$\n .pipe(\n distinctUntilKeyChanged(\"value\"),\n map(({ value }): SearchQueryMessage => ({\n type: SearchMessageType.QUERY,\n data: value\n }))\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Toggle search on focus */\n query$\n .pipe(\n distinctUntilKeyChanged(\"focus\")\n )\n .subscribe(({ focus }) => {\n if (focus)\n setToggle(\"search\", focus)\n })\n\n /* Return search query */\n return query$\n .pipe(\n applySearchQuery(el)\n )\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { OperatorFunction, pipe } from \"rxjs\"\nimport {\n mapTo,\n startWith,\n switchMap,\n switchMapTo,\n tap\n} from \"rxjs/operators\"\n\nimport { setElementFocus } from \"browser\"\n\nimport { useComponent } from \"../../../_\"\nimport { watchSearchReset } from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search reset from source observable\n *\n * @return Operator function\n */\nexport function mountSearchReset(): OperatorFunction {\n return pipe(\n switchMap(el => watchSearchReset(el)\n .pipe(\n switchMapTo(useComponent(\"search-query\")),\n tap(setElementFocus),\n mapTo(undefined)\n )\n ),\n startWith(undefined)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { mapTo } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch search reset\n *\n * @param el - Search reset element\n *\n * @return Search reset observable\n */\nexport function watchSearchReset(\n el: HTMLElement\n): Observable {\n return fromEvent(el, \"click\")\n .pipe(\n mapTo(undefined)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set number of search results\n *\n * @param el - Search result metadata element\n * @param value - Number of results\n */\nexport function setSearchResultMeta(\n el: HTMLElement, value: number\n): void {\n switch (value) {\n\n /* No results */\n case 0:\n el.textContent = translate(\"search.result.none\")\n break\n\n /* One result */\n case 1:\n el.textContent = translate(\"search.result.one\")\n break\n\n /* Multiple result */\n default:\n el.textContent = translate(\"search.result.other\", value)\n }\n}\n\n/**\n * Reset number of search results\n *\n * @param el - Search result metadata element\n */\nexport function resetSearchResultMeta(\n el: HTMLElement\n): void {\n el.textContent = translate(\"search.result.placeholder\")\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Add an element to the search result list\n *\n * @param el - Search result list element\n * @param child - Search result element\n */\nexport function addToSearchResultList(\n el: HTMLElement, child: Element\n): void {\n el.appendChild(child)\n}\n\n/**\n * Reset search result list\n *\n * @param el - Search result list element\n */\nexport function resetSearchResultList(\n el: HTMLElement\n): void {\n el.innerHTML = \"\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n pipe\n} from \"rxjs\"\nimport {\n finalize,\n map,\n mapTo,\n observeOn,\n scan,\n switchMap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport { getElementOrThrow } from \"browser\"\nimport { SearchResult } from \"integrations/search\"\nimport { renderSearchResult } from \"templates\"\n\nimport { SearchQuery } from \"../../query\"\nimport {\n addToSearchResultList,\n resetSearchResultList,\n resetSearchResultMeta,\n setSearchResultMeta\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Apply options\n */\ninterface ApplyOptions {\n query$: Observable /* Search query observable */\n ready$: Observable /* Search ready observable */\n fetch$: Observable /* Result fetch observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Apply search results\n *\n * This function will perform a lazy rendering of the search results, depending\n * on the vertical offset of the search result container. When the scroll offset\n * reaches the bottom of the element, more results are fetched and rendered.\n *\n * @param el - Search result element\n * @param options - Options\n *\n * @return Operator function\n */\nexport function applySearchResult(\n el: HTMLElement, { query$, ready$, fetch$ }: ApplyOptions\n): MonoTypeOperatorFunction {\n const list = getElementOrThrow(\".md-search-result__list\", el)\n const meta = getElementOrThrow(\".md-search-result__meta\", el)\n return pipe(\n\n /* Apply search result metadata */\n withLatestFrom(query$, ready$),\n map(([result, query]) => {\n if (query.value) {\n setSearchResultMeta(meta, result.length)\n } else {\n resetSearchResultMeta(meta)\n }\n return result\n }),\n\n /* Apply search result list */\n switchMap(result => {\n const thresholds = [...result.map(([best]) => best.score), 0]\n return fetch$\n .pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n scan(index => {\n const container = el.parentElement!\n while (index < result.length) {\n addToSearchResultList(list, renderSearchResult(\n result[index++], thresholds[index]\n ))\n if (container.scrollHeight - container.offsetHeight > 16)\n break\n }\n return index\n }, 0),\n\n /* Re-map to search result */\n mapTo(result),\n\n /* Reset on complete or error */\n finalize(() => {\n resetSearchResultList(list)\n })\n )\n }\n )\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, pipe } from \"rxjs\"\nimport {\n distinctUntilChanged,\n filter,\n map,\n mapTo,\n startWith,\n switchMap\n} from \"rxjs/operators\"\n\nimport { WorkerHandler, watchElementOffset } from \"browser\"\nimport {\n SearchMessage,\n SearchResult,\n isSearchReadyMessage,\n isSearchResultMessage\n} from \"integrations\"\n\nimport { SearchQuery } from \"../../query\"\nimport { applySearchResult } from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n query$: Observable /* Search query observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search result from source observable\n *\n * @param handler - Worker handler\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountSearchResult(\n { rx$ }: WorkerHandler, { query$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => {\n const container = el.parentElement!\n\n /* Compute if search is ready */\n const ready$ = rx$\n .pipe(\n filter(isSearchReadyMessage),\n mapTo(true)\n )\n\n /* Compute whether there are more search results to fetch */\n const fetch$ = watchElementOffset(container)\n .pipe(\n map(({ y }) => {\n return y >= container.scrollHeight - container.offsetHeight - 16\n }),\n distinctUntilChanged(),\n filter(Boolean)\n )\n\n /* Apply search results */\n return rx$\n .pipe(\n filter(isSearchResultMessage),\n map(({ data }) => data),\n applySearchResult(el, { query$, ready$, fetch$ }),\n startWith([])\n )\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, of, pipe } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n map,\n switchMap\n} from \"rxjs/operators\"\n\nimport { Viewport, watchViewportAt } from \"browser\"\n\nimport { Header } from \"../../header\"\nimport { applyTabs } from \"../react\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Tabs\n */\nexport interface Tabs {\n hidden: boolean /* Whether the tabs are hidden */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n header$: Observable
    /* Header observable */\n viewport$: Observable /* Viewport observable */\n screen$: Observable /* Media screen observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount tabs from source observable\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountTabs(\n { header$, viewport$, screen$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => screen$\n .pipe(\n switchMap(screen => {\n\n /* [screen +]: Mount tabs above screen breakpoint */\n if (screen) {\n return watchViewportAt(el, { header$, viewport$ })\n .pipe(\n map(({ offset: { y } }) => ({ hidden: y >= 10 })),\n distinctUntilKeyChanged(\"hidden\"),\n applyTabs(el)\n )\n\n /* [screen -]: Unmount tabs below screen breakpoint */\n } else {\n return of({ hidden: true })\n }\n })\n )\n )\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n animationFrameScheduler,\n pipe\n} from \"rxjs\"\nimport { finalize, observeOn, tap } from \"rxjs/operators\"\n\nimport { Tabs } from \"../_\"\nimport {\n resetTabsHidden,\n setTabsHidden\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Apply tabs\n *\n * @param el - Tabs element\n *\n * @return Operator function\n */\nexport function applyTabs(\n el: HTMLElement\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n tap(({ hidden }) => {\n setTabsHidden(el, hidden)\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n resetTabsHidden(el)\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set tabs hidden\n *\n * @param el - Tabs element\n * @param value - Whether the element is hidden\n */\nexport function setTabsHidden(\n el: HTMLElement, value: boolean\n): void {\n el.setAttribute(\"data-md-state\", value ? \"hidden\" : \"\")\n}\n\n/**\n * Reset tabs hidden\n *\n * @param el - Tabs element\n */\nexport function resetTabsHidden(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set anchor blur\n *\n * @param el - Anchor element\n * @param value - Whether the anchor is blurred\n */\nexport function setAnchorBlur(\n el: HTMLElement, value: boolean\n): void {\n el.setAttribute(\"data-md-state\", value ? \"blur\" : \"\")\n}\n\n/**\n * Reset anchor blur\n *\n * @param el - Anchor element\n */\nexport function resetAnchorBlur(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set anchor active\n *\n * @param el - Anchor element\n * @param value - Whether the anchor is active\n */\nexport function setAnchorActive(\n el: HTMLElement, value: boolean\n): void {\n el.classList.toggle(\"md-nav__link--active\", value)\n}\n\n/**\n * Reset anchor active\n *\n * @param el - Anchor element\n */\nexport function resetAnchorActive(\n el: HTMLElement\n): void {\n el.classList.remove(\"md-nav__link--active\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n OperatorFunction,\n combineLatest,\n of,\n pipe\n} from \"rxjs\"\nimport { map, switchMap } from \"rxjs/operators\"\n\nimport { Viewport, getElements } from \"browser\"\n\nimport { Header } from \"../../header\"\nimport { Main } from \"../../main\"\nimport {\n Sidebar,\n applySidebar,\n watchSidebar\n} from \"../../shared\"\nimport {\n AnchorList,\n applyAnchorList,\n watchAnchorList\n} from \"../anchor\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Table of contents for [tablet -]\n */\ninterface TableOfContentsBelowTablet {} // tslint:disable-line\n\n/**\n * Table of contents for [tablet +]\n */\ninterface TableOfContentsAboveTablet {\n sidebar: Sidebar /* Sidebar */\n anchors: AnchorList /* Anchor list */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Table of contents\n */\nexport type TableOfContents =\n | TableOfContentsBelowTablet\n | TableOfContentsAboveTablet\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n viewport$: Observable /* Viewport observable */\n tablet$: Observable /* Tablet media observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount table of contents from source observable\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountTableOfContents(\n { header$, main$, viewport$, tablet$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => tablet$\n .pipe(\n switchMap(tablet => {\n\n /* [tablet +]: Mount table of contents in sidebar */\n if (tablet) {\n const els = getElements(\".md-nav__link\", el)\n\n /* Watch and apply sidebar */\n const sidebar$ = watchSidebar(el, { main$, viewport$ })\n .pipe(\n applySidebar(el, { header$ })\n )\n\n /* Watch and apply anchor list (scroll spy) */\n const anchors$ = watchAnchorList(els, { header$, viewport$ })\n .pipe(\n applyAnchorList(els)\n )\n\n /* Combine into single hot observable */\n return combineLatest([sidebar$, anchors$])\n .pipe(\n map(([sidebar, anchors]) => ({ sidebar, anchors }))\n )\n\n /* [tablet -]: Unmount table of contents */\n } else {\n return of({})\n }\n })\n )\n )\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n MonoTypeOperatorFunction,\n Observable,\n animationFrameScheduler,\n combineLatest,\n pipe\n} from \"rxjs\"\nimport {\n bufferCount,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n scan,\n startWith,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { Viewport, getElement, watchElementSize } from \"browser\"\n\nimport { Header } from \"../../../header\"\nimport { AnchorList } from \"../_\"\nimport {\n resetAnchorActive,\n resetAnchorBlur,\n setAnchorActive,\n setAnchorBlur\n} from \"../set\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n header$: Observable
    /* Header observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch anchor list\n *\n * This is effectively a scroll-spy implementation which will account for the\n * fixed header and automatically re-calculate anchor offsets when the viewport\n * is resized. The returned observable will only emit if the anchor list needs\n * to be repainted.\n *\n * This implementation tracks an anchor element's entire path starting from its\n * level up to the top-most anchor element, e.g. `[h3, h2, h1]`. Although the\n * Material theme currently doesn't make use of this information, it enables\n * the styling of the entire hierarchy through customization.\n *\n * Note that the current anchor is the last item of the `prev` anchor list.\n *\n * @param els - Anchor elements\n * @param options - Options\n *\n * @return Anchor list observable\n */\nexport function watchAnchorList(\n els: HTMLAnchorElement[], { header$, viewport$ }: WatchOptions\n): Observable {\n const table = new Map()\n for (const el of els) {\n const id = decodeURIComponent(el.hash.substring(1))\n const target = getElement(`[id=\"${id}\"]`)\n if (typeof target !== \"undefined\")\n table.set(el, target)\n }\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n map(header => 24 + header.height)\n )\n\n /* Compute partition of previous and next anchors */\n const partition$ = watchElementSize(document.body)\n .pipe(\n distinctUntilKeyChanged(\"height\"),\n\n /* Build index to map anchor paths to vertical offsets */\n map(() => {\n let path: HTMLAnchorElement[] = []\n return [...table].reduce((index, [anchor, target]) => {\n while (path.length) {\n const last = table.get(path[path.length - 1])!\n if (last.tagName >= target.tagName) {\n path.pop()\n } else {\n break\n }\n }\n\n /* If the current anchor is hidden, continue with its parent */\n let offset = target.offsetTop\n while (!offset && target.parentElement) {\n target = target.parentElement\n offset = target.offsetTop\n }\n\n /* Map reversed anchor path to vertical offset */\n return index.set(\n [...path = [...path, anchor]].reverse(),\n offset\n )\n }, new Map())\n }),\n\n /* Re-compute partition when viewport offset changes */\n switchMap(index => combineLatest([adjust$, viewport$])\n .pipe(\n scan(([prev, next], [adjust, { offset: { y } }]) => {\n\n /* Look forward */\n while (next.length) {\n const [, offset] = next[0]\n if (offset - adjust < y) {\n prev = [...prev, next.shift()!]\n } else {\n break\n }\n }\n\n /* Look backward */\n while (prev.length) {\n const [, offset] = prev[prev.length - 1]\n if (offset - adjust >= y) {\n next = [prev.pop()!, ...next]\n } else {\n break\n }\n }\n\n /* Return partition */\n return [prev, next]\n }, [[], [...index]]),\n distinctUntilChanged((a, b) => {\n return a[0] === b[0]\n && a[1] === b[1]\n })\n )\n )\n )\n\n /* Compute and return anchor list migrations */\n return partition$\n .pipe(\n map(([prev, next]) => ({\n prev: prev.map(([path]) => path),\n next: next.map(([path]) => path)\n })),\n\n /* Extract anchor list migrations */\n startWith({ prev: [], next: [] }),\n bufferCount(2, 1),\n map(([a, b]) => {\n\n /* Moving down */\n if (a.prev.length < b.prev.length) {\n return {\n prev: b.prev.slice(Math.max(0, a.prev.length - 1), b.prev.length),\n next: []\n }\n\n /* Moving up */\n } else {\n return {\n prev: b.prev.slice(-1),\n next: b.next.slice(0, b.next.length - a.next.length)\n }\n }\n })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Apply anchor list\n *\n * @param els - Anchor elements\n *\n * @return Operator function\n */\nexport function applyAnchorList(\n els: HTMLAnchorElement[]\n): MonoTypeOperatorFunction {\n return pipe(\n\n /* Defer repaint to next animation frame */\n observeOn(animationFrameScheduler),\n tap(({ prev, next }) => {\n\n /* Look forward */\n for (const [el] of next) {\n resetAnchorActive(el)\n resetAnchorBlur(el)\n }\n\n /* Look backward */\n prev.forEach(([el], index) => {\n setAnchorActive(el, index === prev.length - 1)\n setAnchorBlur(el, true)\n })\n }),\n\n /* Reset on complete or error */\n finalize(() => {\n for (const el of els) {\n resetAnchorActive(el)\n resetAnchorBlur(el)\n }\n })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, fromEvent, iif, merge } from \"rxjs\"\nimport { map, mapTo, shareReplay, switchMap } from \"rxjs/operators\"\n\nimport { getElements } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether the given device is an Apple device\n *\n * @return Test result\n */\nfunction isAppleDevice(): boolean {\n return /(iPad|iPhone|iPod)/.test(navigator.userAgent)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all elements with `data-md-scrollfix` attributes\n *\n * This is a year-old patch which ensures that overflow scrolling works at the\n * top and bottom of containers on iOS by ensuring a `1px` scroll offset upon\n * the start of a touch event.\n *\n * @see https://bit.ly/2SCtAOO - Original source\n *\n * @param options - Options\n */\nexport function patchScrollfix(\n { document$ }: PatchOptions\n): void {\n const els$ = document$\n .pipe(\n map(() => getElements(\"[data-md-scrollfix]\")),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* Remove marker attribute, so we'll only add the fix once */\n els$.subscribe(els => {\n for (const el of els)\n el.removeAttribute(\"data-md-scrollfix\")\n })\n\n /* Patch overflow scrolling on touch start */\n iif(isAppleDevice, els$, NEVER)\n .pipe(\n switchMap(els => merge(...els.map(el => (\n fromEvent(el, \"touchstart\")\n .pipe(\n mapTo(el)\n )\n ))))\n )\n .subscribe(el => {\n const top = el.scrollTop\n\n /* We're at the top of the container */\n if (top === 0) {\n el.scrollTop = 1\n\n /* We're at the bottom of the container */\n } else if (top + el.offsetHeight === el.scrollHeight) {\n el.scrollTop = top - 1\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable } from \"rxjs\"\nimport { catchError, filter, map, switchMap } from \"rxjs/operators\"\n\nimport { getElementOrThrow, getElements } from \"browser\"\nimport { renderSource } from \"templates\"\nimport { cache, hash } from \"utilities\"\n\nimport { fetchSourceFactsFromGitHub } from \"./github\"\nimport { fetchSourceFactsFromGitLab } from \"./gitlab\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Source facts\n */\nexport type SourceFacts = string[]\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch source facts\n *\n * @param url - Source repository URL\n *\n * @return Source facts observable\n */\nfunction fetchSourceFacts(\n url: string\n): Observable {\n const [type] = url.match(/(git(?:hub|lab))/i) || []\n switch (type.toLowerCase()) {\n\n /* GitHub repository */\n case \"github\":\n const [, user, repo] = url.match(/^.+github\\.com\\/([^\\/]+)\\/?([^\\/]+)?/i)!\n return fetchSourceFactsFromGitHub(user, repo)\n\n /* GitLab repository */\n case \"gitlab\":\n const [, base, slug] = url.match(/^.+?([^\\/]*gitlab[^\\/]+)\\/(.+?)\\/?$/i)!\n return fetchSourceFactsFromGitLab(base, slug)\n\n /* Everything else */\n default:\n return NEVER\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch elements containing repository information\n *\n * This function will retrieve the URL from the repository link and try to\n * query data from integrated source code platforms like GitHub or GitLab.\n *\n * @param options - Options\n */\nexport function patchSource(\n { document$ }: PatchOptions\n): void {\n document$\n .pipe(\n map(() => getElementOrThrow(\".md-source[href]\")),\n switchMap(({ href }) => (\n cache(`${hash(href)}`, () => fetchSourceFacts(href))\n )),\n filter(facts => facts.length > 0),\n catchError(() => NEVER)\n )\n .subscribe(facts => {\n for (const el of getElements(\".md-source__repository\")) {\n if (!el.hasAttribute(\"data-md-state\")) {\n el.setAttribute(\"data-md-state\", \"done\")\n el.appendChild(renderSource(facts))\n }\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Repo, User } from \"github-types\"\nimport { Observable, from } from \"rxjs\"\nimport {\n defaultIfEmpty,\n filter,\n map,\n share,\n switchMap\n} from \"rxjs/operators\"\n\nimport { round } from \"utilities\"\n\nimport { SourceFacts } from \"..\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitHub source facts\n *\n * @param user - GitHub user\n * @param repo - GitHub repository\n *\n * @return Source facts observable\n */\nexport function fetchSourceFactsFromGitHub(\n user: string, repo?: string\n): Observable {\n const url = typeof repo !== \"undefined\"\n ? `https://api.github.com/repos/${user}/${repo}`\n : `https://api.github.com/users/${user}`\n return from(fetch(url))\n .pipe(\n filter(res => res.status === 200),\n switchMap(res => res.json()),\n map(data => {\n\n /* GitHub repository */\n if (typeof repo !== \"undefined\") {\n const { stargazers_count, forks_count }: Repo = data\n return [\n `${round(stargazers_count!)} Stars`,\n `${round(forks_count!)} Forks`\n ]\n\n /* GitHub user/organization */\n } else {\n const { public_repos }: User = data\n return [\n `${round(public_repos!)} Repositories`\n ]\n }\n }),\n defaultIfEmpty([]),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ProjectSchema } from \"gitlab\"\nimport { Observable, from } from \"rxjs\"\nimport {\n defaultIfEmpty,\n filter,\n map,\n share,\n switchMap\n} from \"rxjs/operators\"\n\nimport { round } from \"utilities\"\n\nimport { SourceFacts } from \"..\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitLab source facts\n *\n * @param base - GitLab base\n * @param project - GitLab project\n *\n * @return Source facts observable\n */\nexport function fetchSourceFactsFromGitLab(\n base: string, project: string\n): Observable {\n const url = `https://${base}/api/v4/projects/${encodeURIComponent(project)}`\n return from(fetch(url))\n .pipe(\n filter(res => res.status === 200),\n switchMap(res => res.json()),\n map(({ star_count, forks_count }: ProjectSchema) => ([\n `${round(star_count)} Stars`,\n `${round(forks_count)} Forks`\n ])),\n defaultIfEmpty([]),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, defer, of } from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Cache the last value emitted by an observable in session storage\n *\n * If the key is not found in session storage, the factory is executed and the\n * latest value emitted will automatically be persisted to sessions storage.\n * Note that the values emitted by the returned observable must be serializable\n * as `JSON`, or data will be lost.\n *\n * @template T - Value type\n *\n * @param key - Cache key\n * @param factory - Observable factory\n *\n * @return Value observable\n */\nexport function cache(\n key: string, factory: () => Observable\n): Observable {\n return defer(() => {\n const data = sessionStorage.getItem(key)\n if (data) {\n return of(JSON.parse(data) as T)\n\n /* Retrieve value from observable factory and write to storage */\n } else {\n const value$ = factory()\n value$.subscribe(value => {\n try {\n sessionStorage.setItem(key, JSON.stringify(value))\n } catch (err) {\n /* Uncritical, just swallow */\n }\n })\n\n /* Return value */\n return value$\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n// DISCLAIMER: this file is still WIP. There're some refactoring opportunities\n// which must be tackled after we gathered some feedback on v5.\n// tslint:disable\n\nimport \"focus-visible\"\n\nimport {\n merge,\n combineLatest,\n animationFrameScheduler,\n fromEvent,\n from,\n defer,\n of,\n NEVER\n} from \"rxjs\"\nimport {\n delay,\n switchMap,\n tap,\n filter,\n withLatestFrom,\n observeOn,\n take,\n shareReplay,\n catchError,\n map,\n bufferCount,\n distinctUntilKeyChanged\n} from \"rxjs/operators\"\n\nimport {\n watchToggle,\n setToggle,\n getElements,\n watchMedia,\n watchDocument,\n watchLocation,\n watchLocationHash,\n watchViewport,\n isLocalLocation,\n setLocationHash,\n watchLocationBase,\n getElement\n} from \"browser\"\nimport {\n mountHeader,\n mountMain,\n mountNavigation,\n mountSearch,\n mountTableOfContents,\n mountTabs,\n useComponent,\n setupComponents,\n mountSearchQuery,\n mountSearchReset,\n mountSearchResult\n} from \"components\"\nimport {\n setupClipboard,\n setupDialog,\n setupKeyboard,\n setupInstantLoading,\n setupSearchWorker,\n SearchIndex,\n SearchIndexPipeline\n} from \"integrations\"\nimport {\n patchCodeBlocks,\n patchTables,\n patchDetails,\n patchScrollfix,\n patchSource,\n patchScripts\n} from \"patches\"\nimport { isConfig } from \"utilities\"\n\n/* ------------------------------------------------------------------------- */\n\n/* Denote that JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Test for iOS */\nif (navigator.userAgent.match(/(iPad|iPhone|iPod)/g))\n document.documentElement.classList.add(\"ios\")\n\n/**\n * Set scroll lock\n *\n * @param el - Scrollable element\n * @param value - Vertical offset\n */\nexport function setScrollLock(\n el: HTMLElement, value: number\n): void {\n el.setAttribute(\"data-md-state\", \"lock\")\n el.style.top = `-${value}px`\n}\n\n/**\n * Reset scroll lock\n *\n * @param el - Scrollable element\n */\nexport function resetScrollLock(\n el: HTMLElement\n): void {\n const value = -1 * parseInt(el.style.top, 10)\n el.removeAttribute(\"data-md-state\")\n el.style.top = \"\"\n if (value)\n window.scrollTo(0, value)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Initialize Material for MkDocs\n *\n * @param config - Configuration\n */\nexport function initialize(config: unknown) {\n if (!isConfig(config))\n throw new SyntaxError(`Invalid configuration: ${JSON.stringify(config)}`)\n\n /* Set up subjects */\n const document$ = watchDocument()\n const location$ = watchLocation()\n\n /* Set up user interface observables */\n const base$ = watchLocationBase(config.base, { location$ })\n const hash$ = watchLocationHash()\n const viewport$ = watchViewport()\n const tablet$ = watchMedia(\"(min-width: 960px)\")\n const screen$ = watchMedia(\"(min-width: 1220px)\")\n\n /* ----------------------------------------------------------------------- */\n\n /* Set up component bindings */\n setupComponents([\n \"announce\", /* Announcement bar */\n \"container\", /* Container */\n \"header\", /* Header */\n \"header-title\", /* Header title */\n \"main\", /* Main area */\n \"navigation\", /* Navigation */\n \"search\", /* Search */\n \"search-query\", /* Search input */\n \"search-reset\", /* Search reset */\n \"search-result\", /* Search results */\n \"skip\", /* Skip link */\n \"tabs\", /* Tabs */\n \"toc\" /* Table of contents */\n ], { document$ })\n\n const keyboard$ = setupKeyboard()\n\n // Hack: only make code blocks focusable on non-touch devices\n if (matchMedia(\"(hover)\").matches)\n patchCodeBlocks({ document$, viewport$ })\n patchDetails({ document$, hash$ })\n patchScripts({ document$ })\n patchSource({ document$ })\n patchTables({ document$ })\n\n /* Force 1px scroll offset to trigger overflow scrolling */\n patchScrollfix({ document$ })\n\n /* Set up clipboard and dialog */\n const dialog$ = setupDialog()\n const clipboard$ = setupClipboard({ document$, dialog$ })\n\n /* ----------------------------------------------------------------------- */\n\n /* Create header observable */\n const header$ = useComponent(\"header\")\n .pipe(\n mountHeader({ document$, viewport$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n const main$ = useComponent(\"main\")\n .pipe(\n mountMain({ header$, viewport$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* ----------------------------------------------------------------------- */\n\n const navigation$ = useComponent(\"navigation\")\n .pipe(\n mountNavigation({ header$, main$, viewport$, screen$ }),\n shareReplay({ bufferSize: 1, refCount: true }) // shareReplay because there might be late subscribers\n )\n\n const toc$ = useComponent(\"toc\")\n .pipe(\n mountTableOfContents({ header$, main$, viewport$, tablet$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n const tabs$ = useComponent(\"tabs\")\n .pipe(\n mountTabs({ header$, viewport$, screen$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* ----------------------------------------------------------------------- */\n\n /* Search worker - only if search is present */\n const worker$ = useComponent(\"search\")\n .pipe(\n switchMap(() => defer(() => {\n const index = config.search && config.search.index\n ? config.search.index\n : undefined\n\n /* Fetch index if it wasn't passed explicitly */\n const index$ = (\n typeof index !== \"undefined\"\n ? from(index)\n : base$\n .pipe(\n switchMap(base => fetch(`${base}/search/search_index.json`, {\n credentials: \"same-origin\"\n }).then(res => res.json())) // SearchIndex\n )\n )\n\n return of(setupSearchWorker(config.search.worker, {\n base$, index$\n }))\n }))\n )\n\n /* ----------------------------------------------------------------------- */\n\n /* Mount search query */\n const search$ = worker$\n .pipe(\n switchMap(worker => {\n const query$ = useComponent(\"search-query\")\n .pipe(\n mountSearchQuery(worker, { transform: config.search.transform }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* Mount search reset */\n const reset$ = useComponent(\"search-reset\")\n .pipe(\n mountSearchReset(),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* Mount search result */\n const result$ = useComponent(\"search-result\")\n .pipe(\n mountSearchResult(worker, { query$ }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n return useComponent(\"search\")\n .pipe(\n mountSearch(worker, { query$, reset$, result$ }),\n )\n }),\n catchError(() => {\n useComponent(\"search\")\n .subscribe(el => el.hidden = true) // TODO: Hack\n return NEVER\n }),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n\n /* ----------------------------------------------------------------------- */\n\n // // put into search...\n hash$\n .pipe(\n tap(() => setToggle(\"search\", false)),\n delay(125), // ensure that it runs after the body scroll reset...\n )\n .subscribe(hash => setLocationHash(`#${hash}`))\n\n // TODO: scroll restoration must be centralized\n combineLatest([\n watchToggle(\"search\"),\n tablet$,\n ])\n .pipe(\n withLatestFrom(viewport$),\n switchMap(([[toggle, tablet], { offset: { y }}]) => {\n const active = toggle && !tablet\n return document$\n .pipe(\n delay(active ? 400 : 100),\n observeOn(animationFrameScheduler),\n tap(({ body }) => active\n ? setScrollLock(body, y)\n : resetScrollLock(body)\n )\n )\n })\n )\n .subscribe()\n\n /* ----------------------------------------------------------------------- */\n\n /* Always close drawer on click */\n fromEvent(document.body, \"click\")\n .pipe(\n filter(ev => !(ev.metaKey || ev.ctrlKey)),\n filter(ev => {\n if (ev.target instanceof HTMLElement) {\n const el = ev.target.closest(\"a\") // TODO: abstract as link click?\n if (el && isLocalLocation(el)) {\n return true\n }\n }\n return false\n })\n )\n .subscribe(() => {\n setToggle(\"drawer\", false)\n })\n\n /* Enable instant loading, if not on file:// protocol */\n if (\n config.features.includes(\"navigation.instant\") &&\n location.protocol !== \"file:\"\n ) {\n const dom = new DOMParser()\n\n /* Fetch sitemap and extract URL whitelist */\n base$\n .pipe(\n switchMap(base => from(fetch(`${base}/sitemap.xml`)\n .then(res => res.text())\n .then(text => dom.parseFromString(text, \"text/xml\"))\n )),\n withLatestFrom(base$),\n map(([document, base]) => {\n const urls = getElements(\"loc\", document)\n .map(node => node.textContent!)\n\n // Hack: This is a temporary fix to normalize instant loading lookup\n // on localhost and Netlify previews. If this approach proves to be\n // suitable, we'll refactor URL whitelisting anyway. We take the two\n // shortest URLs and determine the common prefix to isolate the\n // domain. If there're no two domains, we just leave it as-is, as\n // there isn't anything to be loaded anway.\n if (urls.length > 1) {\n const [a, b] = urls.sort((a, b) => a.length - b.length)\n\n /* Determine common prefix */\n let index = 0\n if (a === b)\n index = a.length\n else\n while (a.charAt(index) === b.charAt(index))\n index++\n\n /* Replace common prefix (i.e. base) with effective base */\n for (let i = 0; i < urls.length; i++)\n urls[i] = urls[i].replace(a.slice(0, index), `${base}/`)\n }\n return urls\n })\n )\n .subscribe(urls => {\n setupInstantLoading(urls, { document$, location$, viewport$ })\n })\n }\n\n /* ----------------------------------------------------------------------- */\n\n // Make indeterminate toggles indeterminate to expand navigation on screen\n document$.subscribe(() => {\n const toggles = getElements(\"[data-md-state=indeterminate]\")\n for (const toggle of toggles) {\n toggle.dataset.mdState = \"\"\n toggle.indeterminate = true\n toggle.checked = false\n }\n })\n\n // Auto hide header - this is still experimental, so there might be some\n // opportunities for refactoring, but we'll address them when this feature\n // got some feedback from the community.\n if (config.features.includes(\"header.autohide\")) {\n viewport$\n .pipe(\n map(({ offset }) => offset.y),\n bufferCount(2, 1),\n map(([a, b]) => [a < b, b] as const),\n distinctUntilKeyChanged(0),\n switchMap(([direction, y0]) => viewport$\n .pipe(\n map(({ offset }) => offset.y),\n filter(y1 => y1 > 400),\n map(y1 => Math.abs(y0 - y1)),\n filter(y => y > 100),\n map(() => direction),\n take(1)\n )\n )\n )\n .subscribe(hide => {\n const header = getElement(\"[data-md-component=header]\")\n header?.setAttribute(\"data-md-state\", hide ? \"hidden\": \"shadow\")\n })\n }\n\n /* ----------------------------------------------------------------------- */\n\n const state = {\n\n /* Browser observables */\n document$,\n location$,\n viewport$,\n\n /* Component observables */\n header$,\n main$,\n navigation$,\n search$,\n tabs$,\n toc$,\n\n /* Integration observables */\n clipboard$,\n keyboard$,\n dialog$\n }\n\n /* Subscribe to all observables */\n merge(...Object.values(state))\n .subscribe()\n return state\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndex, SearchTransformFn } from \"integrations\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Feature flags\n */\nexport type Feature =\n | \"header.autohide\" /* Hide header */\n | \"navigation.tabs\" /* Tabs navigation */\n | \"navigation.instant\" /* Instant loading */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Configuration\n */\nexport interface Config {\n base: string /* Base URL */\n features: Feature[] /* Feature flags */\n search: {\n worker: string /* Worker URL */\n index?: Promise /* Promise resolving with index */\n transform?: SearchTransformFn /* Transformation function */\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Ensure that the given value is a valid configuration\n *\n * We could use `jsonschema` or any other schema validation framework, but that\n * would just add more bloat to the bundle, so we'll keep it plain and simple.\n *\n * @param config - Configuration\n *\n * @return Test result\n */\nexport function isConfig(config: any): config is Config {\n return typeof config === \"object\"\n && typeof config.base === \"string\"\n && typeof config.features === \"object\"\n && typeof config.search === \"object\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ReplaySubject, Subject, fromEvent } from \"rxjs\"\nimport { mapTo } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch document\n *\n * Documents must be implemented as subjects, so all downstream observables are\n * automatically updated when a new document is emitted. This enabled features\n * like instant loading.\n *\n * @return Document subject\n */\nexport function watchDocument(): Subject {\n const document$ = new ReplaySubject()\n fromEvent(document, \"DOMContentLoaded\")\n .pipe(\n mapTo(document)\n )\n .subscribe(document$)\n\n /* Return document */\n return document$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\nimport { map, shareReplay, take } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n location$: Observable /* Location observable */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location base\n *\n * @return Location base observable\n */\nexport function watchLocationBase(\n base: string, { location$ }: WatchOptions\n): Observable {\n return location$\n .pipe(\n take(1),\n map(({ href }) => new URL(base, href)\n .toString()\n .replace(/\\/$/, \"\")\n ),\n shareReplay({ bufferSize: 1, refCount: true })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, combineLatest } from \"rxjs\"\nimport { distinctUntilKeyChanged, map } from \"rxjs/operators\"\n\nimport { Viewport, getElements } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n document$: Observable /* Document observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all `code` elements\n *\n * This function will make overflowing code blocks focusable via keyboard, so\n * they can be scrolled without a mouse.\n *\n * @param options - Options\n */\nexport function patchCodeBlocks(\n { document$, viewport$ }: MountOptions\n): void {\n const els$ = document$\n .pipe(\n map(() => getElements(\"pre > code\"))\n )\n\n /* Observe viewport size only */\n const size$ = viewport$\n .pipe(\n distinctUntilKeyChanged(\"size\")\n )\n\n /* Make overflowing elements focusable */\n combineLatest([els$, size$])\n .subscribe(([els]) => {\n for (const el of els) {\n if (el.scrollWidth > el.clientWidth)\n el.setAttribute(\"tabindex\", \"0\")\n else\n el.removeAttribute(\"tabindex\")\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport {\n filter,\n map,\n switchMapTo,\n tap\n} from \"rxjs/operators\"\n\nimport {\n getElement,\n getElements,\n watchMedia\n} from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n hash$: Observable /* Location hash observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all `details` elements\n *\n * This function will ensure that all `details` tags are opened prior to\n * printing, so the whole content of the page is included, and on anchor jumps.\n *\n * @param options - Options\n */\nexport function patchDetails(\n { document$, hash$ }: PatchOptions\n): void {\n const els$ = document$\n .pipe(\n map(() => getElements(\"details\"))\n )\n\n /* Open all details before printing */\n merge(\n watchMedia(\"print\").pipe(filter(Boolean)), /* Webkit */\n fromEvent(window, \"beforeprint\") /* IE, FF */\n )\n .pipe(\n switchMapTo(els$)\n )\n .subscribe(els => {\n for (const el of els)\n el.setAttribute(\"open\", \"\")\n })\n\n /* Open parent details and fix anchor jump */\n hash$\n .pipe(\n map(id => getElement(`[id=\"${id}\"]`)!),\n filter(el => typeof el !== \"undefined\"),\n tap(el => {\n const details = el.closest(\"details\")\n if (details && !details.open)\n details.setAttribute(\"open\", \"\")\n })\n )\n .subscribe(el => el.scrollIntoView())\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { EMPTY, Observable, noop, of } from \"rxjs\"\nimport {\n concatMap,\n map,\n skip,\n switchMap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n createElement,\n getElements,\n replaceElement\n} from \"browser\"\nimport { useComponent } from \"components\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all `script` elements\n *\n * This function must be run after a document switch, which means the first\n * emission must be ignored.\n *\n * @param options - Options\n */\nexport function patchScripts(\n { document$ }: PatchOptions\n): void {\n const els$ = document$\n .pipe(\n skip(1),\n withLatestFrom(useComponent(\"container\")),\n map(([, el]) => getElements(\"script\", el))\n )\n\n /* Evaluate all scripts via replacement in order */\n els$\n .pipe(\n switchMap(els => of(...els)),\n concatMap(el => {\n const script = createElement(\"script\")\n if (el.src) {\n script.src = el.src\n replaceElement(el, script)\n\n /* Complete when script is loaded */\n return new Observable(observer => {\n script.onload = () => observer.complete()\n })\n\n /* Complete immediately */\n } else {\n script.textContent = el.textContent!\n replaceElement(el, script)\n return EMPTY\n }\n })\n )\n .subscribe(noop)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\nimport { map } from \"rxjs/operators\"\n\nimport {\n createElement,\n getElements,\n replaceElement\n} from \"browser\"\nimport { renderTable } from \"templates\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all `table` elements\n *\n * This function will re-render all tables by wrapping them to improve overflow\n * scrolling on smaller screen sizes.\n *\n * @param options - Options\n */\nexport function patchTables(\n { document$ }: MountOptions\n): void {\n const sentinel = createElement(\"table\")\n document$\n .pipe(\n map(() => getElements(\"table:not([class])\"))\n )\n .subscribe(els => {\n for (const el of els) {\n replaceElement(el, sentinel)\n replaceElement(sentinel, renderTable(el))\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a table inside a wrapper to improve scrolling on mobile\n *\n * @param table - Table element\n *\n * @return Element\n */\nexport function renderTable(\n table: HTMLTableElement\n) {\n return (\n
    \n
    \n {table}\n
    \n
    \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Subject, animationFrameScheduler, noop, of } from \"rxjs\"\nimport {\n delay,\n map,\n observeOn,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { createElement } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n duration?: number /* Display duration (default: 2s) */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up dialog\n *\n * @param options - Options\n *\n * @return Dialog observable\n */\nexport function setupDialog(\n { duration }: SetupOptions = {}\n): Subject {\n const dialog$ = new Subject()\n\n /* Create dialog */\n const dialog = createElement(\"div\") // TODO: improve scoping\n dialog.classList.add(\"md-dialog\", \"md-typeset\")\n\n /* Display dialog */\n dialog$\n .pipe(\n switchMap(text => of(document.body) // useComponent(\"container\")\n .pipe(\n map(container => container.appendChild(dialog)),\n observeOn(animationFrameScheduler),\n delay(1), // Strangley it doesnt work when we push things to the new animation frame...\n tap(el => {\n el.innerHTML = text\n el.setAttribute(\"data-md-state\", \"open\")\n }),\n delay(duration || 2000),\n tap(el => el.removeAttribute(\"data-md-state\")),\n delay(400),\n tap(el => {\n el.innerHTML = \"\"\n el.remove()\n })\n )\n )\n )\n .subscribe(noop)\n\n /* Return dialog */\n return dialog$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, of, pipe } from \"rxjs\"\nimport { map, switchMap } from \"rxjs/operators\"\n\nimport { Viewport } from \"browser\"\n\nimport { Header } from \"../header\"\nimport { Main } from \"../main\"\nimport {\n Sidebar,\n applySidebar,\n watchSidebar\n} from \"../shared\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Navigation for [screen -]\n */\ninterface NavigationBelowScreen {} // tslint:disable-line\n\n/**\n * Navigation for [screen +]\n */\ninterface NavigationAboveScreen {\n sidebar: Sidebar /* Sidebar */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Navigation\n */\nexport type Navigation =\n | NavigationBelowScreen\n | NavigationAboveScreen\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n viewport$: Observable /* Viewport observable */\n screen$: Observable /* Screen media observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount navigation from source observable\n *\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountNavigation(\n { header$, main$, viewport$, screen$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(el => screen$\n .pipe(\n switchMap(screen => {\n\n /* [screen +]: Mount navigation in sidebar */\n if (screen) {\n return watchSidebar(el, { main$, viewport$ })\n .pipe(\n applySidebar(el, { header$ }),\n map(sidebar => ({ sidebar }))\n )\n\n /* [screen -]: Mount navigation in drawer */\n } else {\n return of({})\n }\n })\n )\n )\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, OperatorFunction, combineLatest, pipe } from \"rxjs\"\nimport {\n filter,\n map,\n mapTo,\n sample,\n startWith,\n switchMap,\n take\n} from \"rxjs/operators\"\n\nimport { WorkerHandler } from \"browser\"\nimport {\n SearchMessage,\n SearchResult,\n isSearchQueryMessage,\n isSearchReadyMessage\n} from \"integrations/search\"\n\nimport { SearchQuery } from \"../query\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search status\n */\nexport type SearchStatus =\n | \"waiting\" /* Search waiting for initialization */\n | \"ready\" /* Search ready */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search\n */\nexport interface Search {\n status: SearchStatus /* Search status */\n query: SearchQuery /* Search query */\n result: SearchResult[] /* Search result list */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n query$: Observable /* Search query observable */\n reset$: Observable /* Search reset observable */\n result$: Observable /* Search result observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search from source observable\n *\n * @param handler - Worker handler\n * @param options - Options\n *\n * @return Operator function\n */\nexport function mountSearch(\n { rx$, tx$ }: WorkerHandler,\n { query$, reset$, result$ }: MountOptions\n): OperatorFunction {\n return pipe(\n switchMap(() => {\n\n /* Compute search status */\n const status$ = rx$\n .pipe(\n filter(isSearchReadyMessage),\n mapTo(\"ready\"),\n startWith(\"waiting\")\n ) as Observable\n\n /* Re-emit the latest query when search is ready */\n tx$\n .pipe(\n filter(isSearchQueryMessage),\n sample(status$),\n take(1)\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Combine into single observable */\n return combineLatest([status$, query$, result$, reset$])\n .pipe(\n map(([status, query, result]) => ({\n status,\n query,\n result\n }))\n )\n })\n )\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.ar.min.js b/public/assets/javascripts/lunr/min/lunr.ar.min.js new file mode 100644 index 0000000..248ddc5 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.ar.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ar=function(){this.pipeline.reset(),this.pipeline.add(e.ar.trimmer,e.ar.stopWordFilter,e.ar.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ar.stemmer))},e.ar.wordCharacters="ء-ٛٱـ",e.ar.trimmer=e.trimmerSupport.generateTrimmer(e.ar.wordCharacters),e.Pipeline.registerFunction(e.ar.trimmer,"trimmer-ar"),e.ar.stemmer=function(){var e=this;return e.result=!1,e.preRemoved=!1,e.sufRemoved=!1,e.pre={pre1:"ف ك ب و س ل ن ا ي ت",pre2:"ال لل",pre3:"بال وال فال تال كال ولل",pre4:"فبال كبال وبال وكال"},e.suf={suf1:"ه ك ت ن ا ي",suf2:"نك نه ها وك يا اه ون ين تن تم نا وا ان كم كن ني نن ما هم هن تك ته ات يه",suf3:"تين كهم نيه نهم ونه وها يهم ونا ونك وني وهم تكم تنا تها تني تهم كما كها ناه نكم هنا تان يها",suf4:"كموه ناها ونني ونهم تكما تموه تكاه كماه ناكم ناهم نيها وننا"},e.patterns=JSON.parse('{"pt43":[{"pt":[{"c":"ا","l":1}]},{"pt":[{"c":"ا,ت,ن,ي","l":0}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"و","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ي","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ا","l":2},{"c":"ل","l":3,"m":3}]},{"pt":[{"c":"م","l":0}]}],"pt53":[{"pt":[{"c":"ت","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":3},{"c":"ل","l":3,"m":4},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":3}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ن","l":4}]},{"pt":[{"c":"ت","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"م","l":0},{"c":"و","l":3}]},{"pt":[{"c":"ا","l":1},{"c":"و","l":3}]},{"pt":[{"c":"و","l":1},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"ا","l":2},{"c":"ن","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":1},{"c":"ا","l":3}]},{"pt":[{"c":"ي,ت,ا,ن","l":0},{"c":"ت","l":1}],"mPt":[{"c":"ف","l":0,"m":2},{"c":"ع","l":1,"m":3},{"c":"ا","l":2},{"c":"ل","l":3,"m":4}]},{"pt":[{"c":"ت,ي,ا,ن","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":2},{"c":"ي","l":3}]},{"pt":[{"c":"ا,ي,ت,ن","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ء","l":4}]}],"pt63":[{"pt":[{"c":"ا","l":0},{"c":"ت","l":2},{"c":"ا","l":4}]},{"pt":[{"c":"ا,ت,ن,ي","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"و","l":3}]},{"pt":[{"c":"م","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ي","l":1},{"c":"ي","l":3},{"c":"ا","l":4},{"c":"ء","l":5}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ا","l":4}]}],"pt54":[{"pt":[{"c":"ت","l":0}]},{"pt":[{"c":"ا,ي,ت,ن","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"م","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":2}]}],"pt64":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":1}]}],"pt73":[{"pt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ا","l":5}]}],"pt75":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":5}]}]}'),e.execArray=["cleanWord","removeDiacritics","cleanAlef","removeStopWords","normalizeHamzaAndAlef","removeStartWaw","removePre432","removeEndTaa","wordCheck"],e.stem=function(){var r=0;for(e.result=!1,e.preRemoved=!1,e.sufRemoved=!1;r=0)return!0},e.normalizeHamzaAndAlef=function(){return e.word=e.word.replace("ؤ","ء"),e.word=e.word.replace("ئ","ء"),e.word=e.word.replace(/([\u0627])\1+/gi,"ا"),!1},e.removeEndTaa=function(){return!(e.word.length>2)||(e.word=e.word.replace(/[\u0627]$/,""),e.word=e.word.replace("ة",""),!1)},e.removeStartWaw=function(){return e.word.length>3&&"و"==e.word[0]&&"و"==e.word[1]&&(e.word=e.word.slice(1)),!1},e.removePre432=function(){var r=e.word;if(e.word.length>=7){var t=new RegExp("^("+e.pre.pre4.split(" ").join("|")+")");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=6){var c=new RegExp("^("+e.pre.pre3.split(" ").join("|")+")");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=5){var l=new RegExp("^("+e.pre.pre2.split(" ").join("|")+")");e.word=e.word.replace(l,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.patternCheck=function(r){for(var t=0;t3){var t=new RegExp("^("+e.pre.pre1.split(" ").join("|")+")");e.word=e.word.replace(t,"")}return r!=e.word&&(e.preRemoved=!0),!1},e.removeSuf1=function(){var r=e.word;if(0==e.sufRemoved&&e.word.length>3){var t=new RegExp("("+e.suf.suf1.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.removeSuf432=function(){var r=e.word;if(e.word.length>=6){var t=new RegExp("("+e.suf.suf4.split(" ").join("|")+")$");e.word=e.word.replace(t,"")}if(e.word==r&&e.word.length>=5){var c=new RegExp("("+e.suf.suf3.split(" ").join("|")+")$");e.word=e.word.replace(c,"")}if(e.word==r&&e.word.length>=4){var l=new RegExp("("+e.suf.suf2.split(" ").join("|")+")$");e.word=e.word.replace(l,"")}return r!=e.word&&(e.sufRemoved=!0),!1},e.wordCheck=function(){for(var r=(e.word,[e.removeSuf432,e.removeSuf1,e.removePre1]),t=0,c=!1;e.word.length>=7&&!e.result&&t=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.de.min.js b/public/assets/javascripts/lunr/min/lunr.de.min.js new file mode 100644 index 0000000..f3b5c10 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.de.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `German` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.de=function(){this.pipeline.reset(),this.pipeline.add(e.de.trimmer,e.de.stopWordFilter,e.de.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.de.stemmer))},e.de.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.de.trimmer=e.trimmerSupport.generateTrimmer(e.de.wordCharacters),e.Pipeline.registerFunction(e.de.trimmer,"trimmer-de"),e.de.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!v.eq_s(1,e)||(v.ket=v.cursor,!v.in_grouping(p,97,252)))&&(v.slice_from(r),v.cursor=n,!0)}function i(){for(var r,n,i,s,t=v.cursor;;)if(r=v.cursor,v.bra=r,v.eq_s(1,"ß"))v.ket=v.cursor,v.slice_from("ss");else{if(r>=v.limit)break;v.cursor=r+1}for(v.cursor=t;;)for(n=v.cursor;;){if(i=v.cursor,v.in_grouping(p,97,252)){if(s=v.cursor,v.bra=s,e("u","U",i))break;if(v.cursor=s,e("y","Y",i))break}if(i>=v.limit)return void(v.cursor=n);v.cursor=i+1}}function s(){for(;!v.in_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}for(;!v.out_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}return!1}function t(){m=v.limit,l=m;var e=v.cursor+3;0<=e&&e<=v.limit&&(d=e,s()||(m=v.cursor,m=v.limit)return;v.cursor++}}}function c(){return m<=v.cursor}function u(){return l<=v.cursor}function a(){var e,r,n,i,s=v.limit-v.cursor;if(v.ket=v.cursor,(e=v.find_among_b(w,7))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:v.slice_del(),v.ket=v.cursor,v.eq_s_b(1,"s")&&(v.bra=v.cursor,v.eq_s_b(3,"nis")&&v.slice_del());break;case 3:v.in_grouping_b(g,98,116)&&v.slice_del()}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(f,4))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:if(v.in_grouping_b(k,98,116)){var t=v.cursor-3;v.limit_backward<=t&&t<=v.limit&&(v.cursor=t,v.slice_del())}}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(_,8))&&(v.bra=v.cursor,u()))switch(e){case 1:v.slice_del(),v.ket=v.cursor,v.eq_s_b(2,"ig")&&(v.bra=v.cursor,r=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-r,u()&&v.slice_del()));break;case 2:n=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-n,v.slice_del());break;case 3:if(v.slice_del(),v.ket=v.cursor,i=v.limit-v.cursor,!v.eq_s_b(2,"er")&&(v.cursor=v.limit-i,!v.eq_s_b(2,"en")))break;v.bra=v.cursor,c()&&v.slice_del();break;case 4:v.slice_del(),v.ket=v.cursor,e=v.find_among_b(b,2),e&&(v.bra=v.cursor,u()&&1==e&&v.slice_del())}}var d,l,m,h=[new r("",-1,6),new r("U",0,2),new r("Y",0,1),new r("ä",0,3),new r("ö",0,4),new r("ü",0,5)],w=[new r("e",-1,2),new r("em",-1,1),new r("en",-1,2),new r("ern",-1,1),new r("er",-1,1),new r("s",-1,3),new r("es",5,2)],f=[new r("en",-1,1),new r("er",-1,1),new r("st",-1,2),new r("est",2,1)],b=[new r("ig",-1,1),new r("lich",-1,1)],_=[new r("end",-1,1),new r("ig",-1,2),new r("ung",-1,1),new r("lich",-1,3),new r("isch",-1,2),new r("ik",-1,2),new r("heit",-1,3),new r("keit",-1,4)],p=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8],g=[117,30,5],k=[117,30,4],v=new n;this.setCurrent=function(e){v.setCurrent(e)},this.getCurrent=function(){return v.getCurrent()},this.stem=function(){var e=v.cursor;return i(),v.cursor=e,t(),v.limit_backward=e,v.cursor=v.limit,a(),v.cursor=v.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.de.stemmer,"stemmer-de"),e.de.stopWordFilter=e.generateStopWordFilter("aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über".split(" ")),e.Pipeline.registerFunction(e.de.stopWordFilter,"stopWordFilter-de")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.du.min.js b/public/assets/javascripts/lunr/min/lunr.du.min.js new file mode 100644 index 0000000..49a0f3f --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.du.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Dutch` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");console.warn('[Lunr Languages] Please use the "nl" instead of the "du". The "nl" code is the standard code for Dutch language, and "du" will be removed in the next major versions.'),e.du=function(){this.pipeline.reset(),this.pipeline.add(e.du.trimmer,e.du.stopWordFilter,e.du.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.du.stemmer))},e.du.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.du.trimmer=e.trimmerSupport.generateTrimmer(e.du.wordCharacters),e.Pipeline.registerFunction(e.du.trimmer,"trimmer-du"),e.du.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e,r,i,o=C.cursor;;){if(C.bra=C.cursor,e=C.find_among(b,11))switch(C.ket=C.cursor,e){case 1:C.slice_from("a");continue;case 2:C.slice_from("e");continue;case 3:C.slice_from("i");continue;case 4:C.slice_from("o");continue;case 5:C.slice_from("u");continue;case 6:if(C.cursor>=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(r=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=r);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=r;else if(n(r))break}else if(n(r))break}function n(e){return C.cursor=e,e>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,f=_,t()||(_=C.cursor,_<3&&(_=3),t()||(f=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var e;;)if(C.bra=C.cursor,e=C.find_among(p,3))switch(C.ket=C.cursor,e){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return f<=C.cursor}function a(){var e=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-e,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var e;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.slice_del(),w=!0,a())))}function m(){var e;u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.eq_s_b(3,"gem")||(C.cursor=C.limit-e,C.slice_del(),a())))}function d(){var e,r,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,e=C.find_among_b(h,5))switch(C.bra=C.cursor,e){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(z,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(r=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-r,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,e=C.find_among_b(k,6))switch(C.bra=C.cursor,e){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(j,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var f,_,w,b=[new r("",-1,6),new r("á",0,1),new r("ä",0,1),new r("é",0,2),new r("ë",0,2),new r("í",0,3),new r("ï",0,3),new r("ó",0,4),new r("ö",0,4),new r("ú",0,5),new r("ü",0,5)],p=[new r("",-1,3),new r("I",0,2),new r("Y",0,1)],g=[new r("dd",-1,-1),new r("kk",-1,-1),new r("tt",-1,-1)],h=[new r("ene",-1,2),new r("se",-1,3),new r("en",-1,2),new r("heden",2,1),new r("s",-1,3)],k=[new r("end",-1,1),new r("ig",-1,2),new r("ing",-1,1),new r("lijk",-1,3),new r("baar",-1,4),new r("bar",-1,5)],v=[new r("aa",-1,-1),new r("ee",-1,-1),new r("oo",-1,-1),new r("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(e){C.setCurrent(e)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var r=C.cursor;return e(),C.cursor=r,o(),C.limit_backward=r,C.cursor=C.limit,d(),C.cursor=C.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.du.stemmer,"stemmer-du"),e.du.stopWordFilter=e.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),e.Pipeline.registerFunction(e.du.stopWordFilter,"stopWordFilter-du")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.es.min.js b/public/assets/javascripts/lunr/min/lunr.es.min.js new file mode 100644 index 0000000..2989d34 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.es.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Spanish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,s){"function"==typeof define&&define.amd?define(s):"object"==typeof exports?module.exports=s():s()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.es=function(){this.pipeline.reset(),this.pipeline.add(e.es.trimmer,e.es.stopWordFilter,e.es.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.es.stemmer))},e.es.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.es.trimmer=e.trimmerSupport.generateTrimmer(e.es.wordCharacters),e.Pipeline.registerFunction(e.es.trimmer,"trimmer-es"),e.es.stemmer=function(){var s=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,n=new function(){function e(){if(A.out_grouping(x,97,252)){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}return!0}function n(){if(A.in_grouping(x,97,252)){var s=A.cursor;if(e()){if(A.cursor=s,!A.in_grouping(x,97,252))return!0;for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!0;A.cursor++}}return!1}return!0}function i(){var s,r=A.cursor;if(n()){if(A.cursor=r,!A.out_grouping(x,97,252))return;if(s=A.cursor,e()){if(A.cursor=s,!A.in_grouping(x,97,252)||A.cursor>=A.limit)return;A.cursor++}}g=A.cursor}function a(){for(;!A.in_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}for(;!A.out_grouping(x,97,252);){if(A.cursor>=A.limit)return!1;A.cursor++}return!0}function t(){var e=A.cursor;g=A.limit,p=g,v=g,i(),A.cursor=e,a()&&(p=A.cursor,a()&&(v=A.cursor))}function o(){for(var e;;){if(A.bra=A.cursor,e=A.find_among(k,6))switch(A.ket=A.cursor,e){case 1:A.slice_from("a");continue;case 2:A.slice_from("e");continue;case 3:A.slice_from("i");continue;case 4:A.slice_from("o");continue;case 5:A.slice_from("u");continue;case 6:if(A.cursor>=A.limit)break;A.cursor++;continue}break}}function u(){return g<=A.cursor}function w(){return p<=A.cursor}function c(){return v<=A.cursor}function m(){var e;if(A.ket=A.cursor,A.find_among_b(y,13)&&(A.bra=A.cursor,(e=A.find_among_b(q,11))&&u()))switch(e){case 1:A.bra=A.cursor,A.slice_from("iendo");break;case 2:A.bra=A.cursor,A.slice_from("ando");break;case 3:A.bra=A.cursor,A.slice_from("ar");break;case 4:A.bra=A.cursor,A.slice_from("er");break;case 5:A.bra=A.cursor,A.slice_from("ir");break;case 6:A.slice_del();break;case 7:A.eq_s_b(1,"u")&&A.slice_del()}}function l(e,s){if(!c())return!0;A.slice_del(),A.ket=A.cursor;var r=A.find_among_b(e,s);return r&&(A.bra=A.cursor,1==r&&c()&&A.slice_del()),!1}function d(e){return!c()||(A.slice_del(),A.ket=A.cursor,A.eq_s_b(2,e)&&(A.bra=A.cursor,c()&&A.slice_del()),!1)}function b(){var e;if(A.ket=A.cursor,e=A.find_among_b(S,46)){switch(A.bra=A.cursor,e){case 1:if(!c())return!1;A.slice_del();break;case 2:if(d("ic"))return!1;break;case 3:if(!c())return!1;A.slice_from("log");break;case 4:if(!c())return!1;A.slice_from("u");break;case 5:if(!c())return!1;A.slice_from("ente");break;case 6:if(!w())return!1;A.slice_del(),A.ket=A.cursor,e=A.find_among_b(C,4),e&&(A.bra=A.cursor,c()&&(A.slice_del(),1==e&&(A.ket=A.cursor,A.eq_s_b(2,"at")&&(A.bra=A.cursor,c()&&A.slice_del()))));break;case 7:if(l(P,3))return!1;break;case 8:if(l(F,3))return!1;break;case 9:if(d("at"))return!1}return!0}return!1}function f(){var e,s;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(W,12),A.limit_backward=s,e)){if(A.bra=A.cursor,1==e){if(!A.eq_s_b(1,"u"))return!1;A.slice_del()}return!0}return!1}function _(){var e,s,r,n;if(A.cursor>=g&&(s=A.limit_backward,A.limit_backward=g,A.ket=A.cursor,e=A.find_among_b(L,96),A.limit_backward=s,e))switch(A.bra=A.cursor,e){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"u")?(n=A.limit-A.cursor,A.eq_s_b(1,"g")?A.cursor=A.limit-n:A.cursor=A.limit-r):A.cursor=A.limit-r,A.bra=A.cursor;case 2:A.slice_del()}}function h(){var e,s;if(A.ket=A.cursor,e=A.find_among_b(z,8))switch(A.bra=A.cursor,e){case 1:u()&&A.slice_del();break;case 2:u()&&(A.slice_del(),A.ket=A.cursor,A.eq_s_b(1,"u")&&(A.bra=A.cursor,s=A.limit-A.cursor,A.eq_s_b(1,"g")&&(A.cursor=A.limit-s,u()&&A.slice_del())))}}var v,p,g,k=[new s("",-1,6),new s("á",0,1),new s("é",0,2),new s("í",0,3),new s("ó",0,4),new s("ú",0,5)],y=[new s("la",-1,-1),new s("sela",0,-1),new s("le",-1,-1),new s("me",-1,-1),new s("se",-1,-1),new s("lo",-1,-1),new s("selo",5,-1),new s("las",-1,-1),new s("selas",7,-1),new s("les",-1,-1),new s("los",-1,-1),new s("selos",10,-1),new s("nos",-1,-1)],q=[new s("ando",-1,6),new s("iendo",-1,6),new s("yendo",-1,7),new s("ándo",-1,2),new s("iéndo",-1,1),new s("ar",-1,6),new s("er",-1,6),new s("ir",-1,6),new s("ár",-1,3),new s("ér",-1,4),new s("ír",-1,5)],C=[new s("ic",-1,-1),new s("ad",-1,-1),new s("os",-1,-1),new s("iv",-1,1)],P=[new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,1)],F=[new s("ic",-1,1),new s("abil",-1,1),new s("iv",-1,1)],S=[new s("ica",-1,1),new s("ancia",-1,2),new s("encia",-1,5),new s("adora",-1,2),new s("osa",-1,1),new s("ista",-1,1),new s("iva",-1,9),new s("anza",-1,1),new s("logía",-1,3),new s("idad",-1,8),new s("able",-1,1),new s("ible",-1,1),new s("ante",-1,2),new s("mente",-1,7),new s("amente",13,6),new s("ación",-1,2),new s("ución",-1,4),new s("ico",-1,1),new s("ismo",-1,1),new s("oso",-1,1),new s("amiento",-1,1),new s("imiento",-1,1),new s("ivo",-1,9),new s("ador",-1,2),new s("icas",-1,1),new s("ancias",-1,2),new s("encias",-1,5),new s("adoras",-1,2),new s("osas",-1,1),new s("istas",-1,1),new s("ivas",-1,9),new s("anzas",-1,1),new s("logías",-1,3),new s("idades",-1,8),new s("ables",-1,1),new s("ibles",-1,1),new s("aciones",-1,2),new s("uciones",-1,4),new s("adores",-1,2),new s("antes",-1,2),new s("icos",-1,1),new s("ismos",-1,1),new s("osos",-1,1),new s("amientos",-1,1),new s("imientos",-1,1),new s("ivos",-1,9)],W=[new s("ya",-1,1),new s("ye",-1,1),new s("yan",-1,1),new s("yen",-1,1),new s("yeron",-1,1),new s("yendo",-1,1),new s("yo",-1,1),new s("yas",-1,1),new s("yes",-1,1),new s("yais",-1,1),new s("yamos",-1,1),new s("yó",-1,1)],L=[new s("aba",-1,2),new s("ada",-1,2),new s("ida",-1,2),new s("ara",-1,2),new s("iera",-1,2),new s("ía",-1,2),new s("aría",5,2),new s("ería",5,2),new s("iría",5,2),new s("ad",-1,2),new s("ed",-1,2),new s("id",-1,2),new s("ase",-1,2),new s("iese",-1,2),new s("aste",-1,2),new s("iste",-1,2),new s("an",-1,2),new s("aban",16,2),new s("aran",16,2),new s("ieran",16,2),new s("ían",16,2),new s("arían",20,2),new s("erían",20,2),new s("irían",20,2),new s("en",-1,1),new s("asen",24,2),new s("iesen",24,2),new s("aron",-1,2),new s("ieron",-1,2),new s("arán",-1,2),new s("erán",-1,2),new s("irán",-1,2),new s("ado",-1,2),new s("ido",-1,2),new s("ando",-1,2),new s("iendo",-1,2),new s("ar",-1,2),new s("er",-1,2),new s("ir",-1,2),new s("as",-1,2),new s("abas",39,2),new s("adas",39,2),new s("idas",39,2),new s("aras",39,2),new s("ieras",39,2),new s("ías",39,2),new s("arías",45,2),new s("erías",45,2),new s("irías",45,2),new s("es",-1,1),new s("ases",49,2),new s("ieses",49,2),new s("abais",-1,2),new s("arais",-1,2),new s("ierais",-1,2),new s("íais",-1,2),new s("aríais",55,2),new s("eríais",55,2),new s("iríais",55,2),new s("aseis",-1,2),new s("ieseis",-1,2),new s("asteis",-1,2),new s("isteis",-1,2),new s("áis",-1,2),new s("éis",-1,1),new s("aréis",64,2),new s("eréis",64,2),new s("iréis",64,2),new s("ados",-1,2),new s("idos",-1,2),new s("amos",-1,2),new s("ábamos",70,2),new s("áramos",70,2),new s("iéramos",70,2),new s("íamos",70,2),new s("aríamos",74,2),new s("eríamos",74,2),new s("iríamos",74,2),new s("emos",-1,1),new s("aremos",78,2),new s("eremos",78,2),new s("iremos",78,2),new s("ásemos",78,2),new s("iésemos",78,2),new s("imos",-1,2),new s("arás",-1,2),new s("erás",-1,2),new s("irás",-1,2),new s("ís",-1,2),new s("ará",-1,2),new s("erá",-1,2),new s("irá",-1,2),new s("aré",-1,2),new s("eré",-1,2),new s("iré",-1,2),new s("ió",-1,2)],z=[new s("a",-1,1),new s("e",-1,2),new s("o",-1,1),new s("os",-1,1),new s("á",-1,1),new s("é",-1,2),new s("í",-1,1),new s("ó",-1,1)],x=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,4,10],A=new r;this.setCurrent=function(e){A.setCurrent(e)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return t(),A.limit_backward=e,A.cursor=A.limit,m(),A.cursor=A.limit,b()||(A.cursor=A.limit,f()||(A.cursor=A.limit,_())),A.cursor=A.limit,h(),A.cursor=A.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.es.stemmer,"stemmer-es"),e.es.stopWordFilter=e.generateStopWordFilter("a al algo algunas algunos ante antes como con contra cual cuando de del desde donde durante e el ella ellas ellos en entre era erais eran eras eres es esa esas ese eso esos esta estaba estabais estaban estabas estad estada estadas estado estados estamos estando estar estaremos estará estarán estarás estaré estaréis estaría estaríais estaríamos estarían estarías estas este estemos esto estos estoy estuve estuviera estuvierais estuvieran estuvieras estuvieron estuviese estuvieseis estuviesen estuvieses estuvimos estuviste estuvisteis estuviéramos estuviésemos estuvo está estábamos estáis están estás esté estéis estén estés fue fuera fuerais fueran fueras fueron fuese fueseis fuesen fueses fui fuimos fuiste fuisteis fuéramos fuésemos ha habida habidas habido habidos habiendo habremos habrá habrán habrás habré habréis habría habríais habríamos habrían habrías habéis había habíais habíamos habían habías han has hasta hay haya hayamos hayan hayas hayáis he hemos hube hubiera hubierais hubieran hubieras hubieron hubiese hubieseis hubiesen hubieses hubimos hubiste hubisteis hubiéramos hubiésemos hubo la las le les lo los me mi mis mucho muchos muy más mí mía mías mío míos nada ni no nos nosotras nosotros nuestra nuestras nuestro nuestros o os otra otras otro otros para pero poco por porque que quien quienes qué se sea seamos sean seas seremos será serán serás seré seréis sería seríais seríamos serían serías seáis sido siendo sin sobre sois somos son soy su sus suya suyas suyo suyos sí también tanto te tendremos tendrá tendrán tendrás tendré tendréis tendría tendríais tendríamos tendrían tendrías tened tenemos tenga tengamos tengan tengas tengo tengáis tenida tenidas tenido tenidos teniendo tenéis tenía teníais teníamos tenían tenías ti tiene tienen tienes todo todos tu tus tuve tuviera tuvierais tuvieran tuvieras tuvieron tuviese tuvieseis tuviesen tuvieses tuvimos tuviste tuvisteis tuviéramos tuviésemos tuvo tuya tuyas tuyo tuyos tú un una uno unos vosotras vosotros vuestra vuestras vuestro vuestros y ya yo él éramos".split(" ")),e.Pipeline.registerFunction(e.es.stopWordFilter,"stopWordFilter-es")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.fi.min.js b/public/assets/javascripts/lunr/min/lunr.fi.min.js new file mode 100644 index 0000000..29f5dfc --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.fi.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Finnish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(i,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e():e()(i.lunr)}(this,function(){return function(i){if(void 0===i)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===i.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");i.fi=function(){this.pipeline.reset(),this.pipeline.add(i.fi.trimmer,i.fi.stopWordFilter,i.fi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(i.fi.stemmer))},i.fi.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",i.fi.trimmer=i.trimmerSupport.generateTrimmer(i.fi.wordCharacters),i.Pipeline.registerFunction(i.fi.trimmer,"trimmer-fi"),i.fi.stemmer=function(){var e=i.stemmerSupport.Among,r=i.stemmerSupport.SnowballProgram,n=new function(){function i(){f=A.limit,d=f,n()||(f=A.cursor,n()||(d=A.cursor))}function n(){for(var i;;){if(i=A.cursor,A.in_grouping(W,97,246))break;if(A.cursor=i,i>=A.limit)return!0;A.cursor++}for(A.cursor=i;!A.out_grouping(W,97,246);){if(A.cursor>=A.limit)return!0;A.cursor++}return!1}function t(){return d<=A.cursor}function s(){var i,e;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(h,10)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.in_grouping_b(x,97,246))return;break;case 2:if(!t())return}A.slice_del()}else A.limit_backward=e}function o(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(v,9))switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:r=A.limit-A.cursor,A.eq_s_b(1,"k")||(A.cursor=A.limit-r,A.slice_del());break;case 2:A.slice_del(),A.ket=A.cursor,A.eq_s_b(3,"kse")&&(A.bra=A.cursor,A.slice_from("ksi"));break;case 3:A.slice_del();break;case 4:A.find_among_b(p,6)&&A.slice_del();break;case 5:A.find_among_b(g,6)&&A.slice_del();break;case 6:A.find_among_b(j,2)&&A.slice_del()}else A.limit_backward=e}function l(){return A.find_among_b(q,7)}function a(){return A.eq_s_b(1,"i")&&A.in_grouping_b(L,97,246)}function u(){var i,e,r;if(A.cursor>=f)if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,i=A.find_among_b(C,30)){switch(A.bra=A.cursor,A.limit_backward=e,i){case 1:if(!A.eq_s_b(1,"a"))return;break;case 2:case 9:if(!A.eq_s_b(1,"e"))return;break;case 3:if(!A.eq_s_b(1,"i"))return;break;case 4:if(!A.eq_s_b(1,"o"))return;break;case 5:if(!A.eq_s_b(1,"ä"))return;break;case 6:if(!A.eq_s_b(1,"ö"))return;break;case 7:if(r=A.limit-A.cursor,!l()&&(A.cursor=A.limit-r,!A.eq_s_b(2,"ie"))){A.cursor=A.limit-r;break}if(A.cursor=A.limit-r,A.cursor<=A.limit_backward){A.cursor=A.limit-r;break}A.cursor--,A.bra=A.cursor;break;case 8:if(!A.in_grouping_b(W,97,246)||!A.out_grouping_b(W,97,246))return}A.slice_del(),k=!0}else A.limit_backward=e}function c(){var i,e,r;if(A.cursor>=d)if(e=A.limit_backward,A.limit_backward=d,A.ket=A.cursor,i=A.find_among_b(P,14)){if(A.bra=A.cursor,A.limit_backward=e,1==i){if(r=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-r}A.slice_del()}else A.limit_backward=e}function m(){var i;A.cursor>=f&&(i=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.find_among_b(F,2)?(A.bra=A.cursor,A.limit_backward=i,A.slice_del()):A.limit_backward=i)}function w(){var i,e,r,n,t,s;if(A.cursor>=f){if(e=A.limit_backward,A.limit_backward=f,A.ket=A.cursor,A.eq_s_b(1,"t")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.in_grouping_b(W,97,246)&&(A.cursor=A.limit-r,A.slice_del(),A.limit_backward=e,n=A.limit-A.cursor,A.cursor>=d&&(A.cursor=d,t=A.limit_backward,A.limit_backward=A.cursor,A.cursor=A.limit-n,A.ket=A.cursor,i=A.find_among_b(S,2))))){if(A.bra=A.cursor,A.limit_backward=t,1==i){if(s=A.limit-A.cursor,A.eq_s_b(2,"po"))return;A.cursor=A.limit-s}return void A.slice_del()}A.limit_backward=e}}function _(){var i,e,r,n;if(A.cursor>=f){for(i=A.limit_backward,A.limit_backward=f,e=A.limit-A.cursor,l()&&(A.cursor=A.limit-e,A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.in_grouping_b(y,97,228)&&(A.bra=A.cursor,A.out_grouping_b(W,97,246)&&A.slice_del()),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"j")&&(A.bra=A.cursor,r=A.limit-A.cursor,A.eq_s_b(1,"o")?A.slice_del():(A.cursor=A.limit-r,A.eq_s_b(1,"u")&&A.slice_del())),A.cursor=A.limit-e,A.ket=A.cursor,A.eq_s_b(1,"o")&&(A.bra=A.cursor,A.eq_s_b(1,"j")&&A.slice_del()),A.cursor=A.limit-e,A.limit_backward=i;;){if(n=A.limit-A.cursor,A.out_grouping_b(W,97,246)){A.cursor=A.limit-n;break}if(A.cursor=A.limit-n,A.cursor<=A.limit_backward)return;A.cursor--}A.ket=A.cursor,A.cursor>A.limit_backward&&(A.cursor--,A.bra=A.cursor,b=A.slice_to(),A.eq_v_b(b)&&A.slice_del())}}var k,b,d,f,h=[new e("pa",-1,1),new e("sti",-1,2),new e("kaan",-1,1),new e("han",-1,1),new e("kin",-1,1),new e("hän",-1,1),new e("kään",-1,1),new e("ko",-1,1),new e("pä",-1,1),new e("kö",-1,1)],p=[new e("lla",-1,-1),new e("na",-1,-1),new e("ssa",-1,-1),new e("ta",-1,-1),new e("lta",3,-1),new e("sta",3,-1)],g=[new e("llä",-1,-1),new e("nä",-1,-1),new e("ssä",-1,-1),new e("tä",-1,-1),new e("ltä",3,-1),new e("stä",3,-1)],j=[new e("lle",-1,-1),new e("ine",-1,-1)],v=[new e("nsa",-1,3),new e("mme",-1,3),new e("nne",-1,3),new e("ni",-1,2),new e("si",-1,1),new e("an",-1,4),new e("en",-1,6),new e("än",-1,5),new e("nsä",-1,3)],q=[new e("aa",-1,-1),new e("ee",-1,-1),new e("ii",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1),new e("ää",-1,-1),new e("öö",-1,-1)],C=[new e("a",-1,8),new e("lla",0,-1),new e("na",0,-1),new e("ssa",0,-1),new e("ta",0,-1),new e("lta",4,-1),new e("sta",4,-1),new e("tta",4,9),new e("lle",-1,-1),new e("ine",-1,-1),new e("ksi",-1,-1),new e("n",-1,7),new e("han",11,1),new e("den",11,-1,a),new e("seen",11,-1,l),new e("hen",11,2),new e("tten",11,-1,a),new e("hin",11,3),new e("siin",11,-1,a),new e("hon",11,4),new e("hän",11,5),new e("hön",11,6),new e("ä",-1,8),new e("llä",22,-1),new e("nä",22,-1),new e("ssä",22,-1),new e("tä",22,-1),new e("ltä",26,-1),new e("stä",26,-1),new e("ttä",26,9)],P=[new e("eja",-1,-1),new e("mma",-1,1),new e("imma",1,-1),new e("mpa",-1,1),new e("impa",3,-1),new e("mmi",-1,1),new e("immi",5,-1),new e("mpi",-1,1),new e("impi",7,-1),new e("ejä",-1,-1),new e("mmä",-1,1),new e("immä",10,-1),new e("mpä",-1,1),new e("impä",12,-1)],F=[new e("i",-1,-1),new e("j",-1,-1)],S=[new e("mma",-1,1),new e("imma",0,-1)],y=[17,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8],W=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],x=[17,97,24,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32],A=new r;this.setCurrent=function(i){A.setCurrent(i)},this.getCurrent=function(){return A.getCurrent()},this.stem=function(){var e=A.cursor;return i(),k=!1,A.limit_backward=e,A.cursor=A.limit,s(),A.cursor=A.limit,o(),A.cursor=A.limit,u(),A.cursor=A.limit,c(),A.cursor=A.limit,k?(m(),A.cursor=A.limit):(A.cursor=A.limit,w(),A.cursor=A.limit),_(),!0}};return function(i){return"function"==typeof i.update?i.update(function(i){return n.setCurrent(i),n.stem(),n.getCurrent()}):(n.setCurrent(i),n.stem(),n.getCurrent())}}(),i.Pipeline.registerFunction(i.fi.stemmer,"stemmer-fi"),i.fi.stopWordFilter=i.generateStopWordFilter("ei eivät emme en et ette että he heidän heidät heihin heille heillä heiltä heissä heistä heitä hän häneen hänelle hänellä häneltä hänen hänessä hänestä hänet häntä itse ja johon joiden joihin joiksi joilla joille joilta joina joissa joista joita joka joksi jolla jolle jolta jona jonka jos jossa josta jota jotka kanssa keiden keihin keiksi keille keillä keiltä keinä keissä keistä keitä keneen keneksi kenelle kenellä keneltä kenen kenenä kenessä kenestä kenet ketkä ketkä ketä koska kuin kuka kun me meidän meidät meihin meille meillä meiltä meissä meistä meitä mihin miksi mikä mille millä miltä minkä minkä minua minulla minulle minulta minun minussa minusta minut minuun minä minä missä mistä mitkä mitä mukaan mutta ne niiden niihin niiksi niille niillä niiltä niin niin niinä niissä niistä niitä noiden noihin noiksi noilla noille noilta noin noina noissa noista noita nuo nyt näiden näihin näiksi näille näillä näiltä näinä näissä näistä näitä nämä ole olemme olen olet olette oli olimme olin olisi olisimme olisin olisit olisitte olisivat olit olitte olivat olla olleet ollut on ovat poikki se sekä sen siihen siinä siitä siksi sille sillä sillä siltä sinua sinulla sinulle sinulta sinun sinussa sinusta sinut sinuun sinä sinä sitä tai te teidän teidät teihin teille teillä teiltä teissä teistä teitä tuo tuohon tuoksi tuolla tuolle tuolta tuon tuona tuossa tuosta tuota tähän täksi tälle tällä tältä tämä tämän tänä tässä tästä tätä vaan vai vaikka yli".split(" ")),i.Pipeline.registerFunction(i.fi.stopWordFilter,"stopWordFilter-fi")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.fr.min.js b/public/assets/javascripts/lunr/min/lunr.fr.min.js new file mode 100644 index 0000000..68cd009 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.fr.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `French` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.fr=function(){this.pipeline.reset(),this.pipeline.add(e.fr.trimmer,e.fr.stopWordFilter,e.fr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.fr.stemmer))},e.fr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.fr.trimmer=e.trimmerSupport.generateTrimmer(e.fr.wordCharacters),e.Pipeline.registerFunction(e.fr.trimmer,"trimmer-fr"),e.fr.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,s){return!(!W.eq_s(1,e)||(W.ket=W.cursor,!W.in_grouping(F,97,251)))&&(W.slice_from(r),W.cursor=s,!0)}function i(e,r,s){return!!W.eq_s(1,e)&&(W.ket=W.cursor,W.slice_from(r),W.cursor=s,!0)}function n(){for(var r,s;;){if(r=W.cursor,W.in_grouping(F,97,251)){if(W.bra=W.cursor,s=W.cursor,e("u","U",r))continue;if(W.cursor=s,e("i","I",r))continue;if(W.cursor=s,i("y","Y",r))continue}if(W.cursor=r,W.bra=r,!e("y","Y",r)){if(W.cursor=r,W.eq_s(1,"q")&&(W.bra=W.cursor,i("u","U",r)))continue;if(W.cursor=r,r>=W.limit)return;W.cursor++}}}function t(){for(;!W.in_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}for(;!W.out_grouping(F,97,251);){if(W.cursor>=W.limit)return!0;W.cursor++}return!1}function u(){var e=W.cursor;if(q=W.limit,g=q,p=q,W.in_grouping(F,97,251)&&W.in_grouping(F,97,251)&&W.cursor=W.limit){W.cursor=q;break}W.cursor++}while(!W.in_grouping(F,97,251))}q=W.cursor,W.cursor=e,t()||(g=W.cursor,t()||(p=W.cursor))}function o(){for(var e,r;;){if(r=W.cursor,W.bra=r,!(e=W.find_among(h,4)))break;switch(W.ket=W.cursor,e){case 1:W.slice_from("i");break;case 2:W.slice_from("u");break;case 3:W.slice_from("y");break;case 4:if(W.cursor>=W.limit)return;W.cursor++}}}function c(){return q<=W.cursor}function a(){return g<=W.cursor}function l(){return p<=W.cursor}function w(){var e,r;if(W.ket=W.cursor,e=W.find_among_b(C,43)){switch(W.bra=W.cursor,e){case 1:if(!l())return!1;W.slice_del();break;case 2:if(!l())return!1;W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")&&(W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU"));break;case 3:if(!l())return!1;W.slice_from("log");break;case 4:if(!l())return!1;W.slice_from("u");break;case 5:if(!l())return!1;W.slice_from("ent");break;case 6:if(!c())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(z,6))switch(W.bra=W.cursor,e){case 1:l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&W.slice_del()));break;case 2:l()?W.slice_del():a()&&W.slice_from("eux");break;case 3:l()&&W.slice_del();break;case 4:c()&&W.slice_from("i")}break;case 7:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,e=W.find_among_b(y,3))switch(W.bra=W.cursor,e){case 1:l()?W.slice_del():W.slice_from("abl");break;case 2:l()?W.slice_del():W.slice_from("iqU");break;case 3:l()&&W.slice_del()}break;case 8:if(!l())return!1;if(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"at")&&(W.bra=W.cursor,l()&&(W.slice_del(),W.ket=W.cursor,W.eq_s_b(2,"ic")))){W.bra=W.cursor,l()?W.slice_del():W.slice_from("iqU");break}break;case 9:W.slice_from("eau");break;case 10:if(!a())return!1;W.slice_from("al");break;case 11:if(l())W.slice_del();else{if(!a())return!1;W.slice_from("eux")}break;case 12:if(!a()||!W.out_grouping_b(F,97,251))return!1;W.slice_del();break;case 13:return c()&&W.slice_from("ant"),!1;case 14:return c()&&W.slice_from("ent"),!1;case 15:return r=W.limit-W.cursor,W.in_grouping_b(F,97,251)&&c()&&(W.cursor=W.limit-r,W.slice_del()),!1}return!0}return!1}function f(){var e,r;if(W.cursor=q){if(s=W.limit_backward,W.limit_backward=q,W.ket=W.cursor,e=W.find_among_b(P,7))switch(W.bra=W.cursor,e){case 1:if(l()){if(i=W.limit-W.cursor,!W.eq_s_b(1,"s")&&(W.cursor=W.limit-i,!W.eq_s_b(1,"t")))break;W.slice_del()}break;case 2:W.slice_from("i");break;case 3:W.slice_del();break;case 4:W.eq_s_b(2,"gu")&&W.slice_del()}W.limit_backward=s}}function b(){var e=W.limit-W.cursor;W.find_among_b(U,5)&&(W.cursor=W.limit-e,W.ket=W.cursor,W.cursor>W.limit_backward&&(W.cursor--,W.bra=W.cursor,W.slice_del()))}function d(){for(var e,r=1;W.out_grouping_b(F,97,251);)r--;if(r<=0){if(W.ket=W.cursor,e=W.limit-W.cursor,!W.eq_s_b(1,"é")&&(W.cursor=W.limit-e,!W.eq_s_b(1,"è")))return;W.bra=W.cursor,W.slice_from("e")}}function k(){if(!w()&&(W.cursor=W.limit,!f()&&(W.cursor=W.limit,!m())))return W.cursor=W.limit,void _();W.cursor=W.limit,W.ket=W.cursor,W.eq_s_b(1,"Y")?(W.bra=W.cursor,W.slice_from("i")):(W.cursor=W.limit,W.eq_s_b(1,"ç")&&(W.bra=W.cursor,W.slice_from("c")))}var p,g,q,v=[new r("col",-1,-1),new r("par",-1,-1),new r("tap",-1,-1)],h=[new r("",-1,4),new r("I",0,1),new r("U",0,2),new r("Y",0,3)],z=[new r("iqU",-1,3),new r("abl",-1,3),new r("Ièr",-1,4),new r("ièr",-1,4),new r("eus",-1,2),new r("iv",-1,1)],y=[new r("ic",-1,2),new r("abil",-1,1),new r("iv",-1,3)],C=[new r("iqUe",-1,1),new r("atrice",-1,2),new r("ance",-1,1),new r("ence",-1,5),new r("logie",-1,3),new r("able",-1,1),new r("isme",-1,1),new r("euse",-1,11),new r("iste",-1,1),new r("ive",-1,8),new r("if",-1,8),new r("usion",-1,4),new r("ation",-1,2),new r("ution",-1,4),new r("ateur",-1,2),new r("iqUes",-1,1),new r("atrices",-1,2),new r("ances",-1,1),new r("ences",-1,5),new r("logies",-1,3),new r("ables",-1,1),new r("ismes",-1,1),new r("euses",-1,11),new r("istes",-1,1),new r("ives",-1,8),new r("ifs",-1,8),new r("usions",-1,4),new r("ations",-1,2),new r("utions",-1,4),new r("ateurs",-1,2),new r("ments",-1,15),new r("ements",30,6),new r("issements",31,12),new r("ités",-1,7),new r("ment",-1,15),new r("ement",34,6),new r("issement",35,12),new r("amment",34,13),new r("emment",34,14),new r("aux",-1,10),new r("eaux",39,9),new r("eux",-1,1),new r("ité",-1,7)],x=[new r("ira",-1,1),new r("ie",-1,1),new r("isse",-1,1),new r("issante",-1,1),new r("i",-1,1),new r("irai",4,1),new r("ir",-1,1),new r("iras",-1,1),new r("ies",-1,1),new r("îmes",-1,1),new r("isses",-1,1),new r("issantes",-1,1),new r("îtes",-1,1),new r("is",-1,1),new r("irais",13,1),new r("issais",13,1),new r("irions",-1,1),new r("issions",-1,1),new r("irons",-1,1),new r("issons",-1,1),new r("issants",-1,1),new r("it",-1,1),new r("irait",21,1),new r("issait",21,1),new r("issant",-1,1),new r("iraIent",-1,1),new r("issaIent",-1,1),new r("irent",-1,1),new r("issent",-1,1),new r("iront",-1,1),new r("ît",-1,1),new r("iriez",-1,1),new r("issiez",-1,1),new r("irez",-1,1),new r("issez",-1,1)],I=[new r("a",-1,3),new r("era",0,2),new r("asse",-1,3),new r("ante",-1,3),new r("ée",-1,2),new r("ai",-1,3),new r("erai",5,2),new r("er",-1,2),new r("as",-1,3),new r("eras",8,2),new r("âmes",-1,3),new r("asses",-1,3),new r("antes",-1,3),new r("âtes",-1,3),new r("ées",-1,2),new r("ais",-1,3),new r("erais",15,2),new r("ions",-1,1),new r("erions",17,2),new r("assions",17,3),new r("erons",-1,2),new r("ants",-1,3),new r("és",-1,2),new r("ait",-1,3),new r("erait",23,2),new r("ant",-1,3),new r("aIent",-1,3),new r("eraIent",26,2),new r("èrent",-1,2),new r("assent",-1,3),new r("eront",-1,2),new r("ât",-1,3),new r("ez",-1,2),new r("iez",32,2),new r("eriez",33,2),new r("assiez",33,3),new r("erez",32,2),new r("é",-1,2)],P=[new r("e",-1,3),new r("Ière",0,2),new r("ière",0,2),new r("ion",-1,1),new r("Ier",-1,2),new r("ier",-1,2),new r("ë",-1,4)],U=[new r("ell",-1,-1),new r("eill",-1,-1),new r("enn",-1,-1),new r("onn",-1,-1),new r("ett",-1,-1)],F=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,128,130,103,8,5],S=[1,65,20,0,0,0,0,0,0,0,0,0,0,0,0,0,128],W=new s;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){var e=W.cursor;return n(),W.cursor=e,u(),W.limit_backward=e,W.cursor=W.limit,k(),W.cursor=W.limit,b(),W.cursor=W.limit,d(),W.cursor=W.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.fr.stemmer,"stemmer-fr"),e.fr.stopWordFilter=e.generateStopWordFilter("ai aie aient aies ait as au aura aurai auraient aurais aurait auras aurez auriez aurions aurons auront aux avaient avais avait avec avez aviez avions avons ayant ayez ayons c ce ceci celà ces cet cette d dans de des du elle en es est et eu eue eues eurent eus eusse eussent eusses eussiez eussions eut eux eûmes eût eûtes furent fus fusse fussent fusses fussiez fussions fut fûmes fût fûtes ici il ils j je l la le les leur leurs lui m ma mais me mes moi mon même n ne nos notre nous on ont ou par pas pour qu que quel quelle quelles quels qui s sa sans se sera serai seraient serais serait seras serez seriez serions serons seront ses soi soient sois soit sommes son sont soyez soyons suis sur t ta te tes toi ton tu un une vos votre vous y à étaient étais était étant étiez étions été étée étées étés êtes".split(" ")),e.Pipeline.registerFunction(e.fr.stopWordFilter,"stopWordFilter-fr")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.hu.min.js b/public/assets/javascripts/lunr/min/lunr.hu.min.js new file mode 100644 index 0000000..ed9d909 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.hu.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Hungarian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hu=function(){this.pipeline.reset(),this.pipeline.add(e.hu.trimmer,e.hu.stopWordFilter,e.hu.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hu.stemmer))},e.hu.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.hu.trimmer=e.trimmerSupport.generateTrimmer(e.hu.wordCharacters),e.Pipeline.registerFunction(e.hu.trimmer,"trimmer-hu"),e.hu.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,n=L.cursor;if(d=L.limit,L.in_grouping(W,97,252))for(;;){if(e=L.cursor,L.out_grouping(W,97,252))return L.cursor=e,L.find_among(g,8)||(L.cursor=e,e=L.limit)return void(d=e);L.cursor++}if(L.cursor=n,L.out_grouping(W,97,252)){for(;!L.in_grouping(W,97,252);){if(L.cursor>=L.limit)return;L.cursor++}d=L.cursor}}function i(){return d<=L.cursor}function a(){var e;if(L.ket=L.cursor,(e=L.find_among_b(h,2))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e")}}function t(){var e=L.limit-L.cursor;return!!L.find_among_b(p,23)&&(L.cursor=L.limit-e,!0)}function s(){if(L.cursor>L.limit_backward){L.cursor--,L.ket=L.cursor;var e=L.cursor-1;L.limit_backward<=e&&e<=L.limit&&(L.cursor=e,L.bra=e,L.slice_del())}}function c(){var e;if(L.ket=L.cursor,(e=L.find_among_b(_,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function o(){L.ket=L.cursor,L.find_among_b(v,44)&&(L.bra=L.cursor,i()&&(L.slice_del(),a()))}function w(){var e;if(L.ket=L.cursor,(e=L.find_among_b(z,3))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("e");break;case 2:case 3:L.slice_from("a")}}function l(){var e;if(L.ket=L.cursor,(e=L.find_among_b(y,6))&&(L.bra=L.cursor,i()))switch(e){case 1:case 2:L.slice_del();break;case 3:L.slice_from("a");break;case 4:L.slice_from("e")}}function u(){var e;if(L.ket=L.cursor,(e=L.find_among_b(j,2))&&(L.bra=L.cursor,i())){if((1==e||2==e)&&!t())return;L.slice_del(),s()}}function m(){var e;if(L.ket=L.cursor,(e=L.find_among_b(C,7))&&(L.bra=L.cursor,i()))switch(e){case 1:L.slice_from("a");break;case 2:L.slice_from("e");break;case 3:case 4:case 5:case 6:case 7:L.slice_del()}}function k(){var e;if(L.ket=L.cursor,(e=L.find_among_b(P,12))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 9:L.slice_del();break;case 2:case 5:case 8:L.slice_from("e");break;case 3:case 6:L.slice_from("a")}}function f(){var e;if(L.ket=L.cursor,(e=L.find_among_b(F,31))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 7:case 8:case 9:case 12:case 13:case 16:case 17:case 18:L.slice_del();break;case 2:case 5:case 10:case 14:case 19:L.slice_from("a");break;case 3:case 6:case 11:case 15:case 20:L.slice_from("e")}}function b(){var e;if(L.ket=L.cursor,(e=L.find_among_b(S,42))&&(L.bra=L.cursor,i()))switch(e){case 1:case 4:case 5:case 6:case 9:case 10:case 11:case 14:case 15:case 16:case 17:case 20:case 21:case 24:case 25:case 26:case 29:L.slice_del();break;case 2:case 7:case 12:case 18:case 22:case 27:L.slice_from("a");break;case 3:case 8:case 13:case 19:case 23:case 28:L.slice_from("e")}}var d,g=[new n("cs",-1,-1),new n("dzs",-1,-1),new n("gy",-1,-1),new n("ly",-1,-1),new n("ny",-1,-1),new n("sz",-1,-1),new n("ty",-1,-1),new n("zs",-1,-1)],h=[new n("á",-1,1),new n("é",-1,2)],p=[new n("bb",-1,-1),new n("cc",-1,-1),new n("dd",-1,-1),new n("ff",-1,-1),new n("gg",-1,-1),new n("jj",-1,-1),new n("kk",-1,-1),new n("ll",-1,-1),new n("mm",-1,-1),new n("nn",-1,-1),new n("pp",-1,-1),new n("rr",-1,-1),new n("ccs",-1,-1),new n("ss",-1,-1),new n("zzs",-1,-1),new n("tt",-1,-1),new n("vv",-1,-1),new n("ggy",-1,-1),new n("lly",-1,-1),new n("nny",-1,-1),new n("tty",-1,-1),new n("ssz",-1,-1),new n("zz",-1,-1)],_=[new n("al",-1,1),new n("el",-1,2)],v=[new n("ba",-1,-1),new n("ra",-1,-1),new n("be",-1,-1),new n("re",-1,-1),new n("ig",-1,-1),new n("nak",-1,-1),new n("nek",-1,-1),new n("val",-1,-1),new n("vel",-1,-1),new n("ul",-1,-1),new n("nál",-1,-1),new n("nél",-1,-1),new n("ból",-1,-1),new n("ról",-1,-1),new n("tól",-1,-1),new n("bõl",-1,-1),new n("rõl",-1,-1),new n("tõl",-1,-1),new n("ül",-1,-1),new n("n",-1,-1),new n("an",19,-1),new n("ban",20,-1),new n("en",19,-1),new n("ben",22,-1),new n("képpen",22,-1),new n("on",19,-1),new n("ön",19,-1),new n("képp",-1,-1),new n("kor",-1,-1),new n("t",-1,-1),new n("at",29,-1),new n("et",29,-1),new n("ként",29,-1),new n("anként",32,-1),new n("enként",32,-1),new n("onként",32,-1),new n("ot",29,-1),new n("ért",29,-1),new n("öt",29,-1),new n("hez",-1,-1),new n("hoz",-1,-1),new n("höz",-1,-1),new n("vá",-1,-1),new n("vé",-1,-1)],z=[new n("án",-1,2),new n("én",-1,1),new n("ánként",-1,3)],y=[new n("stul",-1,2),new n("astul",0,1),new n("ástul",0,3),new n("stül",-1,2),new n("estül",3,1),new n("éstül",3,4)],j=[new n("á",-1,1),new n("é",-1,2)],C=[new n("k",-1,7),new n("ak",0,4),new n("ek",0,6),new n("ok",0,5),new n("ák",0,1),new n("ék",0,2),new n("ök",0,3)],P=[new n("éi",-1,7),new n("áéi",0,6),new n("ééi",0,5),new n("é",-1,9),new n("ké",3,4),new n("aké",4,1),new n("eké",4,1),new n("oké",4,1),new n("áké",4,3),new n("éké",4,2),new n("öké",4,1),new n("éé",3,8)],F=[new n("a",-1,18),new n("ja",0,17),new n("d",-1,16),new n("ad",2,13),new n("ed",2,13),new n("od",2,13),new n("ád",2,14),new n("éd",2,15),new n("öd",2,13),new n("e",-1,18),new n("je",9,17),new n("nk",-1,4),new n("unk",11,1),new n("ánk",11,2),new n("énk",11,3),new n("ünk",11,1),new n("uk",-1,8),new n("juk",16,7),new n("ájuk",17,5),new n("ük",-1,8),new n("jük",19,7),new n("éjük",20,6),new n("m",-1,12),new n("am",22,9),new n("em",22,9),new n("om",22,9),new n("ám",22,10),new n("ém",22,11),new n("o",-1,18),new n("á",-1,19),new n("é",-1,20)],S=[new n("id",-1,10),new n("aid",0,9),new n("jaid",1,6),new n("eid",0,9),new n("jeid",3,6),new n("áid",0,7),new n("éid",0,8),new n("i",-1,15),new n("ai",7,14),new n("jai",8,11),new n("ei",7,14),new n("jei",10,11),new n("ái",7,12),new n("éi",7,13),new n("itek",-1,24),new n("eitek",14,21),new n("jeitek",15,20),new n("éitek",14,23),new n("ik",-1,29),new n("aik",18,26),new n("jaik",19,25),new n("eik",18,26),new n("jeik",21,25),new n("áik",18,27),new n("éik",18,28),new n("ink",-1,20),new n("aink",25,17),new n("jaink",26,16),new n("eink",25,17),new n("jeink",28,16),new n("áink",25,18),new n("éink",25,19),new n("aitok",-1,21),new n("jaitok",32,20),new n("áitok",-1,22),new n("im",-1,5),new n("aim",35,4),new n("jaim",36,1),new n("eim",35,4),new n("jeim",38,1),new n("áim",35,2),new n("éim",35,3)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,17,52,14],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var n=L.cursor;return e(),L.limit_backward=n,L.cursor=L.limit,c(),L.cursor=L.limit,o(),L.cursor=L.limit,w(),L.cursor=L.limit,l(),L.cursor=L.limit,u(),L.cursor=L.limit,k(),L.cursor=L.limit,f(),L.cursor=L.limit,b(),L.cursor=L.limit,m(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.hu.stemmer,"stemmer-hu"),e.hu.stopWordFilter=e.generateStopWordFilter("a abban ahhoz ahogy ahol aki akik akkor alatt amely amelyek amelyekben amelyeket amelyet amelynek ami amikor amit amolyan amíg annak arra arról az azok azon azonban azt aztán azután azzal azért be belül benne bár cikk cikkek cikkeket csak de e ebben eddig egy egyes egyetlen egyik egyre egyéb egész ehhez ekkor el ellen elsõ elég elõ elõször elõtt emilyen ennek erre ez ezek ezen ezt ezzel ezért fel felé hanem hiszen hogy hogyan igen ill ill. illetve ilyen ilyenkor ismét ison itt jobban jó jól kell kellett keressünk keresztül ki kívül között közül legalább legyen lehet lehetett lenne lenni lesz lett maga magát majd majd meg mellett mely melyek mert mi mikor milyen minden mindenki mindent mindig mint mintha mit mivel miért most már más másik még míg nagy nagyobb nagyon ne nekem neki nem nincs néha néhány nélkül olyan ott pedig persze rá s saját sem semmi sok sokat sokkal szemben szerint szinte számára talán tehát teljes tovább továbbá több ugyanis utolsó után utána vagy vagyis vagyok valaki valami valamint való van vannak vele vissza viszont volna volt voltak voltam voltunk által általában át én éppen és így õ õk õket össze úgy új újabb újra".split(" ")),e.Pipeline.registerFunction(e.hu.stopWordFilter,"stopWordFilter-hu")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.it.min.js b/public/assets/javascripts/lunr/min/lunr.it.min.js new file mode 100644 index 0000000..344b6a3 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.it.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Italian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.it=function(){this.pipeline.reset(),this.pipeline.add(e.it.trimmer,e.it.stopWordFilter,e.it.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.it.stemmer))},e.it.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.it.trimmer=e.trimmerSupport.generateTrimmer(e.it.wordCharacters),e.Pipeline.registerFunction(e.it.trimmer,"trimmer-it"),e.it.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!x.eq_s(1,e)||(x.ket=x.cursor,!x.in_grouping(L,97,249)))&&(x.slice_from(r),x.cursor=n,!0)}function i(){for(var r,n,i,o,t=x.cursor;;){if(x.bra=x.cursor,r=x.find_among(h,7))switch(x.ket=x.cursor,r){case 1:x.slice_from("à");continue;case 2:x.slice_from("è");continue;case 3:x.slice_from("ì");continue;case 4:x.slice_from("ò");continue;case 5:x.slice_from("ù");continue;case 6:x.slice_from("qU");continue;case 7:if(x.cursor>=x.limit)break;x.cursor++;continue}break}for(x.cursor=t;;)for(n=x.cursor;;){if(i=x.cursor,x.in_grouping(L,97,249)){if(x.bra=x.cursor,o=x.cursor,e("u","U",i))break;if(x.cursor=o,e("i","I",i))break}if(x.cursor=i,x.cursor>=x.limit)return void(x.cursor=n);x.cursor++}}function o(e){if(x.cursor=e,!x.in_grouping(L,97,249))return!1;for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function t(){if(x.in_grouping(L,97,249)){var e=x.cursor;if(x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return o(e);x.cursor++}return!0}return o(e)}return!1}function s(){var e,r=x.cursor;if(!t()){if(x.cursor=r,!x.out_grouping(L,97,249))return;if(e=x.cursor,x.out_grouping(L,97,249)){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return x.cursor=e,void(x.in_grouping(L,97,249)&&x.cursor=x.limit)return;x.cursor++}k=x.cursor}function a(){for(;!x.in_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}for(;!x.out_grouping(L,97,249);){if(x.cursor>=x.limit)return!1;x.cursor++}return!0}function u(){var e=x.cursor;k=x.limit,p=k,g=k,s(),x.cursor=e,a()&&(p=x.cursor,a()&&(g=x.cursor))}function c(){for(var e;;){if(x.bra=x.cursor,!(e=x.find_among(q,3)))break;switch(x.ket=x.cursor,e){case 1:x.slice_from("i");break;case 2:x.slice_from("u");break;case 3:if(x.cursor>=x.limit)return;x.cursor++}}}function w(){return k<=x.cursor}function l(){return p<=x.cursor}function m(){return g<=x.cursor}function f(){var e;if(x.ket=x.cursor,x.find_among_b(C,37)&&(x.bra=x.cursor,(e=x.find_among_b(z,5))&&w()))switch(e){case 1:x.slice_del();break;case 2:x.slice_from("e")}}function v(){var e;if(x.ket=x.cursor,!(e=x.find_among_b(S,51)))return!1;switch(x.bra=x.cursor,e){case 1:if(!m())return!1;x.slice_del();break;case 2:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del());break;case 3:if(!m())return!1;x.slice_from("log");break;case 4:if(!m())return!1;x.slice_from("u");break;case 5:if(!m())return!1;x.slice_from("ente");break;case 6:if(!w())return!1;x.slice_del();break;case 7:if(!l())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(P,4),e&&(x.bra=x.cursor,m()&&(x.slice_del(),1==e&&(x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&x.slice_del()))));break;case 8:if(!m())return!1;x.slice_del(),x.ket=x.cursor,e=x.find_among_b(F,3),e&&(x.bra=x.cursor,1==e&&m()&&x.slice_del());break;case 9:if(!m())return!1;x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"at")&&(x.bra=x.cursor,m()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(2,"ic")&&(x.bra=x.cursor,m()&&x.slice_del())))}return!0}function b(){var e,r;x.cursor>=k&&(r=x.limit_backward,x.limit_backward=k,x.ket=x.cursor,e=x.find_among_b(W,87),e&&(x.bra=x.cursor,1==e&&x.slice_del()),x.limit_backward=r)}function d(){var e=x.limit-x.cursor;if(x.ket=x.cursor,x.in_grouping_b(y,97,242)&&(x.bra=x.cursor,w()&&(x.slice_del(),x.ket=x.cursor,x.eq_s_b(1,"i")&&(x.bra=x.cursor,w()))))return void x.slice_del();x.cursor=x.limit-e}function _(){d(),x.ket=x.cursor,x.eq_s_b(1,"h")&&(x.bra=x.cursor,x.in_grouping_b(U,99,103)&&w()&&x.slice_del())}var g,p,k,h=[new r("",-1,7),new r("qu",0,6),new r("á",0,1),new r("é",0,2),new r("í",0,3),new r("ó",0,4),new r("ú",0,5)],q=[new r("",-1,3),new r("I",0,1),new r("U",0,2)],C=[new r("la",-1,-1),new r("cela",0,-1),new r("gliela",0,-1),new r("mela",0,-1),new r("tela",0,-1),new r("vela",0,-1),new r("le",-1,-1),new r("cele",6,-1),new r("gliele",6,-1),new r("mele",6,-1),new r("tele",6,-1),new r("vele",6,-1),new r("ne",-1,-1),new r("cene",12,-1),new r("gliene",12,-1),new r("mene",12,-1),new r("sene",12,-1),new r("tene",12,-1),new r("vene",12,-1),new r("ci",-1,-1),new r("li",-1,-1),new r("celi",20,-1),new r("glieli",20,-1),new r("meli",20,-1),new r("teli",20,-1),new r("veli",20,-1),new r("gli",20,-1),new r("mi",-1,-1),new r("si",-1,-1),new r("ti",-1,-1),new r("vi",-1,-1),new r("lo",-1,-1),new r("celo",31,-1),new r("glielo",31,-1),new r("melo",31,-1),new r("telo",31,-1),new r("velo",31,-1)],z=[new r("ando",-1,1),new r("endo",-1,1),new r("ar",-1,2),new r("er",-1,2),new r("ir",-1,2)],P=[new r("ic",-1,-1),new r("abil",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],F=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],S=[new r("ica",-1,1),new r("logia",-1,3),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,9),new r("anza",-1,1),new r("enza",-1,5),new r("ice",-1,1),new r("atrice",7,1),new r("iche",-1,1),new r("logie",-1,3),new r("abile",-1,1),new r("ibile",-1,1),new r("usione",-1,4),new r("azione",-1,2),new r("uzione",-1,4),new r("atore",-1,2),new r("ose",-1,1),new r("ante",-1,1),new r("mente",-1,1),new r("amente",19,7),new r("iste",-1,1),new r("ive",-1,9),new r("anze",-1,1),new r("enze",-1,5),new r("ici",-1,1),new r("atrici",25,1),new r("ichi",-1,1),new r("abili",-1,1),new r("ibili",-1,1),new r("ismi",-1,1),new r("usioni",-1,4),new r("azioni",-1,2),new r("uzioni",-1,4),new r("atori",-1,2),new r("osi",-1,1),new r("anti",-1,1),new r("amenti",-1,6),new r("imenti",-1,6),new r("isti",-1,1),new r("ivi",-1,9),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,6),new r("imento",-1,6),new r("ivo",-1,9),new r("ità",-1,8),new r("istà",-1,1),new r("istè",-1,1),new r("istì",-1,1)],W=[new r("isca",-1,1),new r("enda",-1,1),new r("ata",-1,1),new r("ita",-1,1),new r("uta",-1,1),new r("ava",-1,1),new r("eva",-1,1),new r("iva",-1,1),new r("erebbe",-1,1),new r("irebbe",-1,1),new r("isce",-1,1),new r("ende",-1,1),new r("are",-1,1),new r("ere",-1,1),new r("ire",-1,1),new r("asse",-1,1),new r("ate",-1,1),new r("avate",16,1),new r("evate",16,1),new r("ivate",16,1),new r("ete",-1,1),new r("erete",20,1),new r("irete",20,1),new r("ite",-1,1),new r("ereste",-1,1),new r("ireste",-1,1),new r("ute",-1,1),new r("erai",-1,1),new r("irai",-1,1),new r("isci",-1,1),new r("endi",-1,1),new r("erei",-1,1),new r("irei",-1,1),new r("assi",-1,1),new r("ati",-1,1),new r("iti",-1,1),new r("eresti",-1,1),new r("iresti",-1,1),new r("uti",-1,1),new r("avi",-1,1),new r("evi",-1,1),new r("ivi",-1,1),new r("isco",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("Yamo",-1,1),new r("iamo",-1,1),new r("avamo",-1,1),new r("evamo",-1,1),new r("ivamo",-1,1),new r("eremo",-1,1),new r("iremo",-1,1),new r("assimo",-1,1),new r("ammo",-1,1),new r("emmo",-1,1),new r("eremmo",54,1),new r("iremmo",54,1),new r("immo",-1,1),new r("ano",-1,1),new r("iscano",58,1),new r("avano",58,1),new r("evano",58,1),new r("ivano",58,1),new r("eranno",-1,1),new r("iranno",-1,1),new r("ono",-1,1),new r("iscono",65,1),new r("arono",65,1),new r("erono",65,1),new r("irono",65,1),new r("erebbero",-1,1),new r("irebbero",-1,1),new r("assero",-1,1),new r("essero",-1,1),new r("issero",-1,1),new r("ato",-1,1),new r("ito",-1,1),new r("uto",-1,1),new r("avo",-1,1),new r("evo",-1,1),new r("ivo",-1,1),new r("ar",-1,1),new r("ir",-1,1),new r("erà",-1,1),new r("irà",-1,1),new r("erò",-1,1),new r("irò",-1,1)],L=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2,1],y=[17,65,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,8,2],U=[17],x=new n;this.setCurrent=function(e){x.setCurrent(e)},this.getCurrent=function(){return x.getCurrent()},this.stem=function(){var e=x.cursor;return i(),x.cursor=e,u(),x.limit_backward=e,x.cursor=x.limit,f(),x.cursor=x.limit,v()||(x.cursor=x.limit,b()),x.cursor=x.limit,_(),x.cursor=x.limit_backward,c(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.it.stemmer,"stemmer-it"),e.it.stopWordFilter=e.generateStopWordFilter("a abbia abbiamo abbiano abbiate ad agl agli ai al all alla alle allo anche avemmo avendo avesse avessero avessi avessimo aveste avesti avete aveva avevamo avevano avevate avevi avevo avrai avranno avrebbe avrebbero avrei avremmo avremo avreste avresti avrete avrà avrò avuta avute avuti avuto c che chi ci coi col come con contro cui da dagl dagli dai dal dall dalla dalle dallo degl degli dei del dell della delle dello di dov dove e ebbe ebbero ebbi ed era erano eravamo eravate eri ero essendo faccia facciamo facciano facciate faccio facemmo facendo facesse facessero facessi facessimo faceste facesti faceva facevamo facevano facevate facevi facevo fai fanno farai faranno farebbe farebbero farei faremmo faremo fareste faresti farete farà farò fece fecero feci fosse fossero fossi fossimo foste fosti fu fui fummo furono gli ha hai hanno ho i il in io l la le lei li lo loro lui ma mi mia mie miei mio ne negl negli nei nel nell nella nelle nello noi non nostra nostre nostri nostro o per perché più quale quanta quante quanti quanto quella quelle quelli quello questa queste questi questo sarai saranno sarebbe sarebbero sarei saremmo saremo sareste saresti sarete sarà sarò se sei si sia siamo siano siate siete sono sta stai stando stanno starai staranno starebbe starebbero starei staremmo staremo stareste staresti starete starà starò stava stavamo stavano stavate stavi stavo stemmo stesse stessero stessi stessimo steste stesti stette stettero stetti stia stiamo stiano stiate sto su sua sue sugl sugli sui sul sull sulla sulle sullo suo suoi ti tra tu tua tue tuo tuoi tutti tutto un una uno vi voi vostra vostre vostri vostro è".split(" ")),e.Pipeline.registerFunction(e.it.stopWordFilter,"stopWordFilter-it")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.ja.min.js b/public/assets/javascripts/lunr/min/lunr.ja.min.js new file mode 100644 index 0000000..5f254eb --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.ja.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(e=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=e);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=e;else if(n(e))break}else if(n(e))break}function n(r){return C.cursor=r,r>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,d=_,t()||(_=C.cursor,_<3&&(_=3),t()||(d=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var r;;)if(C.bra=C.cursor,r=C.find_among(p,3))switch(C.ket=C.cursor,r){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return d<=C.cursor}function a(){var r=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-r,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var r;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.slice_del(),w=!0,a())))}function m(){var r;u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.eq_s_b(3,"gem")||(C.cursor=C.limit-r,C.slice_del(),a())))}function f(){var r,e,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,r=C.find_among_b(h,5))switch(C.bra=C.cursor,r){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(j,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(e=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-e,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,r=C.find_among_b(k,6))switch(C.bra=C.cursor,r){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(z,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var d,_,w,b=[new e("",-1,6),new e("á",0,1),new e("ä",0,1),new e("é",0,2),new e("ë",0,2),new e("í",0,3),new e("ï",0,3),new e("ó",0,4),new e("ö",0,4),new e("ú",0,5),new e("ü",0,5)],p=[new e("",-1,3),new e("I",0,2),new e("Y",0,1)],g=[new e("dd",-1,-1),new e("kk",-1,-1),new e("tt",-1,-1)],h=[new e("ene",-1,2),new e("se",-1,3),new e("en",-1,2),new e("heden",2,1),new e("s",-1,3)],k=[new e("end",-1,1),new e("ig",-1,2),new e("ing",-1,1),new e("lijk",-1,3),new e("baar",-1,4),new e("bar",-1,5)],v=[new e("aa",-1,-1),new e("ee",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(r){C.setCurrent(r)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var e=C.cursor;return r(),C.cursor=e,o(),C.limit_backward=e,C.cursor=C.limit,f(),C.cursor=C.limit_backward,s(),!0}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.nl.stemmer,"stemmer-nl"),r.nl.stopWordFilter=r.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),r.Pipeline.registerFunction(r.nl.stopWordFilter,"stopWordFilter-nl")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.no.min.js b/public/assets/javascripts/lunr/min/lunr.no.min.js new file mode 100644 index 0000000..92bc7e4 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.no.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Norwegian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.pt.min.js b/public/assets/javascripts/lunr/min/lunr.pt.min.js new file mode 100644 index 0000000..6c16996 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.pt.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Portuguese` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.pt=function(){this.pipeline.reset(),this.pipeline.add(e.pt.trimmer,e.pt.stopWordFilter,e.pt.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.pt.stemmer))},e.pt.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.pt.trimmer=e.trimmerSupport.generateTrimmer(e.pt.wordCharacters),e.Pipeline.registerFunction(e.pt.trimmer,"trimmer-pt"),e.pt.stemmer=function(){var r=e.stemmerSupport.Among,s=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(k,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("a~");continue;case 2:z.slice_from("o~");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function n(){if(z.out_grouping(y,97,250)){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!0;z.cursor++}return!1}return!0}function i(){if(z.in_grouping(y,97,250))for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return g=z.cursor,!0}function o(){var e,r,s=z.cursor;if(z.in_grouping(y,97,250))if(e=z.cursor,n()){if(z.cursor=e,i())return}else g=z.cursor;if(z.cursor=s,z.out_grouping(y,97,250)){if(r=z.cursor,n()){if(z.cursor=r,!z.in_grouping(y,97,250)||z.cursor>=z.limit)return;z.cursor++}g=z.cursor}}function t(){for(;!z.in_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}for(;!z.out_grouping(y,97,250);){if(z.cursor>=z.limit)return!1;z.cursor++}return!0}function a(){var e=z.cursor;g=z.limit,b=g,h=g,o(),z.cursor=e,t()&&(b=z.cursor,t()&&(h=z.cursor))}function u(){for(var e;;){if(z.bra=z.cursor,e=z.find_among(q,3))switch(z.ket=z.cursor,e){case 1:z.slice_from("ã");continue;case 2:z.slice_from("õ");continue;case 3:if(z.cursor>=z.limit)break;z.cursor++;continue}break}}function w(){return g<=z.cursor}function m(){return b<=z.cursor}function c(){return h<=z.cursor}function l(){var e;if(z.ket=z.cursor,!(e=z.find_among_b(F,45)))return!1;switch(z.bra=z.cursor,e){case 1:if(!c())return!1;z.slice_del();break;case 2:if(!c())return!1;z.slice_from("log");break;case 3:if(!c())return!1;z.slice_from("u");break;case 4:if(!c())return!1;z.slice_from("ente");break;case 5:if(!m())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(j,4),e&&(z.bra=z.cursor,c()&&(z.slice_del(),1==e&&(z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del()))));break;case 6:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(C,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 7:if(!c())return!1;z.slice_del(),z.ket=z.cursor,e=z.find_among_b(P,3),e&&(z.bra=z.cursor,1==e&&c()&&z.slice_del());break;case 8:if(!c())return!1;z.slice_del(),z.ket=z.cursor,z.eq_s_b(2,"at")&&(z.bra=z.cursor,c()&&z.slice_del());break;case 9:if(!w()||!z.eq_s_b(1,"e"))return!1;z.slice_from("ir")}return!0}function f(){var e,r;if(z.cursor>=g){if(r=z.limit_backward,z.limit_backward=g,z.ket=z.cursor,e=z.find_among_b(S,120))return z.bra=z.cursor,1==e&&z.slice_del(),z.limit_backward=r,!0;z.limit_backward=r}return!1}function d(){var e;z.ket=z.cursor,(e=z.find_among_b(W,7))&&(z.bra=z.cursor,1==e&&w()&&z.slice_del())}function v(e,r){if(z.eq_s_b(1,e)){z.bra=z.cursor;var s=z.limit-z.cursor;if(z.eq_s_b(1,r))return z.cursor=z.limit-s,w()&&z.slice_del(),!1}return!0}function p(){var e;if(z.ket=z.cursor,e=z.find_among_b(L,4))switch(z.bra=z.cursor,e){case 1:w()&&(z.slice_del(),z.ket=z.cursor,z.limit-z.cursor,v("u","g")&&v("i","c"));break;case 2:z.slice_from("c")}}function _(){if(!l()&&(z.cursor=z.limit,!f()))return z.cursor=z.limit,void d();z.cursor=z.limit,z.ket=z.cursor,z.eq_s_b(1,"i")&&(z.bra=z.cursor,z.eq_s_b(1,"c")&&(z.cursor=z.limit,w()&&z.slice_del()))}var h,b,g,k=[new r("",-1,3),new r("ã",0,1),new r("õ",0,2)],q=[new r("",-1,3),new r("a~",0,1),new r("o~",0,2)],j=[new r("ic",-1,-1),new r("ad",-1,-1),new r("os",-1,-1),new r("iv",-1,1)],C=[new r("ante",-1,1),new r("avel",-1,1),new r("ível",-1,1)],P=[new r("ic",-1,1),new r("abil",-1,1),new r("iv",-1,1)],F=[new r("ica",-1,1),new r("ância",-1,1),new r("ência",-1,4),new r("ira",-1,9),new r("adora",-1,1),new r("osa",-1,1),new r("ista",-1,1),new r("iva",-1,8),new r("eza",-1,1),new r("logía",-1,2),new r("idade",-1,7),new r("ante",-1,1),new r("mente",-1,6),new r("amente",12,5),new r("ável",-1,1),new r("ível",-1,1),new r("ución",-1,3),new r("ico",-1,1),new r("ismo",-1,1),new r("oso",-1,1),new r("amento",-1,1),new r("imento",-1,1),new r("ivo",-1,8),new r("aça~o",-1,1),new r("ador",-1,1),new r("icas",-1,1),new r("ências",-1,4),new r("iras",-1,9),new r("adoras",-1,1),new r("osas",-1,1),new r("istas",-1,1),new r("ivas",-1,8),new r("ezas",-1,1),new r("logías",-1,2),new r("idades",-1,7),new r("uciones",-1,3),new r("adores",-1,1),new r("antes",-1,1),new r("aço~es",-1,1),new r("icos",-1,1),new r("ismos",-1,1),new r("osos",-1,1),new r("amentos",-1,1),new r("imentos",-1,1),new r("ivos",-1,8)],S=[new r("ada",-1,1),new r("ida",-1,1),new r("ia",-1,1),new r("aria",2,1),new r("eria",2,1),new r("iria",2,1),new r("ara",-1,1),new r("era",-1,1),new r("ira",-1,1),new r("ava",-1,1),new r("asse",-1,1),new r("esse",-1,1),new r("isse",-1,1),new r("aste",-1,1),new r("este",-1,1),new r("iste",-1,1),new r("ei",-1,1),new r("arei",16,1),new r("erei",16,1),new r("irei",16,1),new r("am",-1,1),new r("iam",20,1),new r("ariam",21,1),new r("eriam",21,1),new r("iriam",21,1),new r("aram",20,1),new r("eram",20,1),new r("iram",20,1),new r("avam",20,1),new r("em",-1,1),new r("arem",29,1),new r("erem",29,1),new r("irem",29,1),new r("assem",29,1),new r("essem",29,1),new r("issem",29,1),new r("ado",-1,1),new r("ido",-1,1),new r("ando",-1,1),new r("endo",-1,1),new r("indo",-1,1),new r("ara~o",-1,1),new r("era~o",-1,1),new r("ira~o",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("ir",-1,1),new r("as",-1,1),new r("adas",47,1),new r("idas",47,1),new r("ias",47,1),new r("arias",50,1),new r("erias",50,1),new r("irias",50,1),new r("aras",47,1),new r("eras",47,1),new r("iras",47,1),new r("avas",47,1),new r("es",-1,1),new r("ardes",58,1),new r("erdes",58,1),new r("irdes",58,1),new r("ares",58,1),new r("eres",58,1),new r("ires",58,1),new r("asses",58,1),new r("esses",58,1),new r("isses",58,1),new r("astes",58,1),new r("estes",58,1),new r("istes",58,1),new r("is",-1,1),new r("ais",71,1),new r("eis",71,1),new r("areis",73,1),new r("ereis",73,1),new r("ireis",73,1),new r("áreis",73,1),new r("éreis",73,1),new r("íreis",73,1),new r("ásseis",73,1),new r("ésseis",73,1),new r("ísseis",73,1),new r("áveis",73,1),new r("íeis",73,1),new r("aríeis",84,1),new r("eríeis",84,1),new r("iríeis",84,1),new r("ados",-1,1),new r("idos",-1,1),new r("amos",-1,1),new r("áramos",90,1),new r("éramos",90,1),new r("íramos",90,1),new r("ávamos",90,1),new r("íamos",90,1),new r("aríamos",95,1),new r("eríamos",95,1),new r("iríamos",95,1),new r("emos",-1,1),new r("aremos",99,1),new r("eremos",99,1),new r("iremos",99,1),new r("ássemos",99,1),new r("êssemos",99,1),new r("íssemos",99,1),new r("imos",-1,1),new r("armos",-1,1),new r("ermos",-1,1),new r("irmos",-1,1),new r("ámos",-1,1),new r("arás",-1,1),new r("erás",-1,1),new r("irás",-1,1),new r("eu",-1,1),new r("iu",-1,1),new r("ou",-1,1),new r("ará",-1,1),new r("erá",-1,1),new r("irá",-1,1)],W=[new r("a",-1,1),new r("i",-1,1),new r("o",-1,1),new r("os",-1,1),new r("á",-1,1),new r("í",-1,1),new r("ó",-1,1)],L=[new r("e",-1,1),new r("ç",-1,2),new r("é",-1,1),new r("ê",-1,1)],y=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,3,19,12,2],z=new s;this.setCurrent=function(e){z.setCurrent(e)},this.getCurrent=function(){return z.getCurrent()},this.stem=function(){var r=z.cursor;return e(),z.cursor=r,a(),z.limit_backward=r,z.cursor=z.limit,_(),z.cursor=z.limit,p(),z.cursor=z.limit_backward,u(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.pt.stemmer,"stemmer-pt"),e.pt.stopWordFilter=e.generateStopWordFilter("a ao aos aquela aquelas aquele aqueles aquilo as até com como da das de dela delas dele deles depois do dos e ela elas ele eles em entre era eram essa essas esse esses esta estamos estas estava estavam este esteja estejam estejamos estes esteve estive estivemos estiver estivera estiveram estiverem estivermos estivesse estivessem estivéramos estivéssemos estou está estávamos estão eu foi fomos for fora foram forem formos fosse fossem fui fôramos fôssemos haja hajam hajamos havemos hei houve houvemos houver houvera houveram houverei houverem houveremos houveria houveriam houvermos houverá houverão houveríamos houvesse houvessem houvéramos houvéssemos há hão isso isto já lhe lhes mais mas me mesmo meu meus minha minhas muito na nas nem no nos nossa nossas nosso nossos num numa não nós o os ou para pela pelas pelo pelos por qual quando que quem se seja sejam sejamos sem serei seremos seria seriam será serão seríamos seu seus somos sou sua suas são só também te tem temos tenha tenham tenhamos tenho terei teremos teria teriam terá terão teríamos teu teus teve tinha tinham tive tivemos tiver tivera tiveram tiverem tivermos tivesse tivessem tivéramos tivéssemos tu tua tuas tém tínhamos um uma você vocês vos à às éramos".split(" ")),e.Pipeline.registerFunction(e.pt.stopWordFilter,"stopWordFilter-pt")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.ro.min.js b/public/assets/javascripts/lunr/min/lunr.ro.min.js new file mode 100644 index 0000000..7277140 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.ro.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Romanian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ro=function(){this.pipeline.reset(),this.pipeline.add(e.ro.trimmer,e.ro.stopWordFilter,e.ro.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ro.stemmer))},e.ro.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.ro.trimmer=e.trimmerSupport.generateTrimmer(e.ro.wordCharacters),e.Pipeline.registerFunction(e.ro.trimmer,"trimmer-ro"),e.ro.stemmer=function(){var i=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,n=new function(){function e(e,i){L.eq_s(1,e)&&(L.ket=L.cursor,L.in_grouping(W,97,259)&&L.slice_from(i))}function n(){for(var i,r;;){if(i=L.cursor,L.in_grouping(W,97,259)&&(r=L.cursor,L.bra=r,e("u","U"),L.cursor=r,e("i","I")),L.cursor=i,L.cursor>=L.limit)break;L.cursor++}}function t(){if(L.out_grouping(W,97,259)){for(;!L.in_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}return!0}function a(){if(L.in_grouping(W,97,259))for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!0;L.cursor++}return!1}function o(){var e,i,r=L.cursor;if(L.in_grouping(W,97,259)){if(e=L.cursor,!t())return void(h=L.cursor);if(L.cursor=e,!a())return void(h=L.cursor)}L.cursor=r,L.out_grouping(W,97,259)&&(i=L.cursor,t()&&(L.cursor=i,L.in_grouping(W,97,259)&&L.cursor=L.limit)return!1;L.cursor++}for(;!L.out_grouping(W,97,259);){if(L.cursor>=L.limit)return!1;L.cursor++}return!0}function c(){var e=L.cursor;h=L.limit,k=h,g=h,o(),L.cursor=e,u()&&(k=L.cursor,u()&&(g=L.cursor))}function s(){for(var e;;){if(L.bra=L.cursor,e=L.find_among(z,3))switch(L.ket=L.cursor,e){case 1:L.slice_from("i");continue;case 2:L.slice_from("u");continue;case 3:if(L.cursor>=L.limit)break;L.cursor++;continue}break}}function w(){return h<=L.cursor}function m(){return k<=L.cursor}function l(){return g<=L.cursor}function f(){var e,i;if(L.ket=L.cursor,(e=L.find_among_b(C,16))&&(L.bra=L.cursor,m()))switch(e){case 1:L.slice_del();break;case 2:L.slice_from("a");break;case 3:L.slice_from("e");break;case 4:L.slice_from("i");break;case 5:i=L.limit-L.cursor,L.eq_s_b(2,"ab")||(L.cursor=L.limit-i,L.slice_from("i"));break;case 6:L.slice_from("at");break;case 7:L.slice_from("aţi")}}function p(){var e,i=L.limit-L.cursor;if(L.ket=L.cursor,(e=L.find_among_b(P,46))&&(L.bra=L.cursor,m())){switch(e){case 1:L.slice_from("abil");break;case 2:L.slice_from("ibil");break;case 3:L.slice_from("iv");break;case 4:L.slice_from("ic");break;case 5:L.slice_from("at");break;case 6:L.slice_from("it")}return _=!0,L.cursor=L.limit-i,!0}return!1}function d(){var e,i;for(_=!1;;)if(i=L.limit-L.cursor,!p()){L.cursor=L.limit-i;break}if(L.ket=L.cursor,(e=L.find_among_b(F,62))&&(L.bra=L.cursor,l())){switch(e){case 1:L.slice_del();break;case 2:L.eq_s_b(1,"ţ")&&(L.bra=L.cursor,L.slice_from("t"));break;case 3:L.slice_from("ist")}_=!0}}function b(){var e,i,r;if(L.cursor>=h){if(i=L.limit_backward,L.limit_backward=h,L.ket=L.cursor,e=L.find_among_b(q,94))switch(L.bra=L.cursor,e){case 1:if(r=L.limit-L.cursor,!L.out_grouping_b(W,97,259)&&(L.cursor=L.limit-r,!L.eq_s_b(1,"u")))break;case 2:L.slice_del()}L.limit_backward=i}}function v(){var e;L.ket=L.cursor,(e=L.find_among_b(S,5))&&(L.bra=L.cursor,w()&&1==e&&L.slice_del())}var _,g,k,h,z=[new i("",-1,3),new i("I",0,1),new i("U",0,2)],C=[new i("ea",-1,3),new i("aţia",-1,7),new i("aua",-1,2),new i("iua",-1,4),new i("aţie",-1,7),new i("ele",-1,3),new i("ile",-1,5),new i("iile",6,4),new i("iei",-1,4),new i("atei",-1,6),new i("ii",-1,4),new i("ului",-1,1),new i("ul",-1,1),new i("elor",-1,3),new i("ilor",-1,4),new i("iilor",14,4)],P=[new i("icala",-1,4),new i("iciva",-1,4),new i("ativa",-1,5),new i("itiva",-1,6),new i("icale",-1,4),new i("aţiune",-1,5),new i("iţiune",-1,6),new i("atoare",-1,5),new i("itoare",-1,6),new i("ătoare",-1,5),new i("icitate",-1,4),new i("abilitate",-1,1),new i("ibilitate",-1,2),new i("ivitate",-1,3),new i("icive",-1,4),new i("ative",-1,5),new i("itive",-1,6),new i("icali",-1,4),new i("atori",-1,5),new i("icatori",18,4),new i("itori",-1,6),new i("ători",-1,5),new i("icitati",-1,4),new i("abilitati",-1,1),new i("ivitati",-1,3),new i("icivi",-1,4),new i("ativi",-1,5),new i("itivi",-1,6),new i("icităi",-1,4),new i("abilităi",-1,1),new i("ivităi",-1,3),new i("icităţi",-1,4),new i("abilităţi",-1,1),new i("ivităţi",-1,3),new i("ical",-1,4),new i("ator",-1,5),new i("icator",35,4),new i("itor",-1,6),new i("ător",-1,5),new i("iciv",-1,4),new i("ativ",-1,5),new i("itiv",-1,6),new i("icală",-1,4),new i("icivă",-1,4),new i("ativă",-1,5),new i("itivă",-1,6)],F=[new i("ica",-1,1),new i("abila",-1,1),new i("ibila",-1,1),new i("oasa",-1,1),new i("ata",-1,1),new i("ita",-1,1),new i("anta",-1,1),new i("ista",-1,3),new i("uta",-1,1),new i("iva",-1,1),new i("ic",-1,1),new i("ice",-1,1),new i("abile",-1,1),new i("ibile",-1,1),new i("isme",-1,3),new i("iune",-1,2),new i("oase",-1,1),new i("ate",-1,1),new i("itate",17,1),new i("ite",-1,1),new i("ante",-1,1),new i("iste",-1,3),new i("ute",-1,1),new i("ive",-1,1),new i("ici",-1,1),new i("abili",-1,1),new i("ibili",-1,1),new i("iuni",-1,2),new i("atori",-1,1),new i("osi",-1,1),new i("ati",-1,1),new i("itati",30,1),new i("iti",-1,1),new i("anti",-1,1),new i("isti",-1,3),new i("uti",-1,1),new i("işti",-1,3),new i("ivi",-1,1),new i("ităi",-1,1),new i("oşi",-1,1),new i("ităţi",-1,1),new i("abil",-1,1),new i("ibil",-1,1),new i("ism",-1,3),new i("ator",-1,1),new i("os",-1,1),new i("at",-1,1),new i("it",-1,1),new i("ant",-1,1),new i("ist",-1,3),new i("ut",-1,1),new i("iv",-1,1),new i("ică",-1,1),new i("abilă",-1,1),new i("ibilă",-1,1),new i("oasă",-1,1),new i("ată",-1,1),new i("ită",-1,1),new i("antă",-1,1),new i("istă",-1,3),new i("ută",-1,1),new i("ivă",-1,1)],q=[new i("ea",-1,1),new i("ia",-1,1),new i("esc",-1,1),new i("ăsc",-1,1),new i("ind",-1,1),new i("ând",-1,1),new i("are",-1,1),new i("ere",-1,1),new i("ire",-1,1),new i("âre",-1,1),new i("se",-1,2),new i("ase",10,1),new i("sese",10,2),new i("ise",10,1),new i("use",10,1),new i("âse",10,1),new i("eşte",-1,1),new i("ăşte",-1,1),new i("eze",-1,1),new i("ai",-1,1),new i("eai",19,1),new i("iai",19,1),new i("sei",-1,2),new i("eşti",-1,1),new i("ăşti",-1,1),new i("ui",-1,1),new i("ezi",-1,1),new i("âi",-1,1),new i("aşi",-1,1),new i("seşi",-1,2),new i("aseşi",29,1),new i("seseşi",29,2),new i("iseşi",29,1),new i("useşi",29,1),new i("âseşi",29,1),new i("işi",-1,1),new i("uşi",-1,1),new i("âşi",-1,1),new i("aţi",-1,2),new i("eaţi",38,1),new i("iaţi",38,1),new i("eţi",-1,2),new i("iţi",-1,2),new i("âţi",-1,2),new i("arăţi",-1,1),new i("serăţi",-1,2),new i("aserăţi",45,1),new i("seserăţi",45,2),new i("iserăţi",45,1),new i("userăţi",45,1),new i("âserăţi",45,1),new i("irăţi",-1,1),new i("urăţi",-1,1),new i("ârăţi",-1,1),new i("am",-1,1),new i("eam",54,1),new i("iam",54,1),new i("em",-1,2),new i("asem",57,1),new i("sesem",57,2),new i("isem",57,1),new i("usem",57,1),new i("âsem",57,1),new i("im",-1,2),new i("âm",-1,2),new i("ăm",-1,2),new i("arăm",65,1),new i("serăm",65,2),new i("aserăm",67,1),new i("seserăm",67,2),new i("iserăm",67,1),new i("userăm",67,1),new i("âserăm",67,1),new i("irăm",65,1),new i("urăm",65,1),new i("ârăm",65,1),new i("au",-1,1),new i("eau",76,1),new i("iau",76,1),new i("indu",-1,1),new i("ându",-1,1),new i("ez",-1,1),new i("ească",-1,1),new i("ară",-1,1),new i("seră",-1,2),new i("aseră",84,1),new i("seseră",84,2),new i("iseră",84,1),new i("useră",84,1),new i("âseră",84,1),new i("iră",-1,1),new i("ură",-1,1),new i("âră",-1,1),new i("ează",-1,1)],S=[new i("a",-1,1),new i("e",-1,1),new i("ie",1,1),new i("i",-1,1),new i("ă",-1,1)],W=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,2,32,0,0,4],L=new r;this.setCurrent=function(e){L.setCurrent(e)},this.getCurrent=function(){return L.getCurrent()},this.stem=function(){var e=L.cursor;return n(),L.cursor=e,c(),L.limit_backward=e,L.cursor=L.limit,f(),L.cursor=L.limit,d(),L.cursor=L.limit,_||(L.cursor=L.limit,b(),L.cursor=L.limit),v(),L.cursor=L.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.ro.stemmer,"stemmer-ro"),e.ro.stopWordFilter=e.generateStopWordFilter("acea aceasta această aceea acei aceia acel acela acele acelea acest acesta aceste acestea aceşti aceştia acolo acord acum ai aia aibă aici al ale alea altceva altcineva am ar are asemenea asta astea astăzi asupra au avea avem aveţi azi aş aşadar aţi bine bucur bună ca care caut ce cel ceva chiar cinci cine cineva contra cu cum cumva curând curînd când cât câte câtva câţi cînd cît cîte cîtva cîţi că căci cărei căror cărui către da dacă dar datorită dată dau de deci deja deoarece departe deşi din dinaintea dintr- dintre doi doilea două drept după dă ea ei el ele eram este eu eşti face fata fi fie fiecare fii fim fiu fiţi frumos fără graţie halbă iar ieri la le li lor lui lângă lîngă mai mea mei mele mereu meu mi mie mine mult multă mulţi mulţumesc mâine mîine mă ne nevoie nici nicăieri nimeni nimeri nimic nişte noastre noastră noi noroc nostru nouă noştri nu opt ori oricare orice oricine oricum oricând oricât oricînd oricît oriunde patra patru patrulea pe pentru peste pic poate pot prea prima primul prin puţin puţina puţină până pînă rog sa sale sau se spate spre sub sunt suntem sunteţi sută sînt sîntem sînteţi să săi său ta tale te timp tine toate toată tot totuşi toţi trei treia treilea tu tăi tău un una unde undeva unei uneia unele uneori unii unor unora unu unui unuia unul vi voastre voastră voi vostru vouă voştri vreme vreo vreun vă zece zero zi zice îi îl îmi împotriva în înainte înaintea încotro încât încît între întrucât întrucît îţi ăla ălea ăsta ăstea ăştia şapte şase şi ştiu ţi ţie".split(" ")),e.Pipeline.registerFunction(e.ro.stopWordFilter,"stopWordFilter-ro")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.ru.min.js b/public/assets/javascripts/lunr/min/lunr.ru.min.js new file mode 100644 index 0000000..186cc48 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.ru.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Russian` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():n()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ru=function(){this.pipeline.reset(),this.pipeline.add(e.ru.trimmer,e.ru.stopWordFilter,e.ru.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ru.stemmer))},e.ru.wordCharacters="Ѐ-҄҇-ԯᴫᵸⷠ-ⷿꙀ-ꚟ︮︯",e.ru.trimmer=e.trimmerSupport.generateTrimmer(e.ru.wordCharacters),e.Pipeline.registerFunction(e.ru.trimmer,"trimmer-ru"),e.ru.stemmer=function(){var n=e.stemmerSupport.Among,r=e.stemmerSupport.SnowballProgram,t=new function(){function e(){for(;!W.in_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function t(){for(;!W.out_grouping(S,1072,1103);){if(W.cursor>=W.limit)return!1;W.cursor++}return!0}function w(){b=W.limit,_=b,e()&&(b=W.cursor,t()&&e()&&t()&&(_=W.cursor))}function i(){return _<=W.cursor}function u(e,n){var r,t;if(W.ket=W.cursor,r=W.find_among_b(e,n)){switch(W.bra=W.cursor,r){case 1:if(t=W.limit-W.cursor,!W.eq_s_b(1,"а")&&(W.cursor=W.limit-t,!W.eq_s_b(1,"я")))return!1;case 2:W.slice_del()}return!0}return!1}function o(){return u(h,9)}function s(e,n){var r;return W.ket=W.cursor,!!(r=W.find_among_b(e,n))&&(W.bra=W.cursor,1==r&&W.slice_del(),!0)}function c(){return s(g,26)}function m(){return!!c()&&(u(C,8),!0)}function f(){return s(k,2)}function l(){return u(P,46)}function a(){s(v,36)}function p(){var e;W.ket=W.cursor,(e=W.find_among_b(F,2))&&(W.bra=W.cursor,i()&&1==e&&W.slice_del())}function d(){var e;if(W.ket=W.cursor,e=W.find_among_b(q,4))switch(W.bra=W.cursor,e){case 1:if(W.slice_del(),W.ket=W.cursor,!W.eq_s_b(1,"н"))break;W.bra=W.cursor;case 2:if(!W.eq_s_b(1,"н"))break;case 3:W.slice_del()}}var _,b,h=[new n("в",-1,1),new n("ив",0,2),new n("ыв",0,2),new n("вши",-1,1),new n("ивши",3,2),new n("ывши",3,2),new n("вшись",-1,1),new n("ившись",6,2),new n("ывшись",6,2)],g=[new n("ее",-1,1),new n("ие",-1,1),new n("ое",-1,1),new n("ые",-1,1),new n("ими",-1,1),new n("ыми",-1,1),new n("ей",-1,1),new n("ий",-1,1),new n("ой",-1,1),new n("ый",-1,1),new n("ем",-1,1),new n("им",-1,1),new n("ом",-1,1),new n("ым",-1,1),new n("его",-1,1),new n("ого",-1,1),new n("ему",-1,1),new n("ому",-1,1),new n("их",-1,1),new n("ых",-1,1),new n("ею",-1,1),new n("ою",-1,1),new n("ую",-1,1),new n("юю",-1,1),new n("ая",-1,1),new n("яя",-1,1)],C=[new n("ем",-1,1),new n("нн",-1,1),new n("вш",-1,1),new n("ивш",2,2),new n("ывш",2,2),new n("щ",-1,1),new n("ющ",5,1),new n("ующ",6,2)],k=[new n("сь",-1,1),new n("ся",-1,1)],P=[new n("ла",-1,1),new n("ила",0,2),new n("ыла",0,2),new n("на",-1,1),new n("ена",3,2),new n("ете",-1,1),new n("ите",-1,2),new n("йте",-1,1),new n("ейте",7,2),new n("уйте",7,2),new n("ли",-1,1),new n("или",10,2),new n("ыли",10,2),new n("й",-1,1),new n("ей",13,2),new n("уй",13,2),new n("л",-1,1),new n("ил",16,2),new n("ыл",16,2),new n("ем",-1,1),new n("им",-1,2),new n("ым",-1,2),new n("н",-1,1),new n("ен",22,2),new n("ло",-1,1),new n("ило",24,2),new n("ыло",24,2),new n("но",-1,1),new n("ено",27,2),new n("нно",27,1),new n("ет",-1,1),new n("ует",30,2),new n("ит",-1,2),new n("ыт",-1,2),new n("ют",-1,1),new n("уют",34,2),new n("ят",-1,2),new n("ны",-1,1),new n("ены",37,2),new n("ть",-1,1),new n("ить",39,2),new n("ыть",39,2),new n("ешь",-1,1),new n("ишь",-1,2),new n("ю",-1,2),new n("ую",44,2)],v=[new n("а",-1,1),new n("ев",-1,1),new n("ов",-1,1),new n("е",-1,1),new n("ие",3,1),new n("ье",3,1),new n("и",-1,1),new n("еи",6,1),new n("ии",6,1),new n("ами",6,1),new n("ями",6,1),new n("иями",10,1),new n("й",-1,1),new n("ей",12,1),new n("ией",13,1),new n("ий",12,1),new n("ой",12,1),new n("ам",-1,1),new n("ем",-1,1),new n("ием",18,1),new n("ом",-1,1),new n("ям",-1,1),new n("иям",21,1),new n("о",-1,1),new n("у",-1,1),new n("ах",-1,1),new n("ях",-1,1),new n("иях",26,1),new n("ы",-1,1),new n("ь",-1,1),new n("ю",-1,1),new n("ию",30,1),new n("ью",30,1),new n("я",-1,1),new n("ия",33,1),new n("ья",33,1)],F=[new n("ост",-1,1),new n("ость",-1,1)],q=[new n("ейше",-1,1),new n("н",-1,2),new n("ейш",-1,1),new n("ь",-1,3)],S=[33,65,8,232],W=new r;this.setCurrent=function(e){W.setCurrent(e)},this.getCurrent=function(){return W.getCurrent()},this.stem=function(){return w(),W.cursor=W.limit,!(W.cursor=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursors||e>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor>1),f=0,l=o0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.sv.min.js b/public/assets/javascripts/lunr/min/lunr.sv.min.js new file mode 100644 index 0000000..3e5eb64 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.sv.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Swedish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.tr.min.js b/public/assets/javascripts/lunr/min/lunr.tr.min.js new file mode 100644 index 0000000..563f6ec --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.tr.min.js @@ -0,0 +1,18 @@ +/*! + * Lunr languages, `Turkish` language + * https://github.com/MihaiValentin/lunr-languages + * + * Copyright 2014, Mihai Valentin + * http://www.mozilla.org/MPL/ + */ +/*! + * based on + * Snowball JavaScript Library v0.3 + * http://code.google.com/p/urim/ + * http://snowball.tartarus.org/ + * + * Copyright 2010, Oleg Mazko + * http://www.mozilla.org/MPL/ + */ + +!function(r,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(r.lunr)}(this,function(){return function(r){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");r.tr=function(){this.pipeline.reset(),this.pipeline.add(r.tr.trimmer,r.tr.stopWordFilter,r.tr.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(r.tr.stemmer))},r.tr.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",r.tr.trimmer=r.trimmerSupport.generateTrimmer(r.tr.wordCharacters),r.Pipeline.registerFunction(r.tr.trimmer,"trimmer-tr"),r.tr.stemmer=function(){var i=r.stemmerSupport.Among,e=r.stemmerSupport.SnowballProgram,n=new function(){function r(r,i,e){for(;;){var n=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(r,i,e)){Dr.cursor=Dr.limit-n;break}if(Dr.cursor=Dr.limit-n,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function n(){var i,e;i=Dr.limit-Dr.cursor,r(Wr,97,305);for(var n=0;nDr.limit_backward&&(Dr.cursor--,e=Dr.limit-Dr.cursor,i()))?(Dr.cursor=Dr.limit-e,!0):(Dr.cursor=Dr.limit-n,r()?(Dr.cursor=Dr.limit-n,!1):(Dr.cursor=Dr.limit-n,!(Dr.cursor<=Dr.limit_backward)&&(Dr.cursor--,!!i()&&(Dr.cursor=Dr.limit-n,!0))))}function u(r){return t(r,function(){return Dr.in_grouping_b(Wr,97,305)})}function o(){return u(function(){return Dr.eq_s_b(1,"n")})}function s(){return u(function(){return Dr.eq_s_b(1,"s")})}function c(){return u(function(){return Dr.eq_s_b(1,"y")})}function l(){return t(function(){return Dr.in_grouping_b(Lr,105,305)},function(){return Dr.out_grouping_b(Wr,97,305)})}function a(){return Dr.find_among_b(ur,10)&&l()}function m(){return n()&&Dr.in_grouping_b(Lr,105,305)&&s()}function d(){return Dr.find_among_b(or,2)}function f(){return n()&&Dr.in_grouping_b(Lr,105,305)&&c()}function b(){return n()&&Dr.find_among_b(sr,4)}function w(){return n()&&Dr.find_among_b(cr,4)&&o()}function _(){return n()&&Dr.find_among_b(lr,2)&&c()}function k(){return n()&&Dr.find_among_b(ar,2)}function p(){return n()&&Dr.find_among_b(mr,4)}function g(){return n()&&Dr.find_among_b(dr,2)}function y(){return n()&&Dr.find_among_b(fr,4)}function z(){return n()&&Dr.find_among_b(br,2)}function v(){return n()&&Dr.find_among_b(wr,2)&&c()}function h(){return Dr.eq_s_b(2,"ki")}function q(){return n()&&Dr.find_among_b(_r,2)&&o()}function C(){return n()&&Dr.find_among_b(kr,4)&&c()}function P(){return n()&&Dr.find_among_b(pr,4)}function F(){return n()&&Dr.find_among_b(gr,4)&&c()}function S(){return Dr.find_among_b(yr,4)}function W(){return n()&&Dr.find_among_b(zr,2)}function L(){return n()&&Dr.find_among_b(vr,4)}function x(){return n()&&Dr.find_among_b(hr,8)}function A(){return Dr.find_among_b(qr,2)}function E(){return n()&&Dr.find_among_b(Cr,32)&&c()}function j(){return Dr.find_among_b(Pr,8)&&c()}function T(){return n()&&Dr.find_among_b(Fr,4)&&c()}function Z(){return Dr.eq_s_b(3,"ken")&&c()}function B(){var r=Dr.limit-Dr.cursor;return!(T()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,Z()))))}function D(){if(A()){var r=Dr.limit-Dr.cursor;if(S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T())return!1}return!0}function G(){if(W()){Dr.bra=Dr.cursor,Dr.slice_del();var r=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,x()||(Dr.cursor=Dr.limit-r,E()||(Dr.cursor=Dr.limit-r,j()||(Dr.cursor=Dr.limit-r,T()||(Dr.cursor=Dr.limit-r)))),nr=!1,!1}return!0}function H(){if(!L())return!0;var r=Dr.limit-Dr.cursor;return!E()&&(Dr.cursor=Dr.limit-r,!j())}function I(){var r,i=Dr.limit-Dr.cursor;return!(S()||(Dr.cursor=Dr.limit-i,F()||(Dr.cursor=Dr.limit-i,P()||(Dr.cursor=Dr.limit-i,C()))))||(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,T()||(Dr.cursor=Dr.limit-r),!1)}function J(){var r,i=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,nr=!0,B()&&(Dr.cursor=Dr.limit-i,D()&&(Dr.cursor=Dr.limit-i,G()&&(Dr.cursor=Dr.limit-i,H()&&(Dr.cursor=Dr.limit-i,I()))))){if(Dr.cursor=Dr.limit-i,!x())return;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,S()||(Dr.cursor=Dr.limit-r,W()||(Dr.cursor=Dr.limit-r,C()||(Dr.cursor=Dr.limit-r,P()||(Dr.cursor=Dr.limit-r,F()||(Dr.cursor=Dr.limit-r))))),T()||(Dr.cursor=Dr.limit-r)}Dr.bra=Dr.cursor,Dr.slice_del()}function K(){var r,i,e,n;if(Dr.ket=Dr.cursor,h()){if(r=Dr.limit-Dr.cursor,p())return Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,a()&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))),!0;if(Dr.cursor=Dr.limit-r,w()){if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,e=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-e,!m()&&(Dr.cursor=Dr.limit-e,!K())))return!0;Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}return!0}if(Dr.cursor=Dr.limit-r,g()){if(n=Dr.limit-Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-n,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-n,!K())return!1;return!0}}return!1}function M(r){if(Dr.ket=Dr.cursor,!g()&&(Dr.cursor=Dr.limit-r,!k()))return!1;var i=Dr.limit-Dr.cursor;if(d())Dr.bra=Dr.cursor,Dr.slice_del();else if(Dr.cursor=Dr.limit-i,m())Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K());else if(Dr.cursor=Dr.limit-i,!K())return!1;return!0}function N(r){if(Dr.ket=Dr.cursor,!z()&&(Dr.cursor=Dr.limit-r,!b()))return!1;var i=Dr.limit-Dr.cursor;return!(!m()&&(Dr.cursor=Dr.limit-i,!d()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)}function O(){var r,i=Dr.limit-Dr.cursor;return Dr.ket=Dr.cursor,!(!w()&&(Dr.cursor=Dr.limit-i,!v()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,!(!W()||(Dr.bra=Dr.cursor,Dr.slice_del(),!K()))||(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!(a()||(Dr.cursor=Dr.limit-r,m()||(Dr.cursor=Dr.limit-r,K())))||(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()),!0)))}function Q(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,!p()&&(Dr.cursor=Dr.limit-e,!f()&&(Dr.cursor=Dr.limit-e,!_())))return!1;if(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,r=Dr.limit-Dr.cursor,a())Dr.bra=Dr.cursor,Dr.slice_del(),i=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,W()||(Dr.cursor=Dr.limit-i);else if(Dr.cursor=Dr.limit-r,!W())return!0;return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,K(),!0}function R(){var r,i,e=Dr.limit-Dr.cursor;if(Dr.ket=Dr.cursor,W())return Dr.bra=Dr.cursor,Dr.slice_del(),void K();if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,q())if(Dr.bra=Dr.cursor,Dr.slice_del(),r=Dr.limit-Dr.cursor,Dr.ket=Dr.cursor,d())Dr.bra=Dr.cursor,Dr.slice_del();else{if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!a()&&(Dr.cursor=Dr.limit-r,!m())){if(Dr.cursor=Dr.limit-r,Dr.ket=Dr.cursor,!W())return;if(Dr.bra=Dr.cursor,Dr.slice_del(),!K())return}Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())}else if(Dr.cursor=Dr.limit-e,!M(e)&&(Dr.cursor=Dr.limit-e,!N(e))){if(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,y())return Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,i=Dr.limit-Dr.cursor,void(a()?(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K())):(Dr.cursor=Dr.limit-i,W()?(Dr.bra=Dr.cursor,Dr.slice_del(),K()):(Dr.cursor=Dr.limit-i,K())));if(Dr.cursor=Dr.limit-e,!O()){if(Dr.cursor=Dr.limit-e,d())return Dr.bra=Dr.cursor,void Dr.slice_del();Dr.cursor=Dr.limit-e,K()||(Dr.cursor=Dr.limit-e,Q()||(Dr.cursor=Dr.limit-e,Dr.ket=Dr.cursor,(a()||(Dr.cursor=Dr.limit-e,m()))&&(Dr.bra=Dr.cursor,Dr.slice_del(),Dr.ket=Dr.cursor,W()&&(Dr.bra=Dr.cursor,Dr.slice_del(),K()))))}}}function U(){var r;if(Dr.ket=Dr.cursor,r=Dr.find_among_b(Sr,4))switch(Dr.bra=Dr.cursor,r){case 1:Dr.slice_from("p");break;case 2:Dr.slice_from("ç");break;case 3:Dr.slice_from("t");break;case 4:Dr.slice_from("k")}}function V(){for(;;){var r=Dr.limit-Dr.cursor;if(Dr.in_grouping_b(Wr,97,305)){Dr.cursor=Dr.limit-r;break}if(Dr.cursor=Dr.limit-r,Dr.cursor<=Dr.limit_backward)return!1;Dr.cursor--}return!0}function X(r,i,e){if(Dr.cursor=Dr.limit-r,V()){var n=Dr.limit-Dr.cursor;if(!Dr.eq_s_b(1,i)&&(Dr.cursor=Dr.limit-n,!Dr.eq_s_b(1,e)))return!0;Dr.cursor=Dr.limit-r;var t=Dr.cursor;return Dr.insert(Dr.cursor,Dr.cursor,e),Dr.cursor=t,!1}return!0}function Y(){var r=Dr.limit-Dr.cursor;(Dr.eq_s_b(1,"d")||(Dr.cursor=Dr.limit-r,Dr.eq_s_b(1,"g")))&&X(r,"a","ı")&&X(r,"e","i")&&X(r,"o","u")&&X(r,"ö","ü")}function $(){for(var r,i=Dr.cursor,e=2;;){for(r=Dr.cursor;!Dr.in_grouping(Wr,97,305);){if(Dr.cursor>=Dr.limit)return Dr.cursor=r,!(e>0)&&(Dr.cursor=i,!0);Dr.cursor++}e--}}function rr(r,i,e){for(;!Dr.eq_s(i,e);){if(Dr.cursor>=Dr.limit)return!0;Dr.cursor++}return(tr=i)!=Dr.limit||(Dr.cursor=r,!1)}function ir(){var r=Dr.cursor;return!rr(r,2,"ad")||(Dr.cursor=r,!rr(r,5,"soyad"))}function er(){var r=Dr.cursor;return!ir()&&(Dr.limit_backward=r,Dr.cursor=Dr.limit,Y(),Dr.cursor=Dr.limit,U(),!0)}var nr,tr,ur=[new i("m",-1,-1),new i("n",-1,-1),new i("miz",-1,-1),new i("niz",-1,-1),new i("muz",-1,-1),new i("nuz",-1,-1),new i("müz",-1,-1),new i("nüz",-1,-1),new i("mız",-1,-1),new i("nız",-1,-1)],or=[new i("leri",-1,-1),new i("ları",-1,-1)],sr=[new i("ni",-1,-1),new i("nu",-1,-1),new i("nü",-1,-1),new i("nı",-1,-1)],cr=[new i("in",-1,-1),new i("un",-1,-1),new i("ün",-1,-1),new i("ın",-1,-1)],lr=[new i("a",-1,-1),new i("e",-1,-1)],ar=[new i("na",-1,-1),new i("ne",-1,-1)],mr=[new i("da",-1,-1),new i("ta",-1,-1),new i("de",-1,-1),new i("te",-1,-1)],dr=[new i("nda",-1,-1),new i("nde",-1,-1)],fr=[new i("dan",-1,-1),new i("tan",-1,-1),new i("den",-1,-1),new i("ten",-1,-1)],br=[new i("ndan",-1,-1),new i("nden",-1,-1)],wr=[new i("la",-1,-1),new i("le",-1,-1)],_r=[new i("ca",-1,-1),new i("ce",-1,-1)],kr=[new i("im",-1,-1),new i("um",-1,-1),new i("üm",-1,-1),new i("ım",-1,-1)],pr=[new i("sin",-1,-1),new i("sun",-1,-1),new i("sün",-1,-1),new i("sın",-1,-1)],gr=[new i("iz",-1,-1),new i("uz",-1,-1),new i("üz",-1,-1),new i("ız",-1,-1)],yr=[new i("siniz",-1,-1),new i("sunuz",-1,-1),new i("sünüz",-1,-1),new i("sınız",-1,-1)],zr=[new i("lar",-1,-1),new i("ler",-1,-1)],vr=[new i("niz",-1,-1),new i("nuz",-1,-1),new i("nüz",-1,-1),new i("nız",-1,-1)],hr=[new i("dir",-1,-1),new i("tir",-1,-1),new i("dur",-1,-1),new i("tur",-1,-1),new i("dür",-1,-1),new i("tür",-1,-1),new i("dır",-1,-1),new i("tır",-1,-1)],qr=[new i("casına",-1,-1),new i("cesine",-1,-1)],Cr=[new i("di",-1,-1),new i("ti",-1,-1),new i("dik",-1,-1),new i("tik",-1,-1),new i("duk",-1,-1),new i("tuk",-1,-1),new i("dük",-1,-1),new i("tük",-1,-1),new i("dık",-1,-1),new i("tık",-1,-1),new i("dim",-1,-1),new i("tim",-1,-1),new i("dum",-1,-1),new i("tum",-1,-1),new i("düm",-1,-1),new i("tüm",-1,-1),new i("dım",-1,-1),new i("tım",-1,-1),new i("din",-1,-1),new i("tin",-1,-1),new i("dun",-1,-1),new i("tun",-1,-1),new i("dün",-1,-1),new i("tün",-1,-1),new i("dın",-1,-1),new i("tın",-1,-1),new i("du",-1,-1),new i("tu",-1,-1),new i("dü",-1,-1),new i("tü",-1,-1),new i("dı",-1,-1),new i("tı",-1,-1)],Pr=[new i("sa",-1,-1),new i("se",-1,-1),new i("sak",-1,-1),new i("sek",-1,-1),new i("sam",-1,-1),new i("sem",-1,-1),new i("san",-1,-1),new i("sen",-1,-1)],Fr=[new i("miş",-1,-1),new i("muş",-1,-1),new i("müş",-1,-1),new i("mış",-1,-1)],Sr=[new i("b",-1,1),new i("c",-1,2),new i("d",-1,3),new i("ğ",-1,4)],Wr=[17,65,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,8,0,0,0,0,0,0,1],Lr=[1,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,1],xr=[1,64,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],Ar=[17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130],Er=[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],jr=[17],Tr=[65],Zr=[65],Br=[["a",xr,97,305],["e",Ar,101,252],["ı",Er,97,305],["i",jr,101,105],["o",Tr,111,117],["ö",Zr,246,252],["u",Tr,111,117]],Dr=new e;this.setCurrent=function(r){Dr.setCurrent(r)},this.getCurrent=function(){return Dr.getCurrent()},this.stem=function(){return!!($()&&(Dr.limit_backward=Dr.cursor,Dr.cursor=Dr.limit,J(),Dr.cursor=Dr.limit,nr&&(R(),Dr.cursor=Dr.limit_backward,er())))}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.tr.stemmer,"stemmer-tr"),r.tr.stopWordFilter=r.generateStopWordFilter("acaba altmış altı ama ancak arada aslında ayrıca bana bazı belki ben benden beni benim beri beş bile bin bir biri birkaç birkez birçok birşey birşeyi biz bizden bize bizi bizim bu buna bunda bundan bunlar bunları bunların bunu bunun burada böyle böylece da daha dahi de defa değil diye diğer doksan dokuz dolayı dolayısıyla dört edecek eden ederek edilecek ediliyor edilmesi ediyor elli en etmesi etti ettiği ettiğini eğer gibi göre halen hangi hatta hem henüz hep hepsi her herhangi herkesin hiç hiçbir iki ile ilgili ise itibaren itibariyle için işte kadar karşın katrilyon kendi kendilerine kendini kendisi kendisine kendisini kez ki kim kimden kime kimi kimse kırk milyar milyon mu mü mı nasıl ne neden nedenle nerde nerede nereye niye niçin o olan olarak oldu olduklarını olduğu olduğunu olmadı olmadığı olmak olması olmayan olmaz olsa olsun olup olur olursa oluyor on ona ondan onlar onlardan onları onların onu onun otuz oysa pek rağmen sadece sanki sekiz seksen sen senden seni senin siz sizden sizi sizin tarafından trilyon tüm var vardı ve veya ya yani yapacak yapmak yaptı yaptıkları yaptığı yaptığını yapılan yapılması yapıyor yedi yerine yetmiş yine yirmi yoksa yüz zaten çok çünkü öyle üzere üç şey şeyden şeyi şeyler şu şuna şunda şundan şunları şunu şöyle".split(" ")),r.Pipeline.registerFunction(r.tr.stopWordFilter,"stopWordFilter-tr")}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/min/lunr.vi.min.js b/public/assets/javascripts/lunr/min/lunr.vi.min.js new file mode 100644 index 0000000..22aed28 --- /dev/null +++ b/public/assets/javascripts/lunr/min/lunr.vi.min.js @@ -0,0 +1 @@ +!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}}); \ No newline at end of file diff --git a/public/assets/javascripts/lunr/tinyseg.min.js b/public/assets/javascripts/lunr/tinyseg.min.js new file mode 100644 index 0000000..302befb --- /dev/null +++ b/public/assets/javascripts/lunr/tinyseg.min.js @@ -0,0 +1 @@ +!function(_,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(_.lunr)}(this,(function(){return function(_){function t(){var _={"[一二三四五六七八九十百千万億兆]":"M","[一-龠々〆ヵヶ]":"H","[ぁ-ん]":"I","[ァ-ヴーア-ン゙ー]":"K","[a-zA-Za-zA-Z]":"A","[0-90-9]":"N"};for(var t in this.chartype_=[],_){var H=new RegExp(t);this.chartype_.push([H,_[t]])}return this.BIAS__=-332,this.BC1__={HH:6,II:2461,KH:406,OH:-1378},this.BC2__={AA:-3267,AI:2744,AN:-878,HH:-4070,HM:-1711,HN:4012,HO:3761,IA:1327,IH:-1184,II:-1332,IK:1721,IO:5492,KI:3831,KK:-8741,MH:-3132,MK:3334,OO:-2920},this.BC3__={HH:996,HI:626,HK:-721,HN:-1307,HO:-836,IH:-301,KK:2762,MK:1079,MM:4034,OA:-1652,OH:266},this.BP1__={BB:295,OB:304,OO:-125,UB:352},this.BP2__={BO:60,OO:-1762},this.BQ1__={BHH:1150,BHM:1521,BII:-1158,BIM:886,BMH:1208,BNH:449,BOH:-91,BOO:-2597,OHI:451,OIH:-296,OKA:1851,OKH:-1020,OKK:904,OOO:2965},this.BQ2__={BHH:118,BHI:-1159,BHM:466,BIH:-919,BKK:-1720,BKO:864,OHH:-1139,OHM:-181,OIH:153,UHI:-1146},this.BQ3__={BHH:-792,BHI:2664,BII:-299,BKI:419,BMH:937,BMM:8335,BNN:998,BOH:775,OHH:2174,OHM:439,OII:280,OKH:1798,OKI:-793,OKO:-2242,OMH:-2402,OOO:11699},this.BQ4__={BHH:-3895,BIH:3761,BII:-4654,BIK:1348,BKK:-1806,BMI:-3385,BOO:-12396,OAH:926,OHH:266,OHK:-2036,ONN:-973},this.BW1__={",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682},this.BW2__={"..":-11822,11:-669,"――":-5730,"−−":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"11":-669},this.BW3__={"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1e3,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990},this.TC1__={AAA:1093,HHH:1029,HHM:580,HII:998,HOH:-390,HOM:-331,IHI:1169,IOH:-142,IOI:-1015,IOM:467,MMH:187,OOI:-1832},this.TC2__={HHO:2088,HII:-1023,HMM:-1154,IHI:-1965,KKH:703,OII:-2649},this.TC3__={AAA:-294,HHH:346,HHI:-341,HII:-1088,HIK:731,HOH:-1486,IHH:128,IHI:-3041,IHO:-1935,IIH:-825,IIM:-1035,IOI:-542,KHH:-1216,KKA:491,KKH:-1217,KOK:-1009,MHH:-2694,MHM:-457,MHO:123,MMH:-471,NNH:-1689,NNO:662,OHO:-3393},this.TC4__={HHH:-203,HHI:1344,HHK:365,HHM:-122,HHN:182,HHO:669,HIH:804,HII:679,HOH:446,IHH:695,IHO:-2324,IIH:321,III:1497,IIO:656,IOO:54,KAK:4845,KKA:3386,KKK:3065,MHH:-405,MHI:201,MMH:-241,MMM:661,MOM:841},this.TQ1__={BHHH:-227,BHHI:316,BHIH:-132,BIHH:60,BIII:1595,BNHH:-744,BOHH:225,BOOO:-908,OAKK:482,OHHH:281,OHIH:249,OIHI:200,OIIH:-68},this.TQ2__={BIHH:-1401,BIII:-1033,BKAK:-543,BOOO:-5591},this.TQ3__={BHHH:478,BHHM:-1073,BHIH:222,BHII:-504,BIIH:-116,BIII:-105,BMHI:-863,BMHM:-464,BOMH:620,OHHH:346,OHHI:1729,OHII:997,OHMH:481,OIHH:623,OIIH:1344,OKAK:2792,OKHH:587,OKKA:679,OOHH:110,OOII:-685},this.TQ4__={BHHH:-721,BHHM:-3604,BHII:-966,BIIH:-607,BIII:-2181,OAAA:-2763,OAKK:180,OHHH:-294,OHHI:2446,OHHO:480,OHIH:-1573,OIHH:1935,OIHI:-493,OIIH:626,OIII:-4007,OKAK:-8156},this.TW1__={"につい":-4681,"東京都":2026},this.TW2__={"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216},this.TW3__={"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287},this.TW4__={"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865},this.UC1__={A:484,K:93,M:645,O:-505},this.UC2__={A:819,H:1059,I:409,M:3987,N:5775,O:646},this.UC3__={A:-1370,I:2311},this.UC4__={A:-2643,H:1809,I:-1032,K:-3450,M:3565,N:3876,O:6646},this.UC5__={H:313,I:-1238,K:-799,M:539,O:-831},this.UC6__={H:-506,I:-253,K:87,M:247,O:-387},this.UP1__={O:-214},this.UP2__={B:69,O:935},this.UP3__={B:189},this.UQ1__={BH:21,BI:-12,BK:-99,BN:142,BO:-56,OH:-95,OI:477,OK:410,OO:-2422},this.UQ2__={BH:216,BI:113,OK:1759},this.UQ3__={BA:-479,BH:42,BI:1913,BK:-7198,BM:3160,BN:6427,BO:14761,OI:-827,ON:-3212},this.UW1__={",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135},this.UW2__={",":-829,"、":-829,"〇":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568},this.UW3__={",":4889,1:-800,"−":-1723,"、":4889,"々":-2311,"〇":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"1":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278},this.UW4__={",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"〇":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1e3,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637},this.UW5__={",":465,".":-299,1:-514,E2:-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"1":-514,"E2":-32768,"「":363,"イ":241,"ル":451,"ン":-343},this.UW6__={",":227,".":808,1:-270,E1:306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"1":-270,"E1":306,"ル":-673,"ン":-496},this}t.prototype.ctype_=function(_){for(var t in this.chartype_)if(_.match(this.chartype_[t][0]))return this.chartype_[t][1];return"O"},t.prototype.ts_=function(_){return _||0},t.prototype.segment=function(_){if(null==_||null==_||""==_)return[];var t=[],H=["B3","B2","B1"],s=["O","O","O"],h=_.split("");for(K=0;K0&&(t.push(i),i="",N="B"),I=O,O=B,B=N,i+=H[K]}return t.push(i),t},_.TinySegmenter=t}})); \ No newline at end of file diff --git a/public/assets/javascripts/vendor.93c04032.min.js b/public/assets/javascripts/vendor.93c04032.min.js new file mode 100644 index 0000000..22675f2 --- /dev/null +++ b/public/assets/javascripts/vendor.93c04032.min.js @@ -0,0 +1,16 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[1],[function(t,e,n){"use strict";n.d(e,"a",(function(){return i})),n.d(e,"b",(function(){return o}));var r=n(2);function i(t){return Object(r.a)(null==t?void 0:t.lift)}function o(t){return e=>{if(i(e))return e.lift((function(e){try{return t(e,this)}catch(t){this.error(t)}}));throw new TypeError("Unable to lift unknown Observable type")}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(16);class i extends r.b{constructor(t,e,n,r,i){super(t),this.onUnsubscribe=i,e&&(this._next=function(t){try{e(t)}catch(t){this.destination.error(t)}}),n&&(this._error=function(t){try{n(t)}catch(t){this.destination.error(t)}this.unsubscribe()}),r&&(this._complete=function(){try{r()}catch(t){this.destination.error(t)}this.unsubscribe()})}unsubscribe(){var t;!this.closed&&(null===(t=this.onUnsubscribe)||void 0===t||t.call(this)),super.unsubscribe()}}},function(t,e,n){"use strict";function r(t){return"function"==typeof t}n.d(e,"a",(function(){return r}))},,,function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(16),i=n(7),o=n(14),c=n(39),s=n(11),u=n(2);class a{constructor(t){t&&(this._subscribe=t)}lift(t){const e=new a;return e.source=this,e.operator=t,e}subscribe(t,e,n){const o=(c=t)&&c instanceof r.b||function(t){return t&&Object(u.a)(t.next)&&Object(u.a)(t.error)&&Object(u.a)(t.complete)}(c)&&Object(i.c)(c)?t:new r.a(t,e,n);var c;const{operator:a,source:l}=this;return o.add(a?a.call(o,l):l||s.a.useDeprecatedSynchronousErrorHandling?this._subscribe(o):this._trySubscribe(o)),o}_trySubscribe(t){try{return this._subscribe(t)}catch(e){if(s.a.useDeprecatedSynchronousErrorHandling)throw e;t.error(e)}}forEach(t,e){return new(e=l(e))((e,n)=>{let r;r=this.subscribe(e=>{try{t(e)}catch(t){n(t),null==r||r.unsubscribe()}},n,e)})}_subscribe(t){var e;return null===(e=this.source)||void 0===e?void 0:e.subscribe(t)}[o.a](){return this}pipe(...t){return t.length?Object(c.b)(t)(this):this}toPromise(t){return new(t=l(t))((t,e)=>{let n;this.subscribe(t=>n=t,t=>e(t),()=>t(n))})}}function l(t){var e;return null!==(e=null!=t?t:s.a.Promise)&&void 0!==e?e:Promise}a.create=t=>new a(t)},function(t,e,n){"use strict";n.d(e,"a",(function(){return g})),n.d(e,"c",(function(){return j})),n.d(e,"b",(function(){return O}));function r(t,e,n,r){return new(n||(n=Promise))((function(i,o){function c(t){try{u(r.next(t))}catch(t){o(t)}}function s(t){try{u(r.throw(t))}catch(t){o(t)}}function u(t){var e;t.done?i(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(c,s)}u((r=r.apply(t,e||[])).next())}))}Object.create;function i(t){var e="function"==typeof Symbol&&Symbol.iterator,n=e&&t[e],r=0;if(n)return n.call(t);if(t&&"number"==typeof t.length)return{next:function(){return t&&r>=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function o(t){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var e,n=t[Symbol.asyncIterator];return n?n.call(t):(t=i(t),e={},r("next"),r("throw"),r("return"),e[Symbol.asyncIterator]=function(){return this},e);function r(n){e[n]=t[n]&&function(e){return new Promise((function(r,i){(function(t,e,n,r){Promise.resolve(r).then((function(e){t({value:e,done:n})}),e)})(r,i,(e=t[n](e)).done,e.value)}))}}}Object.create;var c=n(17),s=n(2);function u(t){return Object(s.a)(null==t?void 0:t.then)}const a="function"==typeof Symbol&&Symbol.iterator?Symbol.iterator:"@@iterator";var l=n(14),d=n(5),f=n(7);var h=n(18);function b(t){return Object(s.a)(t[l.a])}function v(t){return Object(s.a)(null==t?void 0:t[a])}function p(t){return Symbol.asyncIterator&&Object(s.a)(null==t?void 0:t[Symbol.asyncIterator])}function m(t){return new TypeError(`You provided ${null!==t&&"object"==typeof t?"an invalid object":`'${t}'`} where a stream was expected. You can provide an Observable, Promise, Array, AsyncIterable, or Iterable.`)}function y(t,e){if(null!=t){if(b(t))return function(t,e){return new d.a(n=>{const r=new f.b;return r.add(e.schedule(()=>{const i=t[l.a]();r.add(i.subscribe({next(t){r.add(e.schedule(()=>n.next(t)))},error(t){r.add(e.schedule(()=>n.error(t)))},complete(){r.add(e.schedule(()=>n.complete()))}}))})),r})}(t,e);if(Object(c.a)(t))return Object(h.a)(t,e);if(u(t))return function(t,e){return new d.a(n=>e.schedule(()=>t.then(t=>{n.add(e.schedule(()=>{n.next(t),n.add(e.schedule(()=>n.complete()))}))},t=>{n.add(e.schedule(()=>n.error(t)))})))}(t,e);if(p(t))return function(t,e){if(!t)throw new Error("Iterable cannot be null");return new d.a(n=>{const r=new f.b;return r.add(e.schedule(()=>{const i=t[Symbol.asyncIterator]();r.add(e.schedule((function(){i.next().then(t=>{t.done?n.complete():(n.next(t.value),this.schedule())})})))})),r})}(t,e);if(v(t))return function(t,e){return new d.a(n=>{let r;return n.add(e.schedule(()=>{r=t[a](),function(t,e,n,r=0){const i=e.schedule((function(){try{n.call(this)}catch(e){t.error(e)}}),r);t.add(i)}(n,e,(function(){const{value:t,done:e}=r.next();e?n.complete():(n.next(t),this.schedule())}))})),()=>Object(s.a)(null==r?void 0:r.return)&&r.return()})}(t,e)}throw m(t)}var w=n(24);function g(t,e){return e?y(t,e):j(t)}function j(t){if(t instanceof d.a)return t;if(null!=t){if(b(t))return f=t,new d.a(t=>{const e=f[l.a]();if(Object(s.a)(e.subscribe))return e.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")});if(Object(c.a)(t))return O(t);if(u(t))return i=t,new d.a(t=>{i.then(e=>{t.closed||(t.next(e),t.complete())},e=>t.error(e)).then(null,w.a)});if(p(t))return n=t,new d.a(t=>{(function(t,e){var n,i,c,s;return r(this,void 0,void 0,(function*(){try{for(n=o(t);!(i=yield n.next()).done;){const t=i.value;e.next(t)}}catch(t){c={error:t}}finally{try{i&&!i.done&&(s=n.return)&&(yield s.call(n))}finally{if(c)throw c.error}}e.complete()}))})(n,t).catch(e=>t.error(e))});if(v(t))return e=t,new d.a(t=>{const n=e[a]();for(;!t.closed;){const{done:e,value:r}=n.next();e?t.complete():t.next(r)}return()=>Object(s.a)(null==n?void 0:n.return)&&n.return()})}var e,n,i,f;throw m(t)}function O(t){return new d.a(e=>{for(let n=0;nfunction(e){t(this),this.message=e?`${e.length} errors occurred during unsubscription:\n${e.map((t,e)=>`${e+1}) ${t.toString()}`).join("\n ")}`:"",this.name="UnsubscriptionError",this.errors=e});var c=n(12);class s{constructor(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._teardowns=null}unsubscribe(){let t;if(!this.closed){this.closed=!0;const{_parentage:e}=this;if(Array.isArray(e))for(const t of e)t.remove(this);else null==e||e.remove(this);const{initialTeardown:n}=this;if(Object(r.a)(n))try{n()}catch(e){t=e instanceof o?e.errors:[e]}const{_teardowns:i}=this;if(i){this._teardowns=null;for(const e of i)try{l(e)}catch(e){t=null!=t?t:[],e instanceof o?t=[...t,...e.errors]:t.push(e)}}if(t)throw new o(t)}}add(t){var e;if(t&&t!==this)if(this.closed)l(t);else{if(t instanceof s){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._teardowns=null!==(e=this._teardowns)&&void 0!==e?e:[]).push(t)}}_hasParent(t){const{_parentage:e}=this;return e===t||Array.isArray(e)&&e.includes(t)}_addParent(t){const{_parentage:e}=this;this._parentage=Array.isArray(e)?(e.push(t),e):e?[e,t]:t}_removeParent(t){const{_parentage:e}=this;e===t?this._parentage=null:Array.isArray(e)&&Object(c.a)(e,t)}remove(t){const{_teardowns:e}=this;e&&Object(c.a)(e,t),t instanceof s&&t._removeParent(this)}}s.EMPTY=(()=>{const t=new s;return t.closed=!0,t})();const u=s.EMPTY;function a(t){return t instanceof s||t&&"closed"in t&&Object(r.a)(t.remove)&&Object(r.a)(t.add)&&Object(r.a)(t.unsubscribe)}function l(t){Object(r.a)(t)?t():t.unsubscribe()}},function(t,e,n){"use strict";n.d(e,"b",(function(){return c})),n.d(e,"c",(function(){return s})),n.d(e,"a",(function(){return u}));var r=n(2),i=n(29);function o(t){return t[t.length-1]}function c(t){return Object(r.a)(o(t))?t.pop():void 0}function s(t){return Object(i.a)(o(t))?t.pop():void 0}function u(t,e){return"number"==typeof o(t)?t.pop():e}},function(t,e,n){"use strict";function r(){}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";function r(t){return t}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1}},function(t,e,n){"use strict";function r(t,e){if(t){const n=t.indexOf(e);0<=n&&t.splice(n,1)}}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";n.d(e,"a",(function(){return u}));var r=n(28),i=n(6),o=n(0),c=n(1);var s=n(2);function u(t,e,n=1/0){return Object(s.a)(e)?u((n,o)=>Object(r.a)((t,r)=>e(n,t,o,r))(Object(i.c)(t(n,o))),n):("number"==typeof e&&(n=e),Object(o.b)((e,r)=>function(t,e,n,r,o,s,u,a){let l=[],d=0,f=0,h=!1;const b=()=>{!h||l.length||d||e.complete()},v=t=>d{s&&e.next(t),d++,Object(i.c)(n(t,f++)).subscribe(new c.a(e,t=>{null==o||o(t),s?v(t):e.next(t)},void 0,()=>{for(d--;l.length&&dp(t))):p(t)}b()}))};return t.subscribe(new c.a(e,v,void 0,()=>{h=!0,b()})),()=>{l=null,null==a||a()}}(e,r,t,n)))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r="function"==typeof Symbol&&Symbol.observable||"@@observable"},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(18),i=n(6);function o(t,e){return e?Object(r.a)(t,e):Object(i.b)(t)}},function(t,e,n){"use strict";n.d(e,"b",(function(){return d})),n.d(e,"a",(function(){return f}));var r=n(2),i=n(7),o=n(11),c=n(24),s=n(9);const u=a("C",void 0,void 0);function a(t,e,n){return{kind:t,value:e,error:n}}var l=n(25);class d extends i.b{constructor(t){super(),this.isStopped=!1,t?(this.destination=t,Object(i.c)(t)&&t.add(this)):this.destination=v}static create(t,e,n){return new f(t,e,n)}next(t){this.isStopped?b(function(t){return a("N",t,void 0)}(t),this):this._next(t)}error(t){this.isStopped?b(a("E",void 0,t),this):(this.isStopped=!0,this._error(t))}complete(){this.isStopped?b(u,this):(this.isStopped=!0,this._complete())}unsubscribe(){this.closed||(this.isStopped=!0,super.unsubscribe())}_next(t){this.destination.next(t)}_error(t){this.destination.error(t),this.unsubscribe()}_complete(){this.destination.complete(),this.unsubscribe()}}class f extends d{constructor(t,e,n){if(super(),this.destination=v,(t||e||n)&&t!==v){let i;if(Object(r.a)(t))i=t;else if(t){let r;({next:i,error:e,complete:n}=t),this&&o.a.useDeprecatedNextContext?(r=Object.create(t),r.unsubscribe=()=>this.unsubscribe()):r=t,i=null==i?void 0:i.bind(r),e=null==e?void 0:e.bind(r),n=null==n?void 0:n.bind(r)}this.destination={next:i||s.a,error:e||h,complete:n||s.a}}}}function h(t){if(o.a.useDeprecatedSynchronousErrorHandling)throw t;Object(c.a)(t)}function b(t,e){const{onStoppedNotification:n}=o.a;n&&l.a.setTimeout(()=>n(t,e))}const v={closed:!0,next:s.a,error:h,complete:s.a}},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r=t=>t&&"number"==typeof t.length&&"function"!=typeof t},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(5);function i(t,e){return new r.a(n=>{let r=0;return e.schedule((function(){r===t.length?n.complete():(n.next(t[r++]),n.closed||this.schedule())}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(5);const i=new r.a(t=>t.complete())},function(t,e,n){"use strict";n.d(e,"b",(function(){return i})),n.d(e,"a",(function(){return o}));var r=n(32);const i=new(n(34).a)(r.a),o=i},function(t,e,n){"use strict";n.d(e,"a",(function(){return u}));var r=n(5),i=n(7),o=n(23);const c=Object(o.a)(t=>function(){t(this),this.name="ObjectUnsubscribedError",this.message="object unsubscribed"});var s=n(12);class u extends r.a{constructor(){super(),this.observers=[],this.closed=!1,this.isStopped=!1,this.hasError=!1,this.thrownError=null}lift(t){const e=new a(this,this);return e.operator=t,e}_throwIfClosed(){if(this.closed)throw new c}next(t){if(this._throwIfClosed(),!this.isStopped){const e=this.observers.slice();for(const n of e)n.next(t)}}error(t){if(this._throwIfClosed(),!this.isStopped){this.hasError=this.isStopped=!0,this.thrownError=t;const{observers:e}=this;for(;e.length;)e.shift().error(t)}}complete(){if(this._throwIfClosed(),!this.isStopped){this.isStopped=!0;const{observers:t}=this;for(;t.length;)t.shift().complete()}}unsubscribe(){this.isStopped=this.closed=!0,this.observers=null}_trySubscribe(t){return this._throwIfClosed(),super._trySubscribe(t)}_subscribe(t){return this._throwIfClosed(),this._checkFinalizedStatuses(t),this._innerSubscribe(t)}_innerSubscribe(t){const{hasError:e,isStopped:n,observers:r}=this;return e||n?i.a:(r.push(t),new i.b(()=>Object(s.a)(this.observers,t)))}_checkFinalizedStatuses(t){const{hasError:e,thrownError:n,isStopped:r}=this;e?t.error(n):r&&t.complete()}asObservable(){const t=new r.a;return t.source=this,t}}u.create=(t,e)=>new a(t,e);class a extends u{constructor(t,e){super(),this.destination=t,this.source=e}next(t){var e,n;null===(n=null===(e=this.destination)||void 0===e?void 0:e.next)||void 0===n||n.call(e,t)}error(t){var e,n;null===(n=null===(e=this.destination)||void 0===e?void 0:e.error)||void 0===n||n.call(e,t)}complete(){var t,e;null===(e=null===(t=this.destination)||void 0===t?void 0:t.complete)||void 0===e||e.call(t)}_subscribe(t){var e,n;return null!==(n=null===(e=this.source)||void 0===e?void 0:e.subscribe(t))&&void 0!==n?n:i.a}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(31);var i=n(15),o=n(8);function c(...t){return Object(r.a)(1)(Object(i.a)(t,Object(o.c)(t)))}},function(t,e,n){"use strict";function r(t){const e=t(t=>{Error.call(t),t.stack=(new Error).stack});return e.prototype=Object.create(Error.prototype),e.prototype.constructor=e,e}n.d(e,"a",(function(){return r}))},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(11),i=n(25);function o(t){i.a.setTimeout(()=>{const{onUnhandledError:e}=r.a;if(!e)throw t;e(t)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r={setTimeout(...t){const{delegate:e}=r;return((null==e?void 0:e.setTimeout)||setTimeout)(...t)},clearTimeout(t){const{delegate:e}=r;return((null==e?void 0:e.clearTimeout)||clearTimeout)(t)},delegate:void 0}},function(t,e,n){"use strict";n.d(e,"a",(function(){return r}));const r={now:()=>(r.delegate||Date).now(),delegate:void 0}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(28);const{isArray:i}=Array;function o(t){return Object(r.a)(e=>function(t,e){return i(e)?t(...e):t(e)}(t,e))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t,e){return Object(r.b)((n,r)=>{let o=0;n.subscribe(new i.a(r,n=>{r.next(t.call(e,n,o++))}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(2);function i(t){return t&&Object(r.a)(t.schedule)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));const{isArray:r}=Array;function i(t){return 1===t.length&&r(t[0])?t[0]:t}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(13),i=n(10);function o(t=1/0){return Object(r.a)(i.a,t)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(7);class i extends r.b{constructor(t,e){super()}schedule(t,e=0){return this}}const o={setInterval(...t){const{delegate:e}=o;return((null==e?void 0:e.setInterval)||setInterval)(...t)},clearInterval(t){const{delegate:e}=o;return((null==e?void 0:e.clearInterval)||clearInterval)(t)},delegate:void 0};var c=n(12);class s extends i{constructor(t,e){super(t,e),this.scheduler=t,this.work=e,this.pending=!1}schedule(t,e=0){if(this.closed)return this;this.state=t;const n=this.id,r=this.scheduler;return null!=n&&(this.id=this.recycleAsyncId(r,n,e)),this.pending=!0,this.delay=e,this.id=this.id||this.requestAsyncId(r,this.id,e),this}requestAsyncId(t,e,n=0){return o.setInterval(t.flush.bind(t,this),n)}recycleAsyncId(t,e,n=0){if(null!=n&&this.delay===n&&!1===this.pending)return e;o.clearInterval(e)}execute(t,e){if(this.closed)return new Error("executing a cancelled action");this.pending=!1;const n=this._execute(t,e);if(n)return n;!1===this.pending&&null!=this.id&&(this.id=this.recycleAsyncId(this.scheduler,this.id,null))}_execute(t,e){let n,r=!1;try{this.work(t)}catch(t){r=!0,n=!!t&&t||new Error(t)}if(r)return this.unsubscribe(),n}unsubscribe(){if(!this.closed){const{id:t,scheduler:e}=this,{actions:n}=e;this.work=this.state=this.scheduler=null,this.pending=!1,Object(c.a)(n,this),null!=t&&(this.id=this.recycleAsyncId(e,t,null)),this.delay=null,super.unsubscribe()}}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(5),i=n(20),o=n(29);function c(t=0,e,n=i.a){let c=-1;return null!=e&&(Object(o.a)(e)?n=e:c=e),new r.a(e=>{let r=(i=t)instanceof Date&&!isNaN(i)?+t-n.now():t;var i;r<0&&(r=0);let o=0;return n.schedule((function(){e.closed||(e.next(o++),0<=c?this.schedule(void 0,c):e.complete())}),r)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(26);class i{constructor(t,e=i.now){this.schedulerActionCtor=t,this.now=e}schedule(t,e=0,n){return new this.schedulerActionCtor(this,t).schedule(n,e)}}i.now=r.a.now;class o extends i{constructor(t,e=i.now){super(t,e),this.actions=[],this.active=!1,this.scheduled=void 0}flush(t){const{actions:e}=this;if(this.active)return void e.push(t);let n;this.active=!0;do{if(n=t.execute(t.state,t.delay))break}while(t=e.shift());if(this.active=!1,n){for(;t=e.shift();)t.unsubscribe();throw n}}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(6),i=n(0),o=n(1);function c(t,e){return Object(i.b)((n,i)=>{let c=null,s=0,u=!1;const a=()=>u&&!c&&i.complete();n.subscribe(new o.a(i,n=>{null==c||c.unsubscribe();let u=0;const l=s++;Object(r.c)(t(n,l)).subscribe(c=new o.a(i,t=>i.next(e?e(n,t,l,u++):t),void 0,()=>{c=null,a()}))},void 0,()=>{u=!0,a()}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(19),i=n(0),o=n(1);function c(t){return t<=0?()=>r.a:Object(i.b)((e,n)=>{let r=0;e.subscribe(new o.a(n,e=>{++r<=t&&(n.next(e),t<=r&&n.complete())}))})}},function(t,e,n){ +/*! + * clipboard.js v2.0.6 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +var r;r=function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=6)}([function(t,e){t.exports=function(t){var e;if("SELECT"===t.nodeName)t.focus(),e=t.value;else if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName){var n=t.hasAttribute("readonly");n||t.setAttribute("readonly",""),t.select(),t.setSelectionRange(0,t.value.length),n||t.removeAttribute("readonly"),e=t.value}else{t.hasAttribute("contenteditable")&&t.focus();var r=window.getSelection(),i=document.createRange();i.selectNodeContents(t),r.removeAllRanges(),r.addRange(i),e=r.toString()}return e}},function(t,e){function n(){}n.prototype={on:function(t,e,n){var r=this.e||(this.e={});return(r[t]||(r[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var r=this;function i(){r.off(t,i),e.apply(n,arguments)}return i._=e,this.on(t,i,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),r=0,i=n.length;r0&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.container=t.container,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function(){var t=this,e="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[e?"right":"left"]="-9999px";var n=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=n+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=i()(this.fakeElem),this.copyText()}},{key:"removeFake",value:function(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function(){this.selectedText=i()(this.target),this.copyText()}},{key:"copyText",value:function(){var t=void 0;try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)}},{key:"handleResult",value:function(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function(){this.trigger&&this.trigger.focus(),document.activeElement.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function(){this.removeFake()}},{key:"action",set:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function(){return this._action}},{key:"target",set:function(t){if(void 0!==t){if(!t||"object"!==(void 0===t?"undefined":o(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function(){return this._target}}]),t}(),u=n(1),a=n.n(u),l=n(2),d=n.n(l),f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},h=function(){function t(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText,this.container="object"===f(t.container)?t.container:document.body}},{key:"listenClick",value:function(t){var e=this;this.listener=d()(t,"click",(function(t){return e.onClick(t)}))}},{key:"onClick",value:function(t){var e=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new s({action:this.action(e),target:this.target(e),text:this.text(e),container:this.container,trigger:e,emitter:this})}},{key:"defaultAction",value:function(t){return v("action",t)}},{key:"defaultTarget",value:function(t){var e=v("target",t);if(e)return document.querySelector(e)}},{key:"defaultText",value:function(t){return v("text",t)}},{key:"destroy",value:function(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],e="string"==typeof t?[t]:t,n=!!document.queryCommandSupported;return e.forEach((function(t){n=n&&!!document.queryCommandSupported(t)})),n}}]),e}(a.a);function v(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}e.default=b}]).default},t.exports=r()},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(21),i=n(26);class o extends r.a{constructor(t=1/0,e=1/0,n=i.a){super(),this.bufferSize=t,this.windowTime=e,this.timestampProvider=n,this.buffer=[],this.infiniteTimeWindow=!0,this.infiniteTimeWindow=e===1/0,this.bufferSize=Math.max(1,t),this.windowTime=Math.max(1,e)}next(t){const{isStopped:e,buffer:n,infiniteTimeWindow:r,timestampProvider:i,windowTime:o}=this;e||(n.push(t),!r&&n.push(i.now()+o)),this.trimBuffer(),super.next(t)}_subscribe(t){this._throwIfClosed(),this.trimBuffer();const e=this._innerSubscribe(t),{infiniteTimeWindow:n,buffer:r}=this,i=r.slice();for(let e=0;ee(t),e)}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t){return Object(r.b)((e,n)=>{e.subscribe(new i.a(n,()=>n.next(t)))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(5),i=n(6);function o(t){return new r.a(e=>{Object(i.c)(t()).subscribe(e)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t,e){return Object(r.b)((n,r)=>{let o=0;n.subscribe(new i.a(r,n=>t.call(e,n,o++)&&r.next(n)))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t,e){return t=null!=t?t:c,Object(r.b)((n,r)=>{let o,c=!0;n.subscribe(new i.a(r,n=>{(c&&(o=n,1)||!t(o,o=e?e(n):n))&&r.next(n),c=!1}))})}function c(t,e){return t===e}},function(t,e,n){"use strict"; +/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var r=/["'&<>]/;t.exports=function(t){var e,n=""+t,i=r.exec(n);if(!i)return n;var o="",c=0,s=0;for(c=i.index;ci=>t[r](e,i,n)):function(t){return Object(c.a)(t.addListener)&&Object(c.a)(t.removeListener)}(t)?a.map(h(t,e)):function(t){return Object(c.a)(t.on)&&Object(c.a)(t.off)}(t)?d.map(h(t,e)):[];return!v&&Object(o.a)(t)?Object(i.a)(t=>f(t,e,n))(Object(u.a)(t)):new r.a(t=>{if(!v)throw new TypeError("Invalid event target");const e=(...e)=>t.next(1p(e)})}function h(t,e){return n=>r=>t[n](e,r)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(31),i=n(15),o=n(30),c=n(6),s=n(19),u=n(8);function a(...t){const e=Object(u.c)(t),n=Object(u.a)(t,1/0),a=Object(o.a)(t);return a.length?1===a.length?Object(c.c)(a[0]):Object(r.a)(n)(Object(i.a)(a,e)):s.a}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(22),i=n(8),o=n(0);function c(...t){const e=Object(i.c)(t);return Object(o.b)((n,i)=>{(e?Object(r.a)(t,n,e):Object(r.a)(t,n)).subscribe(i)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(15),i=n(18),o=n(8);function c(...t){const e=Object(o.c)(t);return e?Object(i.a)(t,e):Object(r.a)(t)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(5),i=n(9);const o=new r.a(i.a)},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(0);function i(t){return Object(r.b)((e,n)=>{e.subscribe(n),n.add(t)})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(38),i=n(0);function o(t,e,n){let o;return o=t&&"object"==typeof t?t:{bufferSize:t,windowTime:e,refCount:!1,scheduler:n},Object(i.b)(function({bufferSize:t=1/0,windowTime:e=1/0,refCount:n,scheduler:i}){let o,c,s=0;return(u,a)=>{let l;s++,o?l=o.subscribe(a):(o=new r.a(t,e,i),l=o.subscribe(a),c=u.subscribe({next(t){o.next(t)},error(t){const e=o;c=void 0,o=void 0,e.error(t)},complete(){c=void 0,o.complete()}}),c.closed&&(c=void 0)),a.add(()=>{s--,l.unsubscribe(),n&&0===s&&c&&(c.unsubscribe(),c=void 0,o=void 0)})}}(o))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(2),i=n(0),o=n(1),c=n(10);function s(t,e,n){const s=Object(r.a)(t)||e||n?{next:t,error:e,complete:n}:t;return s?Object(i.b)((t,e)=>{t.subscribe(new o.a(e,t=>{var n;null===(n=s.next)||void 0===n||n.call(s,t),e.next(t)},t=>{var n;null===(n=s.error)||void 0===n||n.call(s,t),e.error(t)},()=>{var t;null===(t=s.complete)||void 0===t||t.call(s),e.complete()}))}):c.a}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(21);class i extends r.a{constructor(t){super(),this._value=t}get value(){return this.getValue()}_subscribe(t){const e=super._subscribe(t);return!e.closed&&t.next(this._value),e}getValue(){const{hasError:t,thrownError:e,_value:n}=this;if(t)throw e;return this._throwIfClosed(),n}next(t){super.next(this._value=t)}}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(43);function i(t,e){return Object(r.a)((n,r)=>e?e(n[t],r[t]):n[t]===r[t])}},function(t,e,n){"use strict";n.d(e,"a",(function(){return s}));var r=n(0),i=n(1),o=n(6);const c={leading:!0,trailing:!1};function s(t,{leading:e,trailing:n}=c){return Object(r.b)((r,c)=>{let s=!1,u=null,a=null,l=!1;const d=()=>{null==a||a.unsubscribe(),a=null,n&&(b(),l&&c.complete())},f=()=>{a=null,l&&c.complete()},h=e=>a=Object(o.c)(t(e)).subscribe(new i.a(c,d,void 0,f)),b=()=>{s&&(c.next(u),!l&&h(u)),s=!1,u=null};r.subscribe(new i.a(c,t=>{s=!0,u=t,(!a||a.closed)&&(e?b():h(t))},void 0,()=>{l=!0,(!(n&&s&&a)||a.closed)&&c.complete()}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(35);function i(t,e){return e?Object(r.a)(()=>t,e):Object(r.a)(()=>t)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t,e=0){return Object(r.b)((n,r)=>{n.subscribe(new i.a(r,n=>r.add(t.schedule(()=>r.next(n),e)),n=>r.add(t.schedule(()=>r.error(n),e)),()=>r.add(t.schedule(()=>r.complete(),e))))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(0),i=n(1),o=n(6),c=n(10),s=n(9),u=n(8);function a(...t){const e=Object(u.b)(t);return Object(r.b)((n,r)=>{const u=t.length,a=new Array(u);let l=t.map(()=>!1),d=!1;for(let e=0;e{a[e]=t,d||l[e]||(l[e]=!0,(d=l.every(c.a))&&(l=null))},void 0,s.a));n.subscribe(new i.a(r,t=>{if(d){const n=[t,...a];r.next(e?e(...n):n)}}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(0),i=n(9),o=n(1);function c(t){return Object(r.b)((e,n)=>{let r=!1,c=null;e.subscribe(new o.a(n,t=>{r=!0,c=t}));t.subscribe(new o.a(n,()=>{if(r){r=!1;const t=c;c=null,n.next(t)}},void 0,i.a))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(42);function i(t){return Object(r.a)((e,n)=>t<=n)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(6),i=n(1),o=n(0);function c(t){return Object(o.b)((e,n)=>{let o,s=null,u=!1;s=e.subscribe(new i.a(n,void 0,i=>{o=Object(r.c)(t(i,c(t)(e))),s?(s.unsubscribe(),s=null,o.subscribe(n)):u=!0})),u&&(s.unsubscribe(),s=null,o.subscribe(n))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return c}));var r=n(0),i=n(1),o=n(12);function c(t,e=null){return e=null!=e?e:t,Object(r.b)((n,r)=>{let c=[],s=0;n.subscribe(new i.a(r,n=>{let i=null;s++%e==0&&c.push([]);for(const e of c)e.push(n),t<=e.length&&(i=null!=i?i:[],i.push(e));if(i)for(const t of i)Object(o.a)(c,t),r.next(t)},void 0,()=>{for(const t of c)r.next(t);r.complete()},()=>{c=null}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(13),i=n(2);function o(t,e){return Object(i.a)(e)?Object(r.a)(t,e,1):Object(r.a)(t,1)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));var r=n(41);function i(t,e,n){return Object(r.a)(()=>t()?e:n)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));var r=n(0),i=n(1);function o(t=null){return Object(r.b)((e,n)=>{let r=!1;e.subscribe(new i.a(n,t=>{r=!0,n.next(t)},void 0,()=>{r||n.next(t),n.complete()}))})}},function(t,e,n){"use strict";n.d(e,"a",(function(){return f}));var r=n(5),i=n(7),o=n(0),c=n(1);function s(){return Object(o.b)((t,e)=>{let n=null;t._refCount++;const r=new c.a(e,void 0,void 0,void 0,()=>{if(!t||t._refCount<=0||0<--t._refCount)return void(n=null);const r=t._connection,i=n;n=null,!r||i&&r!==i||r.unsubscribe(),e.unsubscribe()});t.subscribe(r),r.closed||(n=t.connect())})}class u extends r.a{constructor(t,e){super(),this.source=t,this.subjectFactory=e,this._subject=null,this._refCount=0,this._connection=null}_subscribe(t){return this.getSubject().subscribe(t)}getSubject(){const t=this._subject;return t&&!t.isStopped||(this._subject=this.subjectFactory()),this._subject}_teardown(){this._refCount=0;const{_connection:t}=this;this._subject=this._connection=null,null==t||t.unsubscribe()}connect(){let t=this._connection;if(!t){t=this._connection=new i.b;const e=this.getSubject();t.add(this.source.subscribe(new c.a(e,void 0,t=>{this._teardown(),e.error(t)},()=>{this._teardown(),e.complete()},()=>this._teardown()))),t.closed&&(this._connection=null,t=i.b.EMPTY)}return t}refCount(){return s()(this)}}var a=n(2);var l=n(21);function d(){return new l.a}function f(){return t=>s()(function(t,e){const n=Object(a.a)(t)?t:()=>t;return Object(a.a)(e)?Object(o.b)((t,r)=>{const i=n();e(i).subscribe(r).add(t.subscribe(i))}):t=>{const e=new u(t,n);return Object(o.a)(t)&&(e.lift=t.lift),e.source=t,e.subjectFactory=n,e}}(d)(t))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(32),i=n(7);const o={schedule(t){let e=requestAnimationFrame,n=cancelAnimationFrame;const{delegate:r}=o;r&&(e=r.requestAnimationFrame,n=r.cancelAnimationFrame);const c=e(e=>{n=void 0,t(e)});return new i.b(()=>null==n?void 0:n(c))},requestAnimationFrame(...t){const{delegate:e}=o;return((null==e?void 0:e.requestAnimationFrame)||requestAnimationFrame)(...t)},cancelAnimationFrame(...t){const{delegate:e}=o;return((null==e?void 0:e.cancelAnimationFrame)||cancelAnimationFrame)(...t)},delegate:void 0};class c extends r.a{constructor(t,e){super(t,e),this.scheduler=t,this.work=e}requestAsyncId(t,e,n=0){return null!==n&&n>0?super.requestAsyncId(t,e,n):(t.actions.push(this),t.scheduled||(t.scheduled=o.requestAnimationFrame(()=>t.flush(void 0))))}recycleAsyncId(t,e,n=0){if(null!=n&&n>0||null==n&&this.delay>0)return super.recycleAsyncId(t,e,n);0===t.actions.length&&(o.cancelAnimationFrame(e),t.scheduled=void 0)}}var s=n(34);class u extends s.a{flush(t){this.active=!0,this.scheduled=void 0;const{actions:e}=this;let n,r=-1;t=t||e.shift();const i=e.length;do{if(n=t.execute(t.state,t.delay))break}while(++rObject(i.a)(e.pipe(Object(o.a)(1),Object(c.b)((t,e)=>{t.subscribe(new s.a(e,u.a))})),n.pipe(d(t))):Object(l.a)((e,n)=>t(e,n).pipe(Object(o.a)(1),Object(a.a)(e)))}var f=n(33);function h(t,e=r.b){const n=Object(f.a)(t,e);return d(()=>n)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return b}));var r=n(5);const{isArray:i}=Array,{getPrototypeOf:o,prototype:c,keys:s}=Object;function u(t){if(1===t.length){const n=t[0];if(i(n))return{args:n,keys:null};if((e=n)&&"object"==typeof e&&o(e)===c){const t=s(n);return{args:t.map(t=>n[t]),keys:t}}}var e;return{args:t,keys:null}}var a=n(16),l=n(6),d=n(10),f=n(27),h=n(8);function b(...t){const e=Object(h.c)(t),n=Object(h.b)(t),{args:i,keys:o}=u(t),c=new r.a(function(t,e,n=d.a){return r=>{p(e,()=>{const{length:i}=t,o=new Array(i);let c=i;const s=t.map(()=>!1);let u=!0;for(let a=0;a{Object(l.a)(t[a],e).subscribe(new v(r,t=>{o[a]=t,u&&(s[a]=!0,u=!s.every(d.a)),u||r.next(n(o.slice()))},()=>0==--c))},r)}},r)}}(i,e,o?t=>{const e={};for(let n=0;n{let u=n,a=e,l=0;c.subscribe(new i.a(s,e=>{const n=l++;a=u?t(a,e,n):(u=!0,e),r&&s.next(a)},void 0,o&&(()=>{u&&s.next(a),s.complete()})))}}function c(t,e){return Object(r.b)(o(t,e,arguments.length>=2,!0))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return d}));var r=n(5),i=n(6),o=n(30),c=n(19),s=n(1),u=n(8);var a=n(0);function l(...t){return Object(a.b)((e,n)=>{(function(...t){const e=Object(u.b)(t),n=Object(o.a)(t);return n.length?new r.a(t=>{let r=n.map(()=>[]),o=n.map(()=>!1);t.add(()=>{r=o=null});for(let c=0;!t.closed&&c{if(r[c].push(n),r.every(t=>t.length)){const n=r.map(t=>t.shift());t.next(e?e(...n):n),r.some((t,e)=>!t.length&&o[e])&&t.complete()}},void 0,()=>{o[c]=!0,!r[c].length&&t.complete()}));return()=>{r=o=null}}):c.a})(e,...t).subscribe(n)})}function d(...t){return l(...t)}},function(t,e,n){"use strict";n.d(e,"a",(function(){return a}));var r=n(20),i=n(0),o=n(9),c=n(1),s=n(6);var u=n(33);function a(t,e=r.b){const n=Object(u.a)(t,e);return a=()=>n,Object(i.b)((t,e)=>{let n=!1,r=null,i=null;const u=()=>{if(null==i||i.unsubscribe(),i=null,n){n=!1;const t=r;r=null,e.next(t)}};t.subscribe(new c.a(e,t=>{null==i||i.unsubscribe(),n=!0,r=t,i=new c.a(e,u,void 0,o.a),Object(s.c)(a(t)).subscribe(i)},void 0,()=>{u(),e.complete()},()=>{r=i=null}))});var a}}]]); +//# sourceMappingURL=vendor.93c04032.min.js.map \ No newline at end of file diff --git a/public/assets/javascripts/vendor.93c04032.min.js.map b/public/assets/javascripts/vendor.93c04032.min.js.map new file mode 100644 index 0000000..f8b7a8c --- /dev/null +++ b/public/assets/javascripts/vendor.93c04032.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./node_modules/rxjs/dist/esm/internal/util/lift.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/OperatorSubscriber.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isFunction.js","webpack:///./node_modules/rxjs/dist/esm/internal/Observable.js","webpack:///./node_modules/tslib/tslib.es6.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isPromise.js","webpack:///./node_modules/rxjs/dist/esm/internal/symbol/iterator.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isInteropObservable.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isIterable.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isAsyncIterable.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/throwUnobservableError.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduled.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduleObservable.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/schedulePromise.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduleAsyncIterable.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduleIterable.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/caughtSchedule.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/from.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/UnsubscriptionError.js","webpack:///./node_modules/rxjs/dist/esm/internal/Subscription.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/args.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/noop.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/identity.js","webpack:///./node_modules/rxjs/dist/esm/internal/config.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/arrRemove.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/mergeMap.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/mergeInternals.js","webpack:///./node_modules/rxjs/dist/esm/internal/symbol/observable.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/fromArray.js","webpack:///./node_modules/rxjs/dist/esm/internal/NotificationFactories.js","webpack:///./node_modules/rxjs/dist/esm/internal/Subscriber.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isArrayLike.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduled/scheduleArray.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/empty.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/async.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/ObjectUnsubscribedError.js","webpack:///./node_modules/rxjs/dist/esm/internal/Subject.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/concat.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/concatAll.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/createErrorClass.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/reportUnhandledError.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/timeoutProvider.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/dateTimestampProvider.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/mapOneOrManyArgs.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/map.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isScheduler.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/argsOrArgArray.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/mergeAll.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/Action.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/intervalProvider.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/AsyncAction.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/timer.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/isDate.js","webpack:///./node_modules/rxjs/dist/esm/internal/Scheduler.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/AsyncScheduler.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/switchMap.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/take.js","webpack:///./node_modules/clipboard/dist/clipboard.js","webpack:///./node_modules/rxjs/dist/esm/internal/ReplaySubject.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/pipe.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/mapTo.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/defer.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/filter.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/distinctUntilChanged.js","webpack:///./node_modules/escape-html/index.js","webpack:///./node_modules/focus-visible/dist/focus-visible.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/fromEvent.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/merge.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/startWith.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/of.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/never.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/finalize.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/shareReplay.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/tap.js","webpack:///./node_modules/rxjs/dist/esm/internal/BehaviorSubject.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/distinctUntilKeyChanged.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/throttle.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/switchMapTo.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/observeOn.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/withLatestFrom.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/sample.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/skip.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/catchError.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/bufferCount.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/concatMap.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/iif.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/defaultIfEmpty.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/refCount.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/ConnectableObservable.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/share.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/multicast.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/animationFrameProvider.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/AnimationFrameAction.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/AnimationFrameScheduler.js","webpack:///./node_modules/rxjs/dist/esm/internal/scheduler/animationFrame.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/delayWhen.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/ignoreElements.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/delay.js","webpack:///./node_modules/rxjs/dist/esm/internal/util/argsArgArrayOrObject.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/combineLatest.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/scanInternals.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/scan.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/zipWith.js","webpack:///./node_modules/rxjs/dist/esm/internal/observable/zip.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/debounceTime.js","webpack:///./node_modules/rxjs/dist/esm/internal/operators/debounce.js"],"names":["hasLift","source","lift","operate","init","liftedSource","this","err","error","TypeError","OperatorSubscriber","destination","onNext","onError","onComplete","onUnsubscribe","super","_next","value","_error","unsubscribe","_complete","_a","closed","call","isFunction","Observable","subscribe","_subscribe","operator","observable","observerOrNext","complete","subscriber","next","isObserver","add","useDeprecatedSynchronousErrorHandling","_trySubscribe","sink","promiseCtor","getPromiseCtor","resolve","reject","subscription","operations","length","x","Promise","create","__awaiter","thisArg","_arguments","P","generator","fulfilled","step","e","rejected","result","done","then","apply","Object","__values","o","s","Symbol","iterator","m","i","__asyncValues","asyncIterator","verb","n","v","d","settle","isPromise","isInteropObservable","input","isIterable","isAsyncIterable","obj","createInvalidObservableTypeError","scheduled","scheduler","sub","Subscription","schedule","scheduleObservable","isArrayLike","scheduleArray","schedulePromise","Error","scheduleAsyncIterable","execute","delay","caughtSchedule","return","scheduleIterable","from","innerFrom","obs","fromArrayLike","promise","reportUnhandledError","asyncIterable","asyncIterable_1","asyncIterable_1_1","e_1","e_1_1","process","catch","iterable","array","UnsubscriptionError","createErrorClass","_super","errors","message","map","toString","join","name","initialTeardown","_parentage","_teardowns","Array","isArray","parent","remove","teardown","execTeardown","push","_hasParent","_addParent","includes","arrRemove","_removeParent","EMPTY","empty","EMPTY_SUBSCRIPTION","isSubscription","last","arr","popResultSelector","args","pop","undefined","popScheduler","popNumber","defaultValue","noop","identity","config","onUnhandledError","onStoppedNotification","useDeprecatedNextContext","item","index","indexOf","splice","mergeMap","project","resultSelector","concurrent","Infinity","a","b","ii","onBeforeNext","expand","innerSubScheduler","additionalTeardown","buffer","active","isComplete","checkComplete","outerNext","doInnerSub","innerValue","bufferedValue","shift","mergeInternals","internalFromArray","COMPLETE_NOTIFICATION","createNotification","kind","isStopped","EMPTY_OBSERVER","handleStoppedNotification","nextNotification","context","bind","defaultErrorHandler","notification","timeoutProvider","setTimeout","asyncScheduler","async","ObjectUnsubscribedError","observers","hasError","thrownError","subject","_throwIfClosed","copy","slice","observer","_checkFinalizedStatuses","_innerSubscribe","_b","concat","mergeAll","concatAll","createImpl","ctorFunc","instance","stack","prototype","constructor","delegate","handle","clearTimeout","dateTimestampProvider","now","Date","mapOneOrManyArgs","fn","callOrApply","isScheduler","argsOrArgArray","work","state","intervalProvider","setInterval","clearInterval","pending","id","recycleAsyncId","requestAsyncId","_id","flush","_scheduler","_execute","_delay","errorValue","errored","actions","timer","dueTime","intervalOrScheduler","intervalDuration","due","isNaN","Scheduler","schedulerActionCtor","SchedulerAction","action","switchMap","innerSubscriber","innerIndex","outerIndex","take","count","seen","factory","modules","installedModules","__webpack_require__","moduleId","exports","module","l","c","getter","defineProperty","enumerable","get","r","toStringTag","t","mode","__esModule","ns","key","object","property","hasOwnProperty","p","element","selectedText","nodeName","focus","isReadOnly","hasAttribute","setAttribute","select","setSelectionRange","removeAttribute","selection","window","getSelection","range","document","createRange","selectNodeContents","removeAllRanges","addRange","E","on","callback","ctx","once","self","listener","off","arguments","_","emit","data","evtArr","len","evts","liveEvents","TinyEmitter","is","target","type","string","node","addEventListener","destroy","removeEventListener","listenNode","nodeList","forEach","listenNodeList","selector","body","listenSelector","HTMLElement","nodeType","String","closest","_delegate","useCapture","listenerFn","delegateTarget","elements","querySelectorAll","Element","matches","proto","matchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector","webkitMatchesSelector","parentNode","__webpack_exports__","src_select","select_default","_typeof","_createClass","defineProperties","props","descriptor","configurable","writable","Constructor","protoProps","staticProps","clipboard_action","ClipboardAction","options","_classCallCheck","resolveOptions","initSelection","container","emitter","text","trigger","selectFake","selectTarget","_this","isRTL","documentElement","getAttribute","removeFake","fakeHandlerCallback","fakeHandler","fakeElem","createElement","style","fontSize","border","padding","margin","position","yPosition","pageYOffset","scrollTop","top","appendChild","copyText","removeChild","succeeded","execCommand","handleResult","clearSelection","activeElement","blur","set","_action","_target","tiny_emitter","tiny_emitter_default","listen","listen_default","clipboard_typeof","clipboard_createClass","clipboard_Clipboard","_Emitter","Clipboard","clipboard_classCallCheck","ReferenceError","_possibleConstructorReturn","__proto__","getPrototypeOf","listenClick","subClass","superClass","setPrototypeOf","_inherits","defaultAction","defaultTarget","defaultText","_this2","onClick","currentTarget","clipboardAction","getAttributeValue","querySelector","support","queryCommandSupported","suffix","attribute","ReplaySubject","bufferSize","windowTime","timestampProvider","infiniteTimeWindow","Math","max","trimBuffer","adjustedBufferSize","pipe","fns","pipeFromArray","reduce","prev","mapTo","defer","observableFactory","filter","predicate","distinctUntilChanged","compare","keySelector","defaultCompare","first","matchHtmlRegExp","escape","str","match","exec","html","lastIndex","charCodeAt","substring","applyFocusVisiblePolyfill","scope","hadKeyboardEvent","hadFocusVisibleRecently","hadFocusVisibleRecentlyTimeout","inputTypesAllowlist","search","url","tel","email","password","number","date","month","week","time","datetime","isValidFocusTarget","el","classList","addFocusVisibleClass","contains","onPointerDown","addInitialPointerMoveListeners","onInitialPointerMove","toLowerCase","metaKey","altKey","ctrlKey","visibilityState","tagName","readOnly","isContentEditable","Node","DOCUMENT_FRAGMENT_NODE","host","DOCUMENT_NODE","event","CustomEvent","createEvent","initCustomEvent","dispatchEvent","nodeEventEmitterMethods","eventTargetMethods","jqueryMethods","fromEvent","eventName","isEventTarget","methodName","handler","addListener","removeListener","isNodeStyleEventEmitter","toCommonHandlerRegistry","isJQueryStyleEventEmitter","subTarget","merge","sources","startWith","values","of","NEVER","finalize","shareReplay","configOrBufferSize","refCount","useRefCount","innerSub","dest","shareReplayOperator","tap","tapObserver","BehaviorSubject","_value","getValue","distinctUntilKeyChanged","y","defaultThrottleConfig","leading","trailing","throttle","durationSelector","hasValue","sendValue","throttled","endThrottling","send","cleanupThrottling","startThrottle","switchMapTo","innerObservable","observeOn","withLatestFrom","inputs","otherValues","ready","every","sample","notifier","lastValue","skip","catchError","handledResult","syncUnsub","bufferCount","startBufferEvery","buffers","toEmit","concatMap","iif","condition","trueResult","falseResult","defaultIfEmpty","connection","_refCount","refCounter","sharedConnection","_connection","conn","connect","subjectFactory","_subject","getSubject","_teardown","shareSubjectFactory","Subject","share","subjectOrSubjectFactory","connectable","multicast","animationFrameProvider","request","requestAnimationFrame","cancel","cancelAnimationFrame","timestamp","AsyncAction","AsyncScheduler","animationFrameScheduler","delayWhen","delayDurationSelector","subscriptionDelay","duration","objectProto","keys","getKeys","argsArgArrayOrObject","combineLatest","observables","valueTransform","maybeSchedule","hasValues","waitingForFirstValues","combineLatestInit","Subscriber","shouldComplete","scanInternals","accumulator","seed","hasSeed","emitOnNext","emitBeforeComplete","hasState","scan","completed","sourceIndex","some","zip","zipWith","otherInputs","debounceTime","durationSubscriber"],"mappings":"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","file":"assets/javascripts/vendor.93c04032.min.js","sourcesContent":["import { isFunction } from './isFunction';\nexport function hasLift(source) {\n return isFunction(source === null || source === void 0 ? void 0 : source.lift);\n}\nexport function operate(init) {\n return (source) => {\n if (hasLift(source)) {\n return source.lift(function (liftedSource) {\n try {\n return init(liftedSource, this);\n }\n catch (err) {\n this.error(err);\n }\n });\n }\n throw new TypeError('Unable to lift unknown Observable type');\n };\n}\n//# sourceMappingURL=lift.js.map","import { Subscriber } from '../Subscriber';\nexport class OperatorSubscriber extends Subscriber {\n constructor(destination, onNext, onError, onComplete, onUnsubscribe) {\n super(destination);\n this.onUnsubscribe = onUnsubscribe;\n if (onNext) {\n this._next = function (value) {\n try {\n onNext(value);\n }\n catch (err) {\n this.destination.error(err);\n }\n };\n }\n if (onError) {\n this._error = function (err) {\n try {\n onError(err);\n }\n catch (err) {\n this.destination.error(err);\n }\n this.unsubscribe();\n };\n }\n if (onComplete) {\n this._complete = function () {\n try {\n onComplete();\n }\n catch (err) {\n this.destination.error(err);\n }\n this.unsubscribe();\n };\n }\n }\n unsubscribe() {\n var _a;\n !this.closed && ((_a = this.onUnsubscribe) === null || _a === void 0 ? void 0 : _a.call(this));\n super.unsubscribe();\n }\n}\n//# sourceMappingURL=OperatorSubscriber.js.map","export function isFunction(value) {\n return typeof value === 'function';\n}\n//# sourceMappingURL=isFunction.js.map","import { SafeSubscriber, Subscriber } from './Subscriber';\nimport { isSubscription } from './Subscription';\nimport { observable as Symbol_observable } from './symbol/observable';\nimport { pipeFromArray } from './util/pipe';\nimport { config } from './config';\nimport { isFunction } from './util/isFunction';\nexport class Observable {\n constructor(subscribe) {\n if (subscribe) {\n this._subscribe = subscribe;\n }\n }\n lift(operator) {\n const observable = new Observable();\n observable.source = this;\n observable.operator = operator;\n return observable;\n }\n subscribe(observerOrNext, error, complete) {\n const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);\n const { operator, source } = this;\n subscriber.add(operator\n ? operator.call(subscriber, source)\n : source || config.useDeprecatedSynchronousErrorHandling\n ? this._subscribe(subscriber)\n : this._trySubscribe(subscriber));\n return subscriber;\n }\n _trySubscribe(sink) {\n try {\n return this._subscribe(sink);\n }\n catch (err) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n throw err;\n }\n sink.error(err);\n }\n }\n forEach(next, promiseCtor) {\n promiseCtor = getPromiseCtor(promiseCtor);\n return new promiseCtor((resolve, reject) => {\n let subscription;\n subscription = this.subscribe((value) => {\n try {\n next(value);\n }\n catch (err) {\n reject(err);\n subscription === null || subscription === void 0 ? void 0 : subscription.unsubscribe();\n }\n }, reject, resolve);\n });\n }\n _subscribe(subscriber) {\n var _a;\n return (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber);\n }\n [Symbol_observable]() {\n return this;\n }\n pipe(...operations) {\n return operations.length ? pipeFromArray(operations)(this) : this;\n }\n toPromise(promiseCtor) {\n promiseCtor = getPromiseCtor(promiseCtor);\n return new promiseCtor((resolve, reject) => {\n let value;\n this.subscribe((x) => (value = x), (err) => reject(err), () => resolve(value));\n });\n }\n}\nObservable.create = (subscribe) => {\n return new Observable(subscribe);\n};\nfunction getPromiseCtor(promiseCtor) {\n var _a;\n return (_a = promiseCtor !== null && promiseCtor !== void 0 ? promiseCtor : config.Promise) !== null && _a !== void 0 ? _a : Promise;\n}\nfunction isObserver(value) {\n return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);\n}\nfunction isSubscriber(value) {\n return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));\n}\n//# sourceMappingURL=Observable.js.map","/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","import { isFunction } from \"./isFunction\";\nexport function isPromise(value) {\n return isFunction(value === null || value === void 0 ? void 0 : value.then);\n}\n//# sourceMappingURL=isPromise.js.map","export function getSymbolIterator() {\n if (typeof Symbol !== 'function' || !Symbol.iterator) {\n return '@@iterator';\n }\n return Symbol.iterator;\n}\nexport const iterator = getSymbolIterator();\nexport const $$iterator = iterator;\n//# sourceMappingURL=iterator.js.map","import { observable as Symbol_observable } from '../symbol/observable';\nimport { isFunction } from './isFunction';\nexport function isInteropObservable(input) {\n return isFunction(input[Symbol_observable]);\n}\n//# sourceMappingURL=isInteropObservable.js.map","import { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from './isFunction';\nexport function isIterable(input) {\n return isFunction(input === null || input === void 0 ? void 0 : input[Symbol_iterator]);\n}\n//# sourceMappingURL=isIterable.js.map","import { isFunction } from './isFunction';\nexport function isAsyncIterable(obj) {\n return Symbol.asyncIterator && isFunction(obj === null || obj === void 0 ? void 0 : obj[Symbol.asyncIterator]);\n}\n//# sourceMappingURL=isAsyncIterable.js.map","export function createInvalidObservableTypeError(input) {\n return new TypeError(`You provided ${input !== null && typeof input === 'object' ? 'an invalid object' : `'${input}'`} where a stream was expected. You can provide an Observable, Promise, Array, AsyncIterable, or Iterable.`);\n}\n//# sourceMappingURL=throwUnobservableError.js.map","import { scheduleObservable } from './scheduleObservable';\nimport { schedulePromise } from './schedulePromise';\nimport { scheduleArray } from './scheduleArray';\nimport { scheduleIterable } from './scheduleIterable';\nimport { isInteropObservable } from '../util/isInteropObservable';\nimport { isPromise } from '../util/isPromise';\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isIterable } from '../util/isIterable';\nimport { scheduleAsyncIterable } from './scheduleAsyncIterable';\nimport { isAsyncIterable } from '../util/isAsyncIterable';\nimport { createInvalidObservableTypeError } from '../util/throwUnobservableError';\nexport function scheduled(input, scheduler) {\n if (input != null) {\n if (isInteropObservable(input)) {\n return scheduleObservable(input, scheduler);\n }\n if (isArrayLike(input)) {\n return scheduleArray(input, scheduler);\n }\n if (isPromise(input)) {\n return schedulePromise(input, scheduler);\n }\n if (isAsyncIterable(input)) {\n return scheduleAsyncIterable(input, scheduler);\n }\n if (isIterable(input)) {\n return scheduleIterable(input, scheduler);\n }\n }\n throw createInvalidObservableTypeError(input);\n}\n//# sourceMappingURL=scheduled.js.map","import { Observable } from '../Observable';\nimport { Subscription } from '../Subscription';\nimport { observable as Symbol_observable } from '../symbol/observable';\nexport function scheduleObservable(input, scheduler) {\n return new Observable(subscriber => {\n const sub = new Subscription();\n sub.add(scheduler.schedule(() => {\n const observable = input[Symbol_observable]();\n sub.add(observable.subscribe({\n next(value) { sub.add(scheduler.schedule(() => subscriber.next(value))); },\n error(err) { sub.add(scheduler.schedule(() => subscriber.error(err))); },\n complete() { sub.add(scheduler.schedule(() => subscriber.complete())); },\n }));\n }));\n return sub;\n });\n}\n//# sourceMappingURL=scheduleObservable.js.map","import { Observable } from '../Observable';\nexport function schedulePromise(input, scheduler) {\n return new Observable((subscriber) => {\n return scheduler.schedule(() => input.then((value) => {\n subscriber.add(scheduler.schedule(() => {\n subscriber.next(value);\n subscriber.add(scheduler.schedule(() => subscriber.complete()));\n }));\n }, (err) => {\n subscriber.add(scheduler.schedule(() => subscriber.error(err)));\n }));\n });\n}\n//# sourceMappingURL=schedulePromise.js.map","import { Observable } from '../Observable';\nimport { Subscription } from '../Subscription';\nexport function scheduleAsyncIterable(input, scheduler) {\n if (!input) {\n throw new Error('Iterable cannot be null');\n }\n return new Observable(subscriber => {\n const sub = new Subscription();\n sub.add(scheduler.schedule(() => {\n const iterator = input[Symbol.asyncIterator]();\n sub.add(scheduler.schedule(function () {\n iterator.next().then(result => {\n if (result.done) {\n subscriber.complete();\n }\n else {\n subscriber.next(result.value);\n this.schedule();\n }\n });\n }));\n }));\n return sub;\n });\n}\n//# sourceMappingURL=scheduleAsyncIterable.js.map","import { Observable } from '../Observable';\nimport { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { isFunction } from '../util/isFunction';\nimport { caughtSchedule } from '../util/caughtSchedule';\nexport function scheduleIterable(input, scheduler) {\n return new Observable((subscriber) => {\n let iterator;\n subscriber.add(scheduler.schedule(() => {\n iterator = input[Symbol_iterator]();\n caughtSchedule(subscriber, scheduler, function () {\n const { value, done } = iterator.next();\n if (done) {\n subscriber.complete();\n }\n else {\n subscriber.next(value);\n this.schedule();\n }\n });\n }));\n return () => isFunction(iterator === null || iterator === void 0 ? void 0 : iterator.return) && iterator.return();\n });\n}\n//# sourceMappingURL=scheduleIterable.js.map","export function caughtSchedule(subscriber, scheduler, execute, delay = 0) {\n const subscription = scheduler.schedule(function () {\n try {\n execute.call(this);\n }\n catch (err) {\n subscriber.error(err);\n }\n }, delay);\n subscriber.add(subscription);\n return subscription;\n}\n//# sourceMappingURL=caughtSchedule.js.map","import { __asyncValues, __awaiter } from \"tslib\";\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isPromise } from '../util/isPromise';\nimport { iterator as Symbol_iterator } from '../symbol/iterator';\nimport { observable as Symbol_observable } from '../symbol/observable';\nimport { Observable } from '../Observable';\nimport { scheduled } from '../scheduled/scheduled';\nimport { isFunction } from '../util/isFunction';\nimport { reportUnhandledError } from '../util/reportUnhandledError';\nimport { isInteropObservable } from '../util/isInteropObservable';\nimport { isAsyncIterable } from '../util/isAsyncIterable';\nimport { createInvalidObservableTypeError } from '../util/throwUnobservableError';\nimport { isIterable } from '../util/isIterable';\nexport function from(input, scheduler) {\n return scheduler ? scheduled(input, scheduler) : innerFrom(input);\n}\nexport function innerFrom(input) {\n if (input instanceof Observable) {\n return input;\n }\n if (input != null) {\n if (isInteropObservable(input)) {\n return fromInteropObservable(input);\n }\n if (isArrayLike(input)) {\n return fromArrayLike(input);\n }\n if (isPromise(input)) {\n return fromPromise(input);\n }\n if (isAsyncIterable(input)) {\n return fromAsyncIterable(input);\n }\n if (isIterable(input)) {\n return fromIterable(input);\n }\n }\n throw createInvalidObservableTypeError(input);\n}\nfunction fromInteropObservable(obj) {\n return new Observable((subscriber) => {\n const obs = obj[Symbol_observable]();\n if (isFunction(obs.subscribe)) {\n return obs.subscribe(subscriber);\n }\n throw new TypeError('Provided object does not correctly implement Symbol.observable');\n });\n}\nexport function fromArrayLike(array) {\n return new Observable((subscriber) => {\n for (let i = 0; i < array.length && !subscriber.closed; i++) {\n subscriber.next(array[i]);\n }\n subscriber.complete();\n });\n}\nfunction fromPromise(promise) {\n return new Observable((subscriber) => {\n promise\n .then((value) => {\n if (!subscriber.closed) {\n subscriber.next(value);\n subscriber.complete();\n }\n }, (err) => subscriber.error(err))\n .then(null, reportUnhandledError);\n });\n}\nfunction fromIterable(iterable) {\n return new Observable((subscriber) => {\n const iterator = iterable[Symbol_iterator]();\n while (!subscriber.closed) {\n const { done, value } = iterator.next();\n if (done) {\n subscriber.complete();\n }\n else {\n subscriber.next(value);\n }\n }\n return () => isFunction(iterator === null || iterator === void 0 ? void 0 : iterator.return) && iterator.return();\n });\n}\nfunction fromAsyncIterable(asyncIterable) {\n return new Observable((subscriber) => {\n process(asyncIterable, subscriber).catch((err) => subscriber.error(err));\n });\n}\nfunction process(asyncIterable, subscriber) {\n var asyncIterable_1, asyncIterable_1_1;\n var e_1, _a;\n return __awaiter(this, void 0, void 0, function* () {\n try {\n for (asyncIterable_1 = __asyncValues(asyncIterable); asyncIterable_1_1 = yield asyncIterable_1.next(), !asyncIterable_1_1.done;) {\n const value = asyncIterable_1_1.value;\n subscriber.next(value);\n }\n }\n catch (e_1_1) { e_1 = { error: e_1_1 }; }\n finally {\n try {\n if (asyncIterable_1_1 && !asyncIterable_1_1.done && (_a = asyncIterable_1.return)) yield _a.call(asyncIterable_1);\n }\n finally { if (e_1) throw e_1.error; }\n }\n subscriber.complete();\n });\n}\n//# sourceMappingURL=from.js.map","import { createErrorClass } from './createErrorClass';\nexport const UnsubscriptionError = createErrorClass((_super) => function UnsubscriptionErrorImpl(errors) {\n _super(this);\n this.message = errors\n ? `${errors.length} errors occurred during unsubscription:\n${errors.map((err, i) => `${i + 1}) ${err.toString()}`).join('\\n ')}`\n : '';\n this.name = 'UnsubscriptionError';\n this.errors = errors;\n});\n//# sourceMappingURL=UnsubscriptionError.js.map","import { isFunction } from './util/isFunction';\nimport { UnsubscriptionError } from './util/UnsubscriptionError';\nimport { arrRemove } from './util/arrRemove';\nexport class Subscription {\n constructor(initialTeardown) {\n this.initialTeardown = initialTeardown;\n this.closed = false;\n this._parentage = null;\n this._teardowns = null;\n }\n unsubscribe() {\n let errors;\n if (!this.closed) {\n this.closed = true;\n const { _parentage } = this;\n if (Array.isArray(_parentage)) {\n for (const parent of _parentage) {\n parent.remove(this);\n }\n }\n else {\n _parentage === null || _parentage === void 0 ? void 0 : _parentage.remove(this);\n }\n const { initialTeardown } = this;\n if (isFunction(initialTeardown)) {\n try {\n initialTeardown();\n }\n catch (e) {\n errors = e instanceof UnsubscriptionError ? e.errors : [e];\n }\n }\n const { _teardowns } = this;\n if (_teardowns) {\n this._teardowns = null;\n for (const teardown of _teardowns) {\n try {\n execTeardown(teardown);\n }\n catch (err) {\n errors = errors !== null && errors !== void 0 ? errors : [];\n if (err instanceof UnsubscriptionError) {\n errors = [...errors, ...err.errors];\n }\n else {\n errors.push(err);\n }\n }\n }\n }\n if (errors) {\n throw new UnsubscriptionError(errors);\n }\n }\n }\n add(teardown) {\n var _a;\n if (teardown && teardown !== this) {\n if (this.closed) {\n execTeardown(teardown);\n }\n else {\n if (teardown instanceof Subscription) {\n if (teardown.closed || teardown._hasParent(this)) {\n return;\n }\n teardown._addParent(this);\n }\n (this._teardowns = (_a = this._teardowns) !== null && _a !== void 0 ? _a : []).push(teardown);\n }\n }\n }\n _hasParent(parent) {\n const { _parentage } = this;\n return _parentage === parent || (Array.isArray(_parentage) && _parentage.includes(parent));\n }\n _addParent(parent) {\n const { _parentage } = this;\n this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;\n }\n _removeParent(parent) {\n const { _parentage } = this;\n if (_parentage === parent) {\n this._parentage = null;\n }\n else if (Array.isArray(_parentage)) {\n arrRemove(_parentage, parent);\n }\n }\n remove(teardown) {\n const { _teardowns } = this;\n _teardowns && arrRemove(_teardowns, teardown);\n if (teardown instanceof Subscription) {\n teardown._removeParent(this);\n }\n }\n}\nSubscription.EMPTY = (() => {\n const empty = new Subscription();\n empty.closed = true;\n return empty;\n})();\nexport const EMPTY_SUBSCRIPTION = Subscription.EMPTY;\nexport function isSubscription(value) {\n return (value instanceof Subscription ||\n (value && 'closed' in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe)));\n}\nfunction execTeardown(teardown) {\n if (isFunction(teardown)) {\n teardown();\n }\n else {\n teardown.unsubscribe();\n }\n}\n//# sourceMappingURL=Subscription.js.map","import { isFunction } from './isFunction';\nimport { isScheduler } from './isScheduler';\nfunction last(arr) {\n return arr[arr.length - 1];\n}\nexport function popResultSelector(args) {\n return isFunction(last(args)) ? args.pop() : undefined;\n}\nexport function popScheduler(args) {\n return isScheduler(last(args)) ? args.pop() : undefined;\n}\nexport function popNumber(args, defaultValue) {\n return typeof last(args) === 'number' ? args.pop() : defaultValue;\n}\n//# sourceMappingURL=args.js.map","export function noop() { }\n//# sourceMappingURL=noop.js.map","export function identity(x) {\n return x;\n}\n//# sourceMappingURL=identity.js.map","export const config = {\n onUnhandledError: null,\n onStoppedNotification: null,\n Promise: undefined,\n useDeprecatedSynchronousErrorHandling: false,\n useDeprecatedNextContext: false,\n};\n//# sourceMappingURL=config.js.map","export function arrRemove(arr, item) {\n if (arr) {\n const index = arr.indexOf(item);\n 0 <= index && arr.splice(index, 1);\n }\n}\n//# sourceMappingURL=arrRemove.js.map","import { map } from './map';\nimport { innerFrom } from '../observable/from';\nimport { operate } from '../util/lift';\nimport { mergeInternals } from './mergeInternals';\nimport { isFunction } from '../util/isFunction';\nexport function mergeMap(project, resultSelector, concurrent = Infinity) {\n if (isFunction(resultSelector)) {\n return mergeMap((a, i) => map((b, ii) => resultSelector(a, b, i, ii))(innerFrom(project(a, i))), concurrent);\n }\n else if (typeof resultSelector === 'number') {\n concurrent = resultSelector;\n }\n return operate((source, subscriber) => mergeInternals(source, subscriber, project, concurrent));\n}\nexport const flatMap = mergeMap;\n//# sourceMappingURL=mergeMap.js.map","import { innerFrom } from '../observable/from';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function mergeInternals(source, subscriber, project, concurrent, onBeforeNext, expand, innerSubScheduler, additionalTeardown) {\n let buffer = [];\n let active = 0;\n let index = 0;\n let isComplete = false;\n const checkComplete = () => {\n if (isComplete && !buffer.length && !active) {\n subscriber.complete();\n }\n };\n const outerNext = (value) => (active < concurrent ? doInnerSub(value) : buffer.push(value));\n const doInnerSub = (value) => {\n expand && subscriber.next(value);\n active++;\n innerFrom(project(value, index++)).subscribe(new OperatorSubscriber(subscriber, (innerValue) => {\n onBeforeNext === null || onBeforeNext === void 0 ? void 0 : onBeforeNext(innerValue);\n if (expand) {\n outerNext(innerValue);\n }\n else {\n subscriber.next(innerValue);\n }\n }, undefined, () => {\n active--;\n while (buffer.length && active < concurrent) {\n const bufferedValue = buffer.shift();\n innerSubScheduler ? subscriber.add(innerSubScheduler.schedule(() => doInnerSub(bufferedValue))) : doInnerSub(bufferedValue);\n }\n checkComplete();\n }));\n };\n source.subscribe(new OperatorSubscriber(subscriber, outerNext, undefined, () => {\n isComplete = true;\n checkComplete();\n }));\n return () => {\n buffer = null;\n additionalTeardown === null || additionalTeardown === void 0 ? void 0 : additionalTeardown();\n };\n}\n//# sourceMappingURL=mergeInternals.js.map","export const observable = (() => (typeof Symbol === 'function' && Symbol.observable) || '@@observable')();\n//# sourceMappingURL=observable.js.map","import { scheduleArray } from '../scheduled/scheduleArray';\nimport { fromArrayLike } from './from';\nexport function internalFromArray(input, scheduler) {\n return scheduler ? scheduleArray(input, scheduler) : fromArrayLike(input);\n}\n//# sourceMappingURL=fromArray.js.map","export const COMPLETE_NOTIFICATION = (() => createNotification('C', undefined, undefined))();\nexport function errorNotification(error) {\n return createNotification('E', undefined, error);\n}\nexport function nextNotification(value) {\n return createNotification('N', value, undefined);\n}\nexport function createNotification(kind, value, error) {\n return {\n kind,\n value,\n error,\n };\n}\n//# sourceMappingURL=NotificationFactories.js.map","import { isFunction } from './util/isFunction';\nimport { isSubscription, Subscription } from './Subscription';\nimport { config } from './config';\nimport { reportUnhandledError } from './util/reportUnhandledError';\nimport { noop } from './util/noop';\nimport { nextNotification, errorNotification, COMPLETE_NOTIFICATION } from './NotificationFactories';\nimport { timeoutProvider } from './scheduler/timeoutProvider';\nexport class Subscriber extends Subscription {\n constructor(destination) {\n super();\n this.isStopped = false;\n if (destination) {\n this.destination = destination;\n if (isSubscription(destination)) {\n destination.add(this);\n }\n }\n else {\n this.destination = EMPTY_OBSERVER;\n }\n }\n static create(next, error, complete) {\n return new SafeSubscriber(next, error, complete);\n }\n next(value) {\n if (this.isStopped) {\n handleStoppedNotification(nextNotification(value), this);\n }\n else {\n this._next(value);\n }\n }\n error(err) {\n if (this.isStopped) {\n handleStoppedNotification(errorNotification(err), this);\n }\n else {\n this.isStopped = true;\n this._error(err);\n }\n }\n complete() {\n if (this.isStopped) {\n handleStoppedNotification(COMPLETE_NOTIFICATION, this);\n }\n else {\n this.isStopped = true;\n this._complete();\n }\n }\n unsubscribe() {\n if (!this.closed) {\n this.isStopped = true;\n super.unsubscribe();\n }\n }\n _next(value) {\n this.destination.next(value);\n }\n _error(err) {\n this.destination.error(err);\n this.unsubscribe();\n }\n _complete() {\n this.destination.complete();\n this.unsubscribe();\n }\n}\nexport class SafeSubscriber extends Subscriber {\n constructor(observerOrNext, error, complete) {\n super();\n this.destination = EMPTY_OBSERVER;\n if ((observerOrNext || error || complete) && observerOrNext !== EMPTY_OBSERVER) {\n let next;\n if (isFunction(observerOrNext)) {\n next = observerOrNext;\n }\n else if (observerOrNext) {\n ({ next, error, complete } = observerOrNext);\n let context;\n if (this && config.useDeprecatedNextContext) {\n context = Object.create(observerOrNext);\n context.unsubscribe = () => this.unsubscribe();\n }\n else {\n context = observerOrNext;\n }\n next = next === null || next === void 0 ? void 0 : next.bind(context);\n error = error === null || error === void 0 ? void 0 : error.bind(context);\n complete = complete === null || complete === void 0 ? void 0 : complete.bind(context);\n }\n this.destination = {\n next: next || noop,\n error: error || defaultErrorHandler,\n complete: complete || noop,\n };\n }\n }\n}\nfunction defaultErrorHandler(err) {\n if (config.useDeprecatedSynchronousErrorHandling) {\n throw err;\n }\n reportUnhandledError(err);\n}\nfunction handleStoppedNotification(notification, subscriber) {\n const { onStoppedNotification } = config;\n onStoppedNotification && timeoutProvider.setTimeout(() => onStoppedNotification(notification, subscriber));\n}\nexport const EMPTY_OBSERVER = {\n closed: true,\n next: noop,\n error: defaultErrorHandler,\n complete: noop,\n};\n//# sourceMappingURL=Subscriber.js.map","export const isArrayLike = ((x) => x && typeof x.length === 'number' && typeof x !== 'function');\n//# sourceMappingURL=isArrayLike.js.map","import { Observable } from '../Observable';\nexport function scheduleArray(input, scheduler) {\n return new Observable((subscriber) => {\n let i = 0;\n return scheduler.schedule(function () {\n if (i === input.length) {\n subscriber.complete();\n }\n else {\n subscriber.next(input[i++]);\n if (!subscriber.closed) {\n this.schedule();\n }\n }\n });\n });\n}\n//# sourceMappingURL=scheduleArray.js.map","import { Observable } from '../Observable';\nexport const EMPTY = new Observable(subscriber => subscriber.complete());\nexport function empty(scheduler) {\n return scheduler ? emptyScheduled(scheduler) : EMPTY;\n}\nfunction emptyScheduled(scheduler) {\n return new Observable(subscriber => scheduler.schedule(() => subscriber.complete()));\n}\n//# sourceMappingURL=empty.js.map","import { AsyncAction } from './AsyncAction';\nimport { AsyncScheduler } from './AsyncScheduler';\nexport const asyncScheduler = new AsyncScheduler(AsyncAction);\nexport const async = asyncScheduler;\n//# sourceMappingURL=async.js.map","import { createErrorClass } from './createErrorClass';\nexport const ObjectUnsubscribedError = createErrorClass((_super) => function ObjectUnsubscribedErrorImpl() {\n _super(this);\n this.name = 'ObjectUnsubscribedError';\n this.message = 'object unsubscribed';\n});\n//# sourceMappingURL=ObjectUnsubscribedError.js.map","import { Observable } from './Observable';\nimport { Subscription, EMPTY_SUBSCRIPTION } from './Subscription';\nimport { ObjectUnsubscribedError } from './util/ObjectUnsubscribedError';\nimport { arrRemove } from './util/arrRemove';\nexport class Subject extends Observable {\n constructor() {\n super();\n this.observers = [];\n this.closed = false;\n this.isStopped = false;\n this.hasError = false;\n this.thrownError = null;\n }\n lift(operator) {\n const subject = new AnonymousSubject(this, this);\n subject.operator = operator;\n return subject;\n }\n _throwIfClosed() {\n if (this.closed) {\n throw new ObjectUnsubscribedError();\n }\n }\n next(value) {\n this._throwIfClosed();\n if (!this.isStopped) {\n const copy = this.observers.slice();\n for (const observer of copy) {\n observer.next(value);\n }\n }\n }\n error(err) {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.hasError = this.isStopped = true;\n this.thrownError = err;\n const { observers } = this;\n while (observers.length) {\n observers.shift().error(err);\n }\n }\n }\n complete() {\n this._throwIfClosed();\n if (!this.isStopped) {\n this.isStopped = true;\n const { observers } = this;\n while (observers.length) {\n observers.shift().complete();\n }\n }\n }\n unsubscribe() {\n this.isStopped = this.closed = true;\n this.observers = null;\n }\n _trySubscribe(subscriber) {\n this._throwIfClosed();\n return super._trySubscribe(subscriber);\n }\n _subscribe(subscriber) {\n this._throwIfClosed();\n this._checkFinalizedStatuses(subscriber);\n return this._innerSubscribe(subscriber);\n }\n _innerSubscribe(subscriber) {\n const { hasError, isStopped, observers } = this;\n return hasError || isStopped\n ? EMPTY_SUBSCRIPTION\n : (observers.push(subscriber), new Subscription(() => arrRemove(this.observers, subscriber)));\n }\n _checkFinalizedStatuses(subscriber) {\n const { hasError, thrownError, isStopped } = this;\n if (hasError) {\n subscriber.error(thrownError);\n }\n else if (isStopped) {\n subscriber.complete();\n }\n }\n asObservable() {\n const observable = new Observable();\n observable.source = this;\n return observable;\n }\n}\nSubject.create = (destination, source) => {\n return new AnonymousSubject(destination, source);\n};\nexport class AnonymousSubject extends Subject {\n constructor(destination, source) {\n super();\n this.destination = destination;\n this.source = source;\n }\n next(value) {\n var _a, _b;\n (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.next) === null || _b === void 0 ? void 0 : _b.call(_a, value);\n }\n error(err) {\n var _a, _b;\n (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.error) === null || _b === void 0 ? void 0 : _b.call(_a, err);\n }\n complete() {\n var _a, _b;\n (_b = (_a = this.destination) === null || _a === void 0 ? void 0 : _a.complete) === null || _b === void 0 ? void 0 : _b.call(_a);\n }\n _subscribe(subscriber) {\n var _a, _b;\n return (_b = (_a = this.source) === null || _a === void 0 ? void 0 : _a.subscribe(subscriber)) !== null && _b !== void 0 ? _b : EMPTY_SUBSCRIPTION;\n }\n}\n//# sourceMappingURL=Subject.js.map","import { concatAll } from '../operators/concatAll';\nimport { internalFromArray } from './fromArray';\nimport { popScheduler } from '../util/args';\nexport function concat(...args) {\n return concatAll()(internalFromArray(args, popScheduler(args)));\n}\n//# sourceMappingURL=concat.js.map","import { mergeAll } from './mergeAll';\nexport function concatAll() {\n return mergeAll(1);\n}\n//# sourceMappingURL=concatAll.js.map","export function createErrorClass(createImpl) {\n const _super = (instance) => {\n Error.call(instance);\n instance.stack = new Error().stack;\n };\n const ctorFunc = createImpl(_super);\n ctorFunc.prototype = Object.create(Error.prototype);\n ctorFunc.prototype.constructor = ctorFunc;\n return ctorFunc;\n}\n//# sourceMappingURL=createErrorClass.js.map","import { config } from '../config';\nimport { timeoutProvider } from '../scheduler/timeoutProvider';\nexport function reportUnhandledError(err) {\n timeoutProvider.setTimeout(() => {\n const { onUnhandledError } = config;\n if (onUnhandledError) {\n onUnhandledError(err);\n }\n else {\n throw err;\n }\n });\n}\n//# sourceMappingURL=reportUnhandledError.js.map","export const timeoutProvider = {\n setTimeout(...args) {\n const { delegate } = timeoutProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.setTimeout) || setTimeout)(...args);\n },\n clearTimeout(handle) {\n const { delegate } = timeoutProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearTimeout) || clearTimeout)(handle);\n },\n delegate: undefined,\n};\n//# sourceMappingURL=timeoutProvider.js.map","export const dateTimestampProvider = {\n now() {\n return (dateTimestampProvider.delegate || Date).now();\n },\n delegate: undefined,\n};\n//# sourceMappingURL=dateTimestampProvider.js.map","import { map } from \"../operators/map\";\nconst { isArray } = Array;\nfunction callOrApply(fn, args) {\n return isArray(args) ? fn(...args) : fn(args);\n}\nexport function mapOneOrManyArgs(fn) {\n return map(args => callOrApply(fn, args));\n}\n//# sourceMappingURL=mapOneOrManyArgs.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function map(project, thisArg) {\n return operate((source, subscriber) => {\n let index = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n subscriber.next(project.call(thisArg, value, index++));\n }));\n });\n}\n//# sourceMappingURL=map.js.map","import { isFunction } from './isFunction';\nexport function isScheduler(value) {\n return value && isFunction(value.schedule);\n}\n//# sourceMappingURL=isScheduler.js.map","const { isArray } = Array;\nexport function argsOrArgArray(args) {\n return args.length === 1 && isArray(args[0]) ? args[0] : args;\n}\n//# sourceMappingURL=argsOrArgArray.js.map","import { mergeMap } from './mergeMap';\nimport { identity } from '../util/identity';\nexport function mergeAll(concurrent = Infinity) {\n return mergeMap(identity, concurrent);\n}\n//# sourceMappingURL=mergeAll.js.map","import { Subscription } from '../Subscription';\nexport class Action extends Subscription {\n constructor(scheduler, work) {\n super();\n }\n schedule(state, delay = 0) {\n return this;\n }\n}\n//# sourceMappingURL=Action.js.map","export const intervalProvider = {\n setInterval(...args) {\n const { delegate } = intervalProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.setInterval) || setInterval)(...args);\n },\n clearInterval(handle) {\n const { delegate } = intervalProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.clearInterval) || clearInterval)(handle);\n },\n delegate: undefined,\n};\n//# sourceMappingURL=intervalProvider.js.map","import { Action } from './Action';\nimport { intervalProvider } from './intervalProvider';\nimport { arrRemove } from '../util/arrRemove';\nexport class AsyncAction extends Action {\n constructor(scheduler, work) {\n super(scheduler, work);\n this.scheduler = scheduler;\n this.work = work;\n this.pending = false;\n }\n schedule(state, delay = 0) {\n if (this.closed) {\n return this;\n }\n this.state = state;\n const id = this.id;\n const scheduler = this.scheduler;\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, delay);\n }\n this.pending = true;\n this.delay = delay;\n this.id = this.id || this.requestAsyncId(scheduler, this.id, delay);\n return this;\n }\n requestAsyncId(scheduler, _id, delay = 0) {\n return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);\n }\n recycleAsyncId(_scheduler, id, delay = 0) {\n if (delay != null && this.delay === delay && this.pending === false) {\n return id;\n }\n intervalProvider.clearInterval(id);\n return undefined;\n }\n execute(state, delay) {\n if (this.closed) {\n return new Error('executing a cancelled action');\n }\n this.pending = false;\n const error = this._execute(state, delay);\n if (error) {\n return error;\n }\n else if (this.pending === false && this.id != null) {\n this.id = this.recycleAsyncId(this.scheduler, this.id, null);\n }\n }\n _execute(state, _delay) {\n let errored = false;\n let errorValue;\n try {\n this.work(state);\n }\n catch (e) {\n errored = true;\n errorValue = (!!e && e) || new Error(e);\n }\n if (errored) {\n this.unsubscribe();\n return errorValue;\n }\n }\n unsubscribe() {\n if (!this.closed) {\n const { id, scheduler } = this;\n const { actions } = scheduler;\n this.work = this.state = this.scheduler = null;\n this.pending = false;\n arrRemove(actions, this);\n if (id != null) {\n this.id = this.recycleAsyncId(scheduler, id, null);\n }\n this.delay = null;\n super.unsubscribe();\n }\n }\n}\n//# sourceMappingURL=AsyncAction.js.map","import { Observable } from '../Observable';\nimport { async as asyncScheduler } from '../scheduler/async';\nimport { isScheduler } from '../util/isScheduler';\nimport { isValidDate } from '../util/isDate';\nexport function timer(dueTime = 0, intervalOrScheduler, scheduler = asyncScheduler) {\n let intervalDuration = -1;\n if (intervalOrScheduler != null) {\n if (isScheduler(intervalOrScheduler)) {\n scheduler = intervalOrScheduler;\n }\n else {\n intervalDuration = intervalOrScheduler;\n }\n }\n return new Observable((subscriber) => {\n let due = isValidDate(dueTime) ? +dueTime - scheduler.now() : dueTime;\n if (due < 0) {\n due = 0;\n }\n let n = 0;\n return scheduler.schedule(function () {\n if (!subscriber.closed) {\n subscriber.next(n++);\n if (0 <= intervalDuration) {\n this.schedule(undefined, intervalDuration);\n }\n else {\n subscriber.complete();\n }\n }\n }, due);\n });\n}\n//# sourceMappingURL=timer.js.map","export function isValidDate(value) {\n return value instanceof Date && !isNaN(value);\n}\n//# sourceMappingURL=isDate.js.map","import { dateTimestampProvider } from \"./scheduler/dateTimestampProvider\";\nexport class Scheduler {\n constructor(schedulerActionCtor, now = Scheduler.now) {\n this.schedulerActionCtor = schedulerActionCtor;\n this.now = now;\n }\n schedule(work, delay = 0, state) {\n return new this.schedulerActionCtor(this, work).schedule(state, delay);\n }\n}\nScheduler.now = dateTimestampProvider.now;\n//# sourceMappingURL=Scheduler.js.map","import { Scheduler } from '../Scheduler';\nexport class AsyncScheduler extends Scheduler {\n constructor(SchedulerAction, now = Scheduler.now) {\n super(SchedulerAction, now);\n this.actions = [];\n this.active = false;\n this.scheduled = undefined;\n }\n flush(action) {\n const { actions } = this;\n if (this.active) {\n actions.push(action);\n return;\n }\n let error;\n this.active = true;\n do {\n if (error = action.execute(action.state, action.delay)) {\n break;\n }\n } while (action = actions.shift());\n this.active = false;\n if (error) {\n while (action = actions.shift()) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n//# sourceMappingURL=AsyncScheduler.js.map","import { innerFrom } from '../observable/from';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function switchMap(project, resultSelector) {\n return operate((source, subscriber) => {\n let innerSubscriber = null;\n let index = 0;\n let isComplete = false;\n const checkComplete = () => isComplete && !innerSubscriber && subscriber.complete();\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n innerSubscriber === null || innerSubscriber === void 0 ? void 0 : innerSubscriber.unsubscribe();\n let innerIndex = 0;\n const outerIndex = index++;\n innerFrom(project(value, outerIndex)).subscribe((innerSubscriber = new OperatorSubscriber(subscriber, (innerValue) => subscriber.next(resultSelector ? resultSelector(value, innerValue, outerIndex, innerIndex++) : innerValue), undefined, () => {\n innerSubscriber = null;\n checkComplete();\n })));\n }, undefined, () => {\n isComplete = true;\n checkComplete();\n }));\n });\n}\n//# sourceMappingURL=switchMap.js.map","import { EMPTY } from '../observable/empty';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function take(count) {\n return count <= 0\n ?\n () => EMPTY\n : operate((source, subscriber) => {\n let seen = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n if (++seen <= count) {\n subscriber.next(value);\n if (count <= seen) {\n subscriber.complete();\n }\n }\n }));\n });\n}\n//# sourceMappingURL=take.js.map","/*!\n * clipboard.js v2.0.6\n * https://clipboardjs.com/\n * \n * Licensed MIT © Zeno Rocha\n */\n(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"ClipboardJS\"] = factory();\n\telse\n\t\troot[\"ClipboardJS\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 6);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports) {\n\nfunction select(element) {\n var selectedText;\n\n if (element.nodeName === 'SELECT') {\n element.focus();\n\n selectedText = element.value;\n }\n else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {\n var isReadOnly = element.hasAttribute('readonly');\n\n if (!isReadOnly) {\n element.setAttribute('readonly', '');\n }\n\n element.select();\n element.setSelectionRange(0, element.value.length);\n\n if (!isReadOnly) {\n element.removeAttribute('readonly');\n }\n\n selectedText = element.value;\n }\n else {\n if (element.hasAttribute('contenteditable')) {\n element.focus();\n }\n\n var selection = window.getSelection();\n var range = document.createRange();\n\n range.selectNodeContents(element);\n selection.removeAllRanges();\n selection.addRange(range);\n\n selectedText = selection.toString();\n }\n\n return selectedText;\n}\n\nmodule.exports = select;\n\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports) {\n\nfunction E () {\n // Keep this empty so it's easier to inherit from\n // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)\n}\n\nE.prototype = {\n on: function (name, callback, ctx) {\n var e = this.e || (this.e = {});\n\n (e[name] || (e[name] = [])).push({\n fn: callback,\n ctx: ctx\n });\n\n return this;\n },\n\n once: function (name, callback, ctx) {\n var self = this;\n function listener () {\n self.off(name, listener);\n callback.apply(ctx, arguments);\n };\n\n listener._ = callback\n return this.on(name, listener, ctx);\n },\n\n emit: function (name) {\n var data = [].slice.call(arguments, 1);\n var evtArr = ((this.e || (this.e = {}))[name] || []).slice();\n var i = 0;\n var len = evtArr.length;\n\n for (i; i < len; i++) {\n evtArr[i].fn.apply(evtArr[i].ctx, data);\n }\n\n return this;\n },\n\n off: function (name, callback) {\n var e = this.e || (this.e = {});\n var evts = e[name];\n var liveEvents = [];\n\n if (evts && callback) {\n for (var i = 0, len = evts.length; i < len; i++) {\n if (evts[i].fn !== callback && evts[i].fn._ !== callback)\n liveEvents.push(evts[i]);\n }\n }\n\n // Remove event from queue to prevent memory leak\n // Suggested by https://github.com/lazd\n // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910\n\n (liveEvents.length)\n ? e[name] = liveEvents\n : delete e[name];\n\n return this;\n }\n};\n\nmodule.exports = E;\nmodule.exports.TinyEmitter = E;\n\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar is = __webpack_require__(3);\nvar delegate = __webpack_require__(4);\n\n/**\n * Validates all params and calls the right\n * listener function based on its target type.\n *\n * @param {String|HTMLElement|HTMLCollection|NodeList} target\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listen(target, type, callback) {\n if (!target && !type && !callback) {\n throw new Error('Missing required arguments');\n }\n\n if (!is.string(type)) {\n throw new TypeError('Second argument must be a String');\n }\n\n if (!is.fn(callback)) {\n throw new TypeError('Third argument must be a Function');\n }\n\n if (is.node(target)) {\n return listenNode(target, type, callback);\n }\n else if (is.nodeList(target)) {\n return listenNodeList(target, type, callback);\n }\n else if (is.string(target)) {\n return listenSelector(target, type, callback);\n }\n else {\n throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');\n }\n}\n\n/**\n * Adds an event listener to a HTML element\n * and returns a remove listener function.\n *\n * @param {HTMLElement} node\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNode(node, type, callback) {\n node.addEventListener(type, callback);\n\n return {\n destroy: function() {\n node.removeEventListener(type, callback);\n }\n }\n}\n\n/**\n * Add an event listener to a list of HTML elements\n * and returns a remove listener function.\n *\n * @param {NodeList|HTMLCollection} nodeList\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenNodeList(nodeList, type, callback) {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.addEventListener(type, callback);\n });\n\n return {\n destroy: function() {\n Array.prototype.forEach.call(nodeList, function(node) {\n node.removeEventListener(type, callback);\n });\n }\n }\n}\n\n/**\n * Add an event listener to a selector\n * and returns a remove listener function.\n *\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Object}\n */\nfunction listenSelector(selector, type, callback) {\n return delegate(document.body, selector, type, callback);\n}\n\nmodule.exports = listen;\n\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports) {\n\n/**\n * Check if argument is a HTML element.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.node = function(value) {\n return value !== undefined\n && value instanceof HTMLElement\n && value.nodeType === 1;\n};\n\n/**\n * Check if argument is a list of HTML elements.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.nodeList = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return value !== undefined\n && (type === '[object NodeList]' || type === '[object HTMLCollection]')\n && ('length' in value)\n && (value.length === 0 || exports.node(value[0]));\n};\n\n/**\n * Check if argument is a string.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.string = function(value) {\n return typeof value === 'string'\n || value instanceof String;\n};\n\n/**\n * Check if argument is a function.\n *\n * @param {Object} value\n * @return {Boolean}\n */\nexports.fn = function(value) {\n var type = Object.prototype.toString.call(value);\n\n return type === '[object Function]';\n};\n\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar closest = __webpack_require__(5);\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction _delegate(element, selector, type, callback, useCapture) {\n var listenerFn = listener.apply(this, arguments);\n\n element.addEventListener(type, listenerFn, useCapture);\n\n return {\n destroy: function() {\n element.removeEventListener(type, listenerFn, useCapture);\n }\n }\n}\n\n/**\n * Delegates event to a selector.\n *\n * @param {Element|String|Array} [elements]\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @param {Boolean} useCapture\n * @return {Object}\n */\nfunction delegate(elements, selector, type, callback, useCapture) {\n // Handle the regular Element usage\n if (typeof elements.addEventListener === 'function') {\n return _delegate.apply(null, arguments);\n }\n\n // Handle Element-less usage, it defaults to global delegation\n if (typeof type === 'function') {\n // Use `document` as the first parameter, then apply arguments\n // This is a short way to .unshift `arguments` without running into deoptimizations\n return _delegate.bind(null, document).apply(null, arguments);\n }\n\n // Handle Selector-based usage\n if (typeof elements === 'string') {\n elements = document.querySelectorAll(elements);\n }\n\n // Handle Array-like based usage\n return Array.prototype.map.call(elements, function (element) {\n return _delegate(element, selector, type, callback, useCapture);\n });\n}\n\n/**\n * Finds closest match and invokes callback.\n *\n * @param {Element} element\n * @param {String} selector\n * @param {String} type\n * @param {Function} callback\n * @return {Function}\n */\nfunction listener(element, selector, type, callback) {\n return function(e) {\n e.delegateTarget = closest(e.target, selector);\n\n if (e.delegateTarget) {\n callback.call(element, e);\n }\n }\n}\n\nmodule.exports = delegate;\n\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports) {\n\nvar DOCUMENT_NODE_TYPE = 9;\n\n/**\n * A polyfill for Element.matches()\n */\nif (typeof Element !== 'undefined' && !Element.prototype.matches) {\n var proto = Element.prototype;\n\n proto.matches = proto.matchesSelector ||\n proto.mozMatchesSelector ||\n proto.msMatchesSelector ||\n proto.oMatchesSelector ||\n proto.webkitMatchesSelector;\n}\n\n/**\n * Finds the closest parent that matches a selector.\n *\n * @param {Element} element\n * @param {String} selector\n * @return {Function}\n */\nfunction closest (element, selector) {\n while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {\n if (typeof element.matches === 'function' &&\n element.matches(selector)) {\n return element;\n }\n element = element.parentNode;\n }\n}\n\nmodule.exports = closest;\n\n\n/***/ }),\n/* 6 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n__webpack_require__.r(__webpack_exports__);\n\n// EXTERNAL MODULE: ./node_modules/select/src/select.js\nvar src_select = __webpack_require__(0);\nvar select_default = /*#__PURE__*/__webpack_require__.n(src_select);\n\n// CONCATENATED MODULE: ./src/clipboard-action.js\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n\n\n/**\n * Inner class which performs selection from either `text` or `target`\n * properties and then executes copy or cut operations.\n */\n\nvar clipboard_action_ClipboardAction = function () {\n /**\n * @param {Object} options\n */\n function ClipboardAction(options) {\n _classCallCheck(this, ClipboardAction);\n\n this.resolveOptions(options);\n this.initSelection();\n }\n\n /**\n * Defines base properties passed from constructor.\n * @param {Object} options\n */\n\n\n _createClass(ClipboardAction, [{\n key: 'resolveOptions',\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n this.action = options.action;\n this.container = options.container;\n this.emitter = options.emitter;\n this.target = options.target;\n this.text = options.text;\n this.trigger = options.trigger;\n\n this.selectedText = '';\n }\n\n /**\n * Decides which selection strategy is going to be applied based\n * on the existence of `text` and `target` properties.\n */\n\n }, {\n key: 'initSelection',\n value: function initSelection() {\n if (this.text) {\n this.selectFake();\n } else if (this.target) {\n this.selectTarget();\n }\n }\n\n /**\n * Creates a fake textarea element, sets its value from `text` property,\n * and makes a selection on it.\n */\n\n }, {\n key: 'selectFake',\n value: function selectFake() {\n var _this = this;\n\n var isRTL = document.documentElement.getAttribute('dir') == 'rtl';\n\n this.removeFake();\n\n this.fakeHandlerCallback = function () {\n return _this.removeFake();\n };\n this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true;\n\n this.fakeElem = document.createElement('textarea');\n // Prevent zooming on iOS\n this.fakeElem.style.fontSize = '12pt';\n // Reset box model\n this.fakeElem.style.border = '0';\n this.fakeElem.style.padding = '0';\n this.fakeElem.style.margin = '0';\n // Move element out of screen horizontally\n this.fakeElem.style.position = 'absolute';\n this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';\n // Move element to the same position vertically\n var yPosition = window.pageYOffset || document.documentElement.scrollTop;\n this.fakeElem.style.top = yPosition + 'px';\n\n this.fakeElem.setAttribute('readonly', '');\n this.fakeElem.value = this.text;\n\n this.container.appendChild(this.fakeElem);\n\n this.selectedText = select_default()(this.fakeElem);\n this.copyText();\n }\n\n /**\n * Only removes the fake element after another click event, that way\n * a user can hit `Ctrl+C` to copy because selection still exists.\n */\n\n }, {\n key: 'removeFake',\n value: function removeFake() {\n if (this.fakeHandler) {\n this.container.removeEventListener('click', this.fakeHandlerCallback);\n this.fakeHandler = null;\n this.fakeHandlerCallback = null;\n }\n\n if (this.fakeElem) {\n this.container.removeChild(this.fakeElem);\n this.fakeElem = null;\n }\n }\n\n /**\n * Selects the content from element passed on `target` property.\n */\n\n }, {\n key: 'selectTarget',\n value: function selectTarget() {\n this.selectedText = select_default()(this.target);\n this.copyText();\n }\n\n /**\n * Executes the copy operation based on the current selection.\n */\n\n }, {\n key: 'copyText',\n value: function copyText() {\n var succeeded = void 0;\n\n try {\n succeeded = document.execCommand(this.action);\n } catch (err) {\n succeeded = false;\n }\n\n this.handleResult(succeeded);\n }\n\n /**\n * Fires an event based on the copy operation result.\n * @param {Boolean} succeeded\n */\n\n }, {\n key: 'handleResult',\n value: function handleResult(succeeded) {\n this.emitter.emit(succeeded ? 'success' : 'error', {\n action: this.action,\n text: this.selectedText,\n trigger: this.trigger,\n clearSelection: this.clearSelection.bind(this)\n });\n }\n\n /**\n * Moves focus away from `target` and back to the trigger, removes current selection.\n */\n\n }, {\n key: 'clearSelection',\n value: function clearSelection() {\n if (this.trigger) {\n this.trigger.focus();\n }\n document.activeElement.blur();\n window.getSelection().removeAllRanges();\n }\n\n /**\n * Sets the `action` to be performed which can be either 'copy' or 'cut'.\n * @param {String} action\n */\n\n }, {\n key: 'destroy',\n\n\n /**\n * Destroy lifecycle.\n */\n value: function destroy() {\n this.removeFake();\n }\n }, {\n key: 'action',\n set: function set() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy';\n\n this._action = action;\n\n if (this._action !== 'copy' && this._action !== 'cut') {\n throw new Error('Invalid \"action\" value, use either \"copy\" or \"cut\"');\n }\n }\n\n /**\n * Gets the `action` property.\n * @return {String}\n */\n ,\n get: function get() {\n return this._action;\n }\n\n /**\n * Sets the `target` property using an element\n * that will be have its content copied.\n * @param {Element} target\n */\n\n }, {\n key: 'target',\n set: function set(target) {\n if (target !== undefined) {\n if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {\n if (this.action === 'copy' && target.hasAttribute('disabled')) {\n throw new Error('Invalid \"target\" attribute. Please use \"readonly\" instead of \"disabled\" attribute');\n }\n\n if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {\n throw new Error('Invalid \"target\" attribute. You can\\'t cut text from elements with \"readonly\" or \"disabled\" attributes');\n }\n\n this._target = target;\n } else {\n throw new Error('Invalid \"target\" value, use a valid Element');\n }\n }\n }\n\n /**\n * Gets the `target` property.\n * @return {String|HTMLElement}\n */\n ,\n get: function get() {\n return this._target;\n }\n }]);\n\n return ClipboardAction;\n}();\n\n/* harmony default export */ var clipboard_action = (clipboard_action_ClipboardAction);\n// EXTERNAL MODULE: ./node_modules/tiny-emitter/index.js\nvar tiny_emitter = __webpack_require__(1);\nvar tiny_emitter_default = /*#__PURE__*/__webpack_require__.n(tiny_emitter);\n\n// EXTERNAL MODULE: ./node_modules/good-listener/src/listen.js\nvar listen = __webpack_require__(2);\nvar listen_default = /*#__PURE__*/__webpack_require__.n(listen);\n\n// CONCATENATED MODULE: ./src/clipboard.js\nvar clipboard_typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar clipboard_createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction clipboard_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\n\n\n\n\n/**\n * Base class which takes one or more elements, adds event listeners to them,\n * and instantiates a new `ClipboardAction` on each click.\n */\n\nvar clipboard_Clipboard = function (_Emitter) {\n _inherits(Clipboard, _Emitter);\n\n /**\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n * @param {Object} options\n */\n function Clipboard(trigger, options) {\n clipboard_classCallCheck(this, Clipboard);\n\n var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this));\n\n _this.resolveOptions(options);\n _this.listenClick(trigger);\n return _this;\n }\n\n /**\n * Defines if attributes would be resolved using internal setter functions\n * or custom functions that were passed in the constructor.\n * @param {Object} options\n */\n\n\n clipboard_createClass(Clipboard, [{\n key: 'resolveOptions',\n value: function resolveOptions() {\n var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n this.action = typeof options.action === 'function' ? options.action : this.defaultAction;\n this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;\n this.text = typeof options.text === 'function' ? options.text : this.defaultText;\n this.container = clipboard_typeof(options.container) === 'object' ? options.container : document.body;\n }\n\n /**\n * Adds a click event listener to the passed trigger.\n * @param {String|HTMLElement|HTMLCollection|NodeList} trigger\n */\n\n }, {\n key: 'listenClick',\n value: function listenClick(trigger) {\n var _this2 = this;\n\n this.listener = listen_default()(trigger, 'click', function (e) {\n return _this2.onClick(e);\n });\n }\n\n /**\n * Defines a new `ClipboardAction` on each click event.\n * @param {Event} e\n */\n\n }, {\n key: 'onClick',\n value: function onClick(e) {\n var trigger = e.delegateTarget || e.currentTarget;\n\n if (this.clipboardAction) {\n this.clipboardAction = null;\n }\n\n this.clipboardAction = new clipboard_action({\n action: this.action(trigger),\n target: this.target(trigger),\n text: this.text(trigger),\n container: this.container,\n trigger: trigger,\n emitter: this\n });\n }\n\n /**\n * Default `action` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: 'defaultAction',\n value: function defaultAction(trigger) {\n return getAttributeValue('action', trigger);\n }\n\n /**\n * Default `target` lookup function.\n * @param {Element} trigger\n */\n\n }, {\n key: 'defaultTarget',\n value: function defaultTarget(trigger) {\n var selector = getAttributeValue('target', trigger);\n\n if (selector) {\n return document.querySelector(selector);\n }\n }\n\n /**\n * Returns the support of the given action, or all actions if no action is\n * given.\n * @param {String} [action]\n */\n\n }, {\n key: 'defaultText',\n\n\n /**\n * Default `text` lookup function.\n * @param {Element} trigger\n */\n value: function defaultText(trigger) {\n return getAttributeValue('text', trigger);\n }\n\n /**\n * Destroy lifecycle.\n */\n\n }, {\n key: 'destroy',\n value: function destroy() {\n this.listener.destroy();\n\n if (this.clipboardAction) {\n this.clipboardAction.destroy();\n this.clipboardAction = null;\n }\n }\n }], [{\n key: 'isSupported',\n value: function isSupported() {\n var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];\n\n var actions = typeof action === 'string' ? [action] : action;\n var support = !!document.queryCommandSupported;\n\n actions.forEach(function (action) {\n support = support && !!document.queryCommandSupported(action);\n });\n\n return support;\n }\n }]);\n\n return Clipboard;\n}(tiny_emitter_default.a);\n\n/**\n * Helper function to retrieve attribute value.\n * @param {String} suffix\n * @param {Element} element\n */\n\n\nfunction getAttributeValue(suffix, element) {\n var attribute = 'data-clipboard-' + suffix;\n\n if (!element.hasAttribute(attribute)) {\n return;\n }\n\n return element.getAttribute(attribute);\n}\n\n/* harmony default export */ var clipboard = __webpack_exports__[\"default\"] = (clipboard_Clipboard);\n\n/***/ })\n/******/ ])[\"default\"];\n});","import { Subject } from './Subject';\nimport { dateTimestampProvider } from './scheduler/dateTimestampProvider';\nexport class ReplaySubject extends Subject {\n constructor(bufferSize = Infinity, windowTime = Infinity, timestampProvider = dateTimestampProvider) {\n super();\n this.bufferSize = bufferSize;\n this.windowTime = windowTime;\n this.timestampProvider = timestampProvider;\n this.buffer = [];\n this.infiniteTimeWindow = true;\n this.infiniteTimeWindow = windowTime === Infinity;\n this.bufferSize = Math.max(1, bufferSize);\n this.windowTime = Math.max(1, windowTime);\n }\n next(value) {\n const { isStopped, buffer, infiniteTimeWindow, timestampProvider, windowTime } = this;\n if (!isStopped) {\n buffer.push(value);\n !infiniteTimeWindow && buffer.push(timestampProvider.now() + windowTime);\n }\n this.trimBuffer();\n super.next(value);\n }\n _subscribe(subscriber) {\n this._throwIfClosed();\n this.trimBuffer();\n const subscription = this._innerSubscribe(subscriber);\n const { infiniteTimeWindow, buffer } = this;\n const copy = buffer.slice();\n for (let i = 0; i < copy.length && !subscriber.closed; i += infiniteTimeWindow ? 1 : 2) {\n subscriber.next(copy[i]);\n }\n this._checkFinalizedStatuses(subscriber);\n return subscription;\n }\n trimBuffer() {\n const { bufferSize, timestampProvider, buffer, infiniteTimeWindow } = this;\n const adjustedBufferSize = (infiniteTimeWindow ? 1 : 2) * bufferSize;\n bufferSize < Infinity && adjustedBufferSize < buffer.length && buffer.splice(0, buffer.length - adjustedBufferSize);\n if (!infiniteTimeWindow) {\n const now = timestampProvider.now();\n let last = 0;\n for (let i = 1; i < buffer.length && buffer[i] <= now; i += 2) {\n last = i;\n }\n last && buffer.splice(0, last + 1);\n }\n }\n}\n//# sourceMappingURL=ReplaySubject.js.map","import { identity } from './identity';\nexport function pipe(...fns) {\n return pipeFromArray(fns);\n}\nexport function pipeFromArray(fns) {\n if (fns.length === 0) {\n return identity;\n }\n if (fns.length === 1) {\n return fns[0];\n }\n return function piped(input) {\n return fns.reduce((prev, fn) => fn(prev), input);\n };\n}\n//# sourceMappingURL=pipe.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function mapTo(value) {\n return operate((source, subscriber) => {\n source.subscribe(new OperatorSubscriber(subscriber, () => subscriber.next(value)));\n });\n}\n//# sourceMappingURL=mapTo.js.map","import { Observable } from '../Observable';\nimport { innerFrom } from './from';\nexport function defer(observableFactory) {\n return new Observable((subscriber) => {\n innerFrom(observableFactory()).subscribe(subscriber);\n });\n}\n//# sourceMappingURL=defer.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function filter(predicate, thisArg) {\n return operate((source, subscriber) => {\n let index = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => predicate.call(thisArg, value, index++) && subscriber.next(value)));\n });\n}\n//# sourceMappingURL=filter.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function distinctUntilChanged(compare, keySelector) {\n compare = compare !== null && compare !== void 0 ? compare : defaultCompare;\n return operate((source, subscriber) => {\n let prev;\n let first = true;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n ((first && ((prev = value), 1)) || !compare(prev, (prev = keySelector ? keySelector(value) : value))) &&\n subscriber.next(value);\n first = false;\n }));\n });\n}\nfunction defaultCompare(a, b) {\n return a === b;\n}\n//# sourceMappingURL=distinctUntilChanged.js.map","/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n","(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (factory());\n}(this, (function () { 'use strict';\n\n /**\n * Applies the :focus-visible polyfill at the given scope.\n * A scope in this case is either the top-level Document or a Shadow Root.\n *\n * @param {(Document|ShadowRoot)} scope\n * @see https://github.com/WICG/focus-visible\n */\n function applyFocusVisiblePolyfill(scope) {\n var hadKeyboardEvent = true;\n var hadFocusVisibleRecently = false;\n var hadFocusVisibleRecentlyTimeout = null;\n\n var inputTypesAllowlist = {\n text: true,\n search: true,\n url: true,\n tel: true,\n email: true,\n password: true,\n number: true,\n date: true,\n month: true,\n week: true,\n time: true,\n datetime: true,\n 'datetime-local': true\n };\n\n /**\n * Helper function for legacy browsers and iframes which sometimes focus\n * elements like document, body, and non-interactive SVG.\n * @param {Element} el\n */\n function isValidFocusTarget(el) {\n if (\n el &&\n el !== document &&\n el.nodeName !== 'HTML' &&\n el.nodeName !== 'BODY' &&\n 'classList' in el &&\n 'contains' in el.classList\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * Computes whether the given element should automatically trigger the\n * `focus-visible` class being added, i.e. whether it should always match\n * `:focus-visible` when focused.\n * @param {Element} el\n * @return {boolean}\n */\n function focusTriggersKeyboardModality(el) {\n var type = el.type;\n var tagName = el.tagName;\n\n if (tagName === 'INPUT' && inputTypesAllowlist[type] && !el.readOnly) {\n return true;\n }\n\n if (tagName === 'TEXTAREA' && !el.readOnly) {\n return true;\n }\n\n if (el.isContentEditable) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Add the `focus-visible` class to the given element if it was not added by\n * the author.\n * @param {Element} el\n */\n function addFocusVisibleClass(el) {\n if (el.classList.contains('focus-visible')) {\n return;\n }\n el.classList.add('focus-visible');\n el.setAttribute('data-focus-visible-added', '');\n }\n\n /**\n * Remove the `focus-visible` class from the given element if it was not\n * originally added by the author.\n * @param {Element} el\n */\n function removeFocusVisibleClass(el) {\n if (!el.hasAttribute('data-focus-visible-added')) {\n return;\n }\n el.classList.remove('focus-visible');\n el.removeAttribute('data-focus-visible-added');\n }\n\n /**\n * If the most recent user interaction was via the keyboard;\n * and the key press did not include a meta, alt/option, or control key;\n * then the modality is keyboard. Otherwise, the modality is not keyboard.\n * Apply `focus-visible` to any current active element and keep track\n * of our keyboard modality state with `hadKeyboardEvent`.\n * @param {KeyboardEvent} e\n */\n function onKeyDown(e) {\n if (e.metaKey || e.altKey || e.ctrlKey) {\n return;\n }\n\n if (isValidFocusTarget(scope.activeElement)) {\n addFocusVisibleClass(scope.activeElement);\n }\n\n hadKeyboardEvent = true;\n }\n\n /**\n * If at any point a user clicks with a pointing device, ensure that we change\n * the modality away from keyboard.\n * This avoids the situation where a user presses a key on an already focused\n * element, and then clicks on a different element, focusing it with a\n * pointing device, while we still think we're in keyboard modality.\n * @param {Event} e\n */\n function onPointerDown(e) {\n hadKeyboardEvent = false;\n }\n\n /**\n * On `focus`, add the `focus-visible` class to the target if:\n * - the target received focus as a result of keyboard navigation, or\n * - the event target is an element that will likely require interaction\n * via the keyboard (e.g. a text box)\n * @param {Event} e\n */\n function onFocus(e) {\n // Prevent IE from focusing the document or HTML element.\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (hadKeyboardEvent || focusTriggersKeyboardModality(e.target)) {\n addFocusVisibleClass(e.target);\n }\n }\n\n /**\n * On `blur`, remove the `focus-visible` class from the target.\n * @param {Event} e\n */\n function onBlur(e) {\n if (!isValidFocusTarget(e.target)) {\n return;\n }\n\n if (\n e.target.classList.contains('focus-visible') ||\n e.target.hasAttribute('data-focus-visible-added')\n ) {\n // To detect a tab/window switch, we look for a blur event followed\n // rapidly by a visibility change.\n // If we don't see a visibility change within 100ms, it's probably a\n // regular focus change.\n hadFocusVisibleRecently = true;\n window.clearTimeout(hadFocusVisibleRecentlyTimeout);\n hadFocusVisibleRecentlyTimeout = window.setTimeout(function() {\n hadFocusVisibleRecently = false;\n }, 100);\n removeFocusVisibleClass(e.target);\n }\n }\n\n /**\n * If the user changes tabs, keep track of whether or not the previously\n * focused element had .focus-visible.\n * @param {Event} e\n */\n function onVisibilityChange(e) {\n if (document.visibilityState === 'hidden') {\n // If the tab becomes active again, the browser will handle calling focus\n // on the element (Safari actually calls it twice).\n // If this tab change caused a blur on an element with focus-visible,\n // re-apply the class when the user switches back to the tab.\n if (hadFocusVisibleRecently) {\n hadKeyboardEvent = true;\n }\n addInitialPointerMoveListeners();\n }\n }\n\n /**\n * Add a group of listeners to detect usage of any pointing devices.\n * These listeners will be added when the polyfill first loads, and anytime\n * the window is blurred, so that they are active when the window regains\n * focus.\n */\n function addInitialPointerMoveListeners() {\n document.addEventListener('mousemove', onInitialPointerMove);\n document.addEventListener('mousedown', onInitialPointerMove);\n document.addEventListener('mouseup', onInitialPointerMove);\n document.addEventListener('pointermove', onInitialPointerMove);\n document.addEventListener('pointerdown', onInitialPointerMove);\n document.addEventListener('pointerup', onInitialPointerMove);\n document.addEventListener('touchmove', onInitialPointerMove);\n document.addEventListener('touchstart', onInitialPointerMove);\n document.addEventListener('touchend', onInitialPointerMove);\n }\n\n function removeInitialPointerMoveListeners() {\n document.removeEventListener('mousemove', onInitialPointerMove);\n document.removeEventListener('mousedown', onInitialPointerMove);\n document.removeEventListener('mouseup', onInitialPointerMove);\n document.removeEventListener('pointermove', onInitialPointerMove);\n document.removeEventListener('pointerdown', onInitialPointerMove);\n document.removeEventListener('pointerup', onInitialPointerMove);\n document.removeEventListener('touchmove', onInitialPointerMove);\n document.removeEventListener('touchstart', onInitialPointerMove);\n document.removeEventListener('touchend', onInitialPointerMove);\n }\n\n /**\n * When the polfyill first loads, assume the user is in keyboard modality.\n * If any event is received from a pointing device (e.g. mouse, pointer,\n * touch), turn off keyboard modality.\n * This accounts for situations where focus enters the page from the URL bar.\n * @param {Event} e\n */\n function onInitialPointerMove(e) {\n // Work around a Safari quirk that fires a mousemove on whenever the\n // window blurs, even if you're tabbing out of the page. ¯\\_(ツ)_/¯\n if (e.target.nodeName && e.target.nodeName.toLowerCase() === 'html') {\n return;\n }\n\n hadKeyboardEvent = false;\n removeInitialPointerMoveListeners();\n }\n\n // For some kinds of state, we are interested in changes at the global scope\n // only. For example, global pointer input, global key presses and global\n // visibility change should affect the state at every scope:\n document.addEventListener('keydown', onKeyDown, true);\n document.addEventListener('mousedown', onPointerDown, true);\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('touchstart', onPointerDown, true);\n document.addEventListener('visibilitychange', onVisibilityChange, true);\n\n addInitialPointerMoveListeners();\n\n // For focus and blur, we specifically care about state changes in the local\n // scope. This is because focus / blur events that originate from within a\n // shadow root are not re-dispatched from the host element if it was already\n // the active element in its own scope:\n scope.addEventListener('focus', onFocus, true);\n scope.addEventListener('blur', onBlur, true);\n\n // We detect that a node is a ShadowRoot by ensuring that it is a\n // DocumentFragment and also has a host property. This check covers native\n // implementation and polyfill implementation transparently. If we only cared\n // about the native implementation, we could just check if the scope was\n // an instance of a ShadowRoot.\n if (scope.nodeType === Node.DOCUMENT_FRAGMENT_NODE && scope.host) {\n // Since a ShadowRoot is a special kind of DocumentFragment, it does not\n // have a root element to add a class to. So, we add this attribute to the\n // host element instead:\n scope.host.setAttribute('data-js-focus-visible', '');\n } else if (scope.nodeType === Node.DOCUMENT_NODE) {\n document.documentElement.classList.add('js-focus-visible');\n document.documentElement.setAttribute('data-js-focus-visible', '');\n }\n }\n\n // It is important to wrap all references to global window and document in\n // these checks to support server-side rendering use cases\n // @see https://github.com/WICG/focus-visible/issues/199\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n // Make the polyfill helper globally available. This can be used as a signal\n // to interested libraries that wish to coordinate with the polyfill for e.g.,\n // applying the polyfill to a shadow root:\n window.applyFocusVisiblePolyfill = applyFocusVisiblePolyfill;\n\n // Notify interested libraries of the polyfill's presence, in case the\n // polyfill was loaded lazily:\n var event;\n\n try {\n event = new CustomEvent('focus-visible-polyfill-ready');\n } catch (error) {\n // IE11 does not support using CustomEvent as a constructor directly:\n event = document.createEvent('CustomEvent');\n event.initCustomEvent('focus-visible-polyfill-ready', false, false, {});\n }\n\n window.dispatchEvent(event);\n }\n\n if (typeof document !== 'undefined') {\n // Apply the polyfill to the global document, so that no JavaScript\n // coordination is required to use the polyfill in the top-level document:\n applyFocusVisiblePolyfill(document);\n }\n\n})));\n","import { Observable } from '../Observable';\nimport { mergeMap } from '../operators/mergeMap';\nimport { isArrayLike } from '../util/isArrayLike';\nimport { isFunction } from '../util/isFunction';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs';\nimport { internalFromArray } from './fromArray';\nconst nodeEventEmitterMethods = ['addListener', 'removeListener'];\nconst eventTargetMethods = ['addEventListener', 'removeEventListener'];\nconst jqueryMethods = ['on', 'off'];\nexport function fromEvent(target, eventName, options, resultSelector) {\n if (isFunction(options)) {\n resultSelector = options;\n options = undefined;\n }\n if (resultSelector) {\n return fromEvent(target, eventName, options).pipe(mapOneOrManyArgs(resultSelector));\n }\n const [add, remove] = isEventTarget(target)\n ? eventTargetMethods.map((methodName) => (handler) => target[methodName](eventName, handler, options))\n :\n isNodeStyleEventEmitter(target)\n ? nodeEventEmitterMethods.map(toCommonHandlerRegistry(target, eventName))\n : isJQueryStyleEventEmitter(target)\n ? jqueryMethods.map(toCommonHandlerRegistry(target, eventName))\n : [];\n if (!add) {\n if (isArrayLike(target)) {\n return mergeMap((subTarget) => fromEvent(subTarget, eventName, options))(internalFromArray(target));\n }\n }\n return new Observable((subscriber) => {\n if (!add) {\n throw new TypeError('Invalid event target');\n }\n const handler = (...args) => subscriber.next(1 < args.length ? args : args[0]);\n add(handler);\n return () => remove(handler);\n });\n}\nfunction toCommonHandlerRegistry(target, eventName) {\n return (methodName) => (handler) => target[methodName](eventName, handler);\n}\nfunction isNodeStyleEventEmitter(target) {\n return isFunction(target.addListener) && isFunction(target.removeListener);\n}\nfunction isJQueryStyleEventEmitter(target) {\n return isFunction(target.on) && isFunction(target.off);\n}\nfunction isEventTarget(target) {\n return isFunction(target.addEventListener) && isFunction(target.removeEventListener);\n}\n//# sourceMappingURL=fromEvent.js.map","import { mergeAll } from '../operators/mergeAll';\nimport { internalFromArray } from './fromArray';\nimport { argsOrArgArray } from '../util/argsOrArgArray';\nimport { innerFrom } from './from';\nimport { EMPTY } from './empty';\nimport { popNumber, popScheduler } from '../util/args';\nexport function merge(...args) {\n const scheduler = popScheduler(args);\n const concurrent = popNumber(args, Infinity);\n const sources = argsOrArgArray(args);\n return !sources.length\n ?\n EMPTY\n : sources.length === 1\n ?\n innerFrom(sources[0])\n :\n mergeAll(concurrent)(internalFromArray(sources, scheduler));\n}\n//# sourceMappingURL=merge.js.map","import { concat } from '../observable/concat';\nimport { popScheduler } from '../util/args';\nimport { operate } from '../util/lift';\nexport function startWith(...values) {\n const scheduler = popScheduler(values);\n return operate((source, subscriber) => {\n (scheduler ? concat(values, source, scheduler) : concat(values, source)).subscribe(subscriber);\n });\n}\n//# sourceMappingURL=startWith.js.map","import { internalFromArray } from './fromArray';\nimport { scheduleArray } from '../scheduled/scheduleArray';\nimport { popScheduler } from '../util/args';\nexport function of(...args) {\n const scheduler = popScheduler(args);\n return scheduler ? scheduleArray(args, scheduler) : internalFromArray(args);\n}\n//# sourceMappingURL=of.js.map","import { Observable } from '../Observable';\nimport { noop } from '../util/noop';\nexport const NEVER = new Observable(noop);\nexport function never() {\n return NEVER;\n}\n//# sourceMappingURL=never.js.map","import { operate } from '../util/lift';\nexport function finalize(callback) {\n return operate((source, subscriber) => {\n source.subscribe(subscriber);\n subscriber.add(callback);\n });\n}\n//# sourceMappingURL=finalize.js.map","import { ReplaySubject } from '../ReplaySubject';\nimport { operate } from '../util/lift';\nexport function shareReplay(configOrBufferSize, windowTime, scheduler) {\n let config;\n if (configOrBufferSize && typeof configOrBufferSize === 'object') {\n config = configOrBufferSize;\n }\n else {\n config = {\n bufferSize: configOrBufferSize,\n windowTime,\n refCount: false,\n scheduler\n };\n }\n return operate(shareReplayOperator(config));\n}\nfunction shareReplayOperator({ bufferSize = Infinity, windowTime = Infinity, refCount: useRefCount, scheduler }) {\n let subject;\n let refCount = 0;\n let subscription;\n return (source, subscriber) => {\n refCount++;\n let innerSub;\n if (!subject) {\n subject = new ReplaySubject(bufferSize, windowTime, scheduler);\n innerSub = subject.subscribe(subscriber);\n subscription = source.subscribe({\n next(value) { subject.next(value); },\n error(err) {\n const dest = subject;\n subscription = undefined;\n subject = undefined;\n dest.error(err);\n },\n complete() {\n subscription = undefined;\n subject.complete();\n },\n });\n if (subscription.closed) {\n subscription = undefined;\n }\n }\n else {\n innerSub = subject.subscribe(subscriber);\n }\n subscriber.add(() => {\n refCount--;\n innerSub.unsubscribe();\n if (useRefCount && refCount === 0 && subscription) {\n subscription.unsubscribe();\n subscription = undefined;\n subject = undefined;\n }\n });\n };\n}\n//# sourceMappingURL=shareReplay.js.map","import { isFunction } from '../util/isFunction';\nimport { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { identity } from '../util/identity';\nexport function tap(observerOrNext, error, complete) {\n const tapObserver = isFunction(observerOrNext) || error || complete ? { next: observerOrNext, error, complete } : observerOrNext;\n return tapObserver\n ? operate((source, subscriber) => {\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n var _a;\n (_a = tapObserver.next) === null || _a === void 0 ? void 0 : _a.call(tapObserver, value);\n subscriber.next(value);\n }, (err) => {\n var _a;\n (_a = tapObserver.error) === null || _a === void 0 ? void 0 : _a.call(tapObserver, err);\n subscriber.error(err);\n }, () => {\n var _a;\n (_a = tapObserver.complete) === null || _a === void 0 ? void 0 : _a.call(tapObserver);\n subscriber.complete();\n }));\n })\n :\n identity;\n}\n//# sourceMappingURL=tap.js.map","import { Subject } from './Subject';\nexport class BehaviorSubject extends Subject {\n constructor(_value) {\n super();\n this._value = _value;\n }\n get value() {\n return this.getValue();\n }\n _subscribe(subscriber) {\n const subscription = super._subscribe(subscriber);\n !subscription.closed && subscriber.next(this._value);\n return subscription;\n }\n getValue() {\n const { hasError, thrownError, _value } = this;\n if (hasError) {\n throw thrownError;\n }\n this._throwIfClosed();\n return _value;\n }\n next(value) {\n super.next((this._value = value));\n }\n}\n//# sourceMappingURL=BehaviorSubject.js.map","import { distinctUntilChanged } from './distinctUntilChanged';\nexport function distinctUntilKeyChanged(key, compare) {\n return distinctUntilChanged((x, y) => compare ? compare(x[key], y[key]) : x[key] === y[key]);\n}\n//# sourceMappingURL=distinctUntilKeyChanged.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/from';\nexport const defaultThrottleConfig = {\n leading: true,\n trailing: false,\n};\nexport function throttle(durationSelector, { leading, trailing } = defaultThrottleConfig) {\n return operate((source, subscriber) => {\n let hasValue = false;\n let sendValue = null;\n let throttled = null;\n let isComplete = false;\n const endThrottling = () => {\n throttled === null || throttled === void 0 ? void 0 : throttled.unsubscribe();\n throttled = null;\n if (trailing) {\n send();\n isComplete && subscriber.complete();\n }\n };\n const cleanupThrottling = () => {\n throttled = null;\n isComplete && subscriber.complete();\n };\n const startThrottle = (value) => (throttled = innerFrom(durationSelector(value)).subscribe(new OperatorSubscriber(subscriber, endThrottling, undefined, cleanupThrottling)));\n const send = () => {\n if (hasValue) {\n subscriber.next(sendValue);\n !isComplete && startThrottle(sendValue);\n }\n hasValue = false;\n sendValue = null;\n };\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n hasValue = true;\n sendValue = value;\n !(throttled && !throttled.closed) && (leading ? send() : startThrottle(value));\n }, undefined, () => {\n isComplete = true;\n !(trailing && hasValue && throttled && !throttled.closed) && subscriber.complete();\n }));\n });\n}\n//# sourceMappingURL=throttle.js.map","import { switchMap } from './switchMap';\nexport function switchMapTo(innerObservable, resultSelector) {\n return resultSelector ? switchMap(() => innerObservable, resultSelector) : switchMap(() => innerObservable);\n}\n//# sourceMappingURL=switchMapTo.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function observeOn(scheduler, delay = 0) {\n return operate((source, subscriber) => {\n source.subscribe(new OperatorSubscriber(subscriber, (value) => subscriber.add(scheduler.schedule(() => subscriber.next(value), delay)), (err) => subscriber.add(scheduler.schedule(() => subscriber.error(err), delay)), () => subscriber.add(scheduler.schedule(() => subscriber.complete(), delay))));\n });\n}\n//# sourceMappingURL=observeOn.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/from';\nimport { identity } from '../util/identity';\nimport { noop } from '../util/noop';\nimport { popResultSelector } from '../util/args';\nexport function withLatestFrom(...inputs) {\n const project = popResultSelector(inputs);\n return operate((source, subscriber) => {\n const len = inputs.length;\n const otherValues = new Array(len);\n let hasValue = inputs.map(() => false);\n let ready = false;\n for (let i = 0; i < len; i++) {\n innerFrom(inputs[i]).subscribe(new OperatorSubscriber(subscriber, (value) => {\n otherValues[i] = value;\n if (!ready && !hasValue[i]) {\n hasValue[i] = true;\n (ready = hasValue.every(identity)) && (hasValue = null);\n }\n }, undefined, noop));\n }\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n if (ready) {\n const values = [value, ...otherValues];\n subscriber.next(project ? project(...values) : values);\n }\n }));\n });\n}\n//# sourceMappingURL=withLatestFrom.js.map","import { operate } from '../util/lift';\nimport { noop } from '../util/noop';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function sample(notifier) {\n return operate((source, subscriber) => {\n let hasValue = false;\n let lastValue = null;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n hasValue = true;\n lastValue = value;\n }));\n const emit = () => {\n if (hasValue) {\n hasValue = false;\n const value = lastValue;\n lastValue = null;\n subscriber.next(value);\n }\n };\n notifier.subscribe(new OperatorSubscriber(subscriber, emit, undefined, noop));\n });\n}\n//# sourceMappingURL=sample.js.map","import { filter } from './filter';\nexport function skip(count) {\n return filter((_, index) => count <= index);\n}\n//# sourceMappingURL=skip.js.map","import { innerFrom } from '../observable/from';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { operate } from '../util/lift';\nexport function catchError(selector) {\n return operate((source, subscriber) => {\n let innerSub = null;\n let syncUnsub = false;\n let handledResult;\n innerSub = source.subscribe(new OperatorSubscriber(subscriber, undefined, (err) => {\n handledResult = innerFrom(selector(err, catchError(selector)(source)));\n if (innerSub) {\n innerSub.unsubscribe();\n innerSub = null;\n handledResult.subscribe(subscriber);\n }\n else {\n syncUnsub = true;\n }\n }));\n if (syncUnsub) {\n innerSub.unsubscribe();\n innerSub = null;\n handledResult.subscribe(subscriber);\n }\n });\n}\n//# sourceMappingURL=catchError.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { arrRemove } from '../util/arrRemove';\nexport function bufferCount(bufferSize, startBufferEvery = null) {\n startBufferEvery = startBufferEvery !== null && startBufferEvery !== void 0 ? startBufferEvery : bufferSize;\n return operate((source, subscriber) => {\n let buffers = [];\n let count = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n let toEmit = null;\n if (count++ % startBufferEvery === 0) {\n buffers.push([]);\n }\n for (const buffer of buffers) {\n buffer.push(value);\n if (bufferSize <= buffer.length) {\n toEmit = toEmit !== null && toEmit !== void 0 ? toEmit : [];\n toEmit.push(buffer);\n }\n }\n if (toEmit) {\n for (const buffer of toEmit) {\n arrRemove(buffers, buffer);\n subscriber.next(buffer);\n }\n }\n }, undefined, () => {\n for (const buffer of buffers) {\n subscriber.next(buffer);\n }\n subscriber.complete();\n }, () => {\n buffers = null;\n }));\n });\n}\n//# sourceMappingURL=bufferCount.js.map","import { mergeMap } from './mergeMap';\nimport { isFunction } from '../util/isFunction';\nexport function concatMap(project, resultSelector) {\n return isFunction(resultSelector) ? mergeMap(project, resultSelector, 1) : mergeMap(project, 1);\n}\n//# sourceMappingURL=concatMap.js.map","import { defer } from './defer';\nexport function iif(condition, trueResult, falseResult) {\n return defer(() => (condition() ? trueResult : falseResult));\n}\n//# sourceMappingURL=iif.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function defaultIfEmpty(defaultValue = null) {\n return operate((source, subscriber) => {\n let hasValue = false;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n hasValue = true;\n subscriber.next(value);\n }, undefined, () => {\n if (!hasValue) {\n subscriber.next(defaultValue);\n }\n subscriber.complete();\n }));\n });\n}\n//# sourceMappingURL=defaultIfEmpty.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nexport function refCount() {\n return operate((source, subscriber) => {\n let connection = null;\n source._refCount++;\n const refCounter = new OperatorSubscriber(subscriber, undefined, undefined, undefined, () => {\n if (!source || source._refCount <= 0 || 0 < --source._refCount) {\n connection = null;\n return;\n }\n const sharedConnection = source._connection;\n const conn = connection;\n connection = null;\n if (sharedConnection && (!conn || sharedConnection === conn)) {\n sharedConnection.unsubscribe();\n }\n subscriber.unsubscribe();\n });\n source.subscribe(refCounter);\n if (!refCounter.closed) {\n connection = source.connect();\n }\n });\n}\n//# sourceMappingURL=refCount.js.map","import { Observable } from '../Observable';\nimport { Subscription } from '../Subscription';\nimport { refCount as higherOrderRefCount } from '../operators/refCount';\nimport { OperatorSubscriber } from '../operators/OperatorSubscriber';\nexport class ConnectableObservable extends Observable {\n constructor(source, subjectFactory) {\n super();\n this.source = source;\n this.subjectFactory = subjectFactory;\n this._subject = null;\n this._refCount = 0;\n this._connection = null;\n }\n _subscribe(subscriber) {\n return this.getSubject().subscribe(subscriber);\n }\n getSubject() {\n const subject = this._subject;\n if (!subject || subject.isStopped) {\n this._subject = this.subjectFactory();\n }\n return this._subject;\n }\n _teardown() {\n this._refCount = 0;\n const { _connection } = this;\n this._subject = this._connection = null;\n _connection === null || _connection === void 0 ? void 0 : _connection.unsubscribe();\n }\n connect() {\n let connection = this._connection;\n if (!connection) {\n connection = this._connection = new Subscription();\n const subject = this.getSubject();\n connection.add(this.source.subscribe(new OperatorSubscriber(subject, undefined, (err) => {\n this._teardown();\n subject.error(err);\n }, () => {\n this._teardown();\n subject.complete();\n }, () => this._teardown())));\n if (connection.closed) {\n this._connection = null;\n connection = Subscription.EMPTY;\n }\n }\n return connection;\n }\n refCount() {\n return higherOrderRefCount()(this);\n }\n}\n//# sourceMappingURL=ConnectableObservable.js.map","import { multicast } from './multicast';\nimport { refCount } from './refCount';\nimport { Subject } from '../Subject';\nfunction shareSubjectFactory() {\n return new Subject();\n}\nexport function share() {\n return (source) => refCount()(multicast(shareSubjectFactory)(source));\n}\n//# sourceMappingURL=share.js.map","import { ConnectableObservable } from '../observable/ConnectableObservable';\nimport { hasLift, operate } from '../util/lift';\nimport { isFunction } from '../util/isFunction';\nexport function multicast(subjectOrSubjectFactory, selector) {\n const subjectFactory = isFunction(subjectOrSubjectFactory) ? subjectOrSubjectFactory : () => subjectOrSubjectFactory;\n if (isFunction(selector)) {\n return operate((source, subscriber) => {\n const subject = subjectFactory();\n selector(subject).subscribe(subscriber).add(source.subscribe(subject));\n });\n }\n return (source) => {\n const connectable = new ConnectableObservable(source, subjectFactory);\n if (hasLift(source)) {\n connectable.lift = source.lift;\n }\n connectable.source = source;\n connectable.subjectFactory = subjectFactory;\n return connectable;\n };\n}\n//# sourceMappingURL=multicast.js.map","import { Subscription } from '../Subscription';\nexport const animationFrameProvider = {\n schedule(callback) {\n let request = requestAnimationFrame;\n let cancel = cancelAnimationFrame;\n const { delegate } = animationFrameProvider;\n if (delegate) {\n request = delegate.requestAnimationFrame;\n cancel = delegate.cancelAnimationFrame;\n }\n const handle = request((timestamp) => {\n cancel = undefined;\n callback(timestamp);\n });\n return new Subscription(() => cancel === null || cancel === void 0 ? void 0 : cancel(handle));\n },\n requestAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.requestAnimationFrame) || requestAnimationFrame)(...args);\n },\n cancelAnimationFrame(...args) {\n const { delegate } = animationFrameProvider;\n return ((delegate === null || delegate === void 0 ? void 0 : delegate.cancelAnimationFrame) || cancelAnimationFrame)(...args);\n },\n delegate: undefined,\n};\n//# sourceMappingURL=animationFrameProvider.js.map","import { AsyncAction } from './AsyncAction';\nimport { animationFrameProvider } from './animationFrameProvider';\nexport class AnimationFrameAction extends AsyncAction {\n constructor(scheduler, work) {\n super(scheduler, work);\n this.scheduler = scheduler;\n this.work = work;\n }\n requestAsyncId(scheduler, id, delay = 0) {\n if (delay !== null && delay > 0) {\n return super.requestAsyncId(scheduler, id, delay);\n }\n scheduler.actions.push(this);\n return scheduler.scheduled || (scheduler.scheduled = animationFrameProvider.requestAnimationFrame(() => scheduler.flush(undefined)));\n }\n recycleAsyncId(scheduler, id, delay = 0) {\n if ((delay != null && delay > 0) || (delay == null && this.delay > 0)) {\n return super.recycleAsyncId(scheduler, id, delay);\n }\n if (scheduler.actions.length === 0) {\n animationFrameProvider.cancelAnimationFrame(id);\n scheduler.scheduled = undefined;\n }\n return undefined;\n }\n}\n//# sourceMappingURL=AnimationFrameAction.js.map","import { AsyncScheduler } from './AsyncScheduler';\nexport class AnimationFrameScheduler extends AsyncScheduler {\n flush(action) {\n this.active = true;\n this.scheduled = undefined;\n const { actions } = this;\n let error;\n let index = -1;\n action = action || actions.shift();\n const count = actions.length;\n do {\n if (error = action.execute(action.state, action.delay)) {\n break;\n }\n } while (++index < count && (action = actions.shift()));\n this.active = false;\n if (error) {\n while (++index < count && (action = actions.shift())) {\n action.unsubscribe();\n }\n throw error;\n }\n }\n}\n//# sourceMappingURL=AnimationFrameScheduler.js.map","import { AnimationFrameAction } from './AnimationFrameAction';\nimport { AnimationFrameScheduler } from './AnimationFrameScheduler';\nexport const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);\nexport const animationFrame = animationFrameScheduler;\n//# sourceMappingURL=animationFrame.js.map","import { concat } from '../observable/concat';\nimport { take } from './take';\nimport { ignoreElements } from './ignoreElements';\nimport { mapTo } from './mapTo';\nimport { mergeMap } from './mergeMap';\nexport function delayWhen(delayDurationSelector, subscriptionDelay) {\n if (subscriptionDelay) {\n return (source) => concat(subscriptionDelay.pipe(take(1), ignoreElements()), source.pipe(delayWhen(delayDurationSelector)));\n }\n return mergeMap((value, index) => delayDurationSelector(value, index).pipe(take(1), mapTo(value)));\n}\n//# sourceMappingURL=delayWhen.js.map","import { operate } from '../util/lift';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { noop } from '../util/noop';\nexport function ignoreElements() {\n return operate((source, subscriber) => {\n source.subscribe(new OperatorSubscriber(subscriber, noop));\n });\n}\n//# sourceMappingURL=ignoreElements.js.map","import { asyncScheduler } from '../scheduler/async';\nimport { delayWhen } from './delayWhen';\nimport { timer } from '../observable/timer';\nexport function delay(due, scheduler = asyncScheduler) {\n const duration = timer(due, scheduler);\n return delayWhen(() => duration);\n}\n//# sourceMappingURL=delay.js.map","const { isArray } = Array;\nconst { getPrototypeOf, prototype: objectProto, keys: getKeys } = Object;\nexport function argsArgArrayOrObject(args) {\n if (args.length === 1) {\n const first = args[0];\n if (isArray(first)) {\n return { args: first, keys: null };\n }\n if (isPOJO(first)) {\n const keys = getKeys(first);\n return {\n args: keys.map((key) => first[key]),\n keys,\n };\n }\n }\n return { args: args, keys: null };\n}\nfunction isPOJO(obj) {\n return obj && typeof obj === 'object' && getPrototypeOf(obj) === objectProto;\n}\n//# sourceMappingURL=argsArgArrayOrObject.js.map","import { Observable } from '../Observable';\nimport { argsArgArrayOrObject } from '../util/argsArgArrayOrObject';\nimport { Subscriber } from '../Subscriber';\nimport { from } from './from';\nimport { identity } from '../util/identity';\nimport { mapOneOrManyArgs } from '../util/mapOneOrManyArgs';\nimport { popResultSelector, popScheduler } from '../util/args';\nexport function combineLatest(...args) {\n const scheduler = popScheduler(args);\n const resultSelector = popResultSelector(args);\n const { args: observables, keys } = argsArgArrayOrObject(args);\n const result = new Observable(combineLatestInit(observables, scheduler, keys\n ?\n (values) => {\n const value = {};\n for (let i = 0; i < values.length; i++) {\n value[keys[i]] = values[i];\n }\n return value;\n }\n :\n identity));\n if (resultSelector) {\n return result.pipe(mapOneOrManyArgs(resultSelector));\n }\n return result;\n}\nclass CombineLatestSubscriber extends Subscriber {\n constructor(destination, _next, shouldComplete) {\n super(destination);\n this._next = _next;\n this.shouldComplete = shouldComplete;\n }\n _complete() {\n if (this.shouldComplete()) {\n super._complete();\n }\n else {\n this.unsubscribe();\n }\n }\n}\nexport function combineLatestInit(observables, scheduler, valueTransform = identity) {\n return (subscriber) => {\n const primarySubscribe = () => {\n const { length } = observables;\n const values = new Array(length);\n let active = length;\n const hasValues = observables.map(() => false);\n let waitingForFirstValues = true;\n const emit = () => subscriber.next(valueTransform(values.slice()));\n for (let i = 0; i < length; i++) {\n const subscribe = () => {\n const source = from(observables[i], scheduler);\n source.subscribe(new CombineLatestSubscriber(subscriber, (value) => {\n values[i] = value;\n if (waitingForFirstValues) {\n hasValues[i] = true;\n waitingForFirstValues = !hasValues.every(identity);\n }\n if (!waitingForFirstValues) {\n emit();\n }\n }, () => --active === 0));\n };\n maybeSchedule(scheduler, subscribe, subscriber);\n }\n };\n maybeSchedule(scheduler, primarySubscribe, subscriber);\n };\n}\nfunction maybeSchedule(scheduler, execute, subscription) {\n if (scheduler) {\n subscription.add(scheduler.schedule(execute));\n }\n else {\n execute();\n }\n}\n//# sourceMappingURL=combineLatest.js.map","import { OperatorSubscriber } from './OperatorSubscriber';\nexport function scanInternals(accumulator, seed, hasSeed, emitOnNext, emitBeforeComplete) {\n return (source, subscriber) => {\n let hasState = hasSeed;\n let state = seed;\n let index = 0;\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n const i = index++;\n state = hasState\n ?\n accumulator(state, value, i)\n :\n ((hasState = true), value);\n emitOnNext && subscriber.next(state);\n }, undefined, emitBeforeComplete &&\n (() => {\n hasState && subscriber.next(state);\n subscriber.complete();\n })));\n };\n}\n//# sourceMappingURL=scanInternals.js.map","import { operate } from '../util/lift';\nimport { scanInternals } from './scanInternals';\nexport function scan(accumulator, seed) {\n return operate(scanInternals(accumulator, seed, arguments.length >= 2, true));\n}\n//# sourceMappingURL=scan.js.map","import { zip as zipStatic } from '../observable/zip';\nimport { operate } from '../util/lift';\nexport function zip(...sources) {\n return operate((source, subscriber) => {\n zipStatic(source, ...sources).subscribe(subscriber);\n });\n}\nexport function zipWith(...otherInputs) {\n return zip(...otherInputs);\n}\n//# sourceMappingURL=zipWith.js.map","import { Observable } from '../Observable';\nimport { innerFrom } from './from';\nimport { argsOrArgArray } from '../util/argsOrArgArray';\nimport { EMPTY } from './empty';\nimport { OperatorSubscriber } from '../operators/OperatorSubscriber';\nimport { popResultSelector } from '../util/args';\nexport function zip(...args) {\n const resultSelector = popResultSelector(args);\n const sources = argsOrArgArray(args);\n return sources.length\n ? new Observable((subscriber) => {\n let buffers = sources.map(() => []);\n let completed = sources.map(() => false);\n subscriber.add(() => {\n buffers = completed = null;\n });\n for (let sourceIndex = 0; !subscriber.closed && sourceIndex < sources.length; sourceIndex++) {\n innerFrom(sources[sourceIndex]).subscribe(new OperatorSubscriber(subscriber, (value) => {\n buffers[sourceIndex].push(value);\n if (buffers.every((buffer) => buffer.length)) {\n const result = buffers.map((buffer) => buffer.shift());\n subscriber.next(resultSelector ? resultSelector(...result) : result);\n if (buffers.some((buffer, i) => !buffer.length && completed[i])) {\n subscriber.complete();\n }\n }\n }, undefined, () => {\n completed[sourceIndex] = true;\n !buffers[sourceIndex].length && subscriber.complete();\n }));\n }\n return () => {\n buffers = completed = null;\n };\n })\n : EMPTY;\n}\n//# sourceMappingURL=zip.js.map","import { asyncScheduler } from '../scheduler/async';\nimport { debounce } from './debounce';\nimport { timer } from '../observable/timer';\nexport function debounceTime(dueTime, scheduler = asyncScheduler) {\n const duration = timer(dueTime, scheduler);\n return debounce(() => duration);\n}\n//# sourceMappingURL=debounceTime.js.map","import { operate } from '../util/lift';\nimport { noop } from '../util/noop';\nimport { OperatorSubscriber } from './OperatorSubscriber';\nimport { innerFrom } from '../observable/from';\nexport function debounce(durationSelector) {\n return operate((source, subscriber) => {\n let hasValue = false;\n let lastValue = null;\n let durationSubscriber = null;\n const emit = () => {\n durationSubscriber === null || durationSubscriber === void 0 ? void 0 : durationSubscriber.unsubscribe();\n durationSubscriber = null;\n if (hasValue) {\n hasValue = false;\n const value = lastValue;\n lastValue = null;\n subscriber.next(value);\n }\n };\n source.subscribe(new OperatorSubscriber(subscriber, (value) => {\n durationSubscriber === null || durationSubscriber === void 0 ? void 0 : durationSubscriber.unsubscribe();\n hasValue = true;\n lastValue = value;\n durationSubscriber = new OperatorSubscriber(subscriber, emit, undefined, noop);\n innerFrom(durationSelector(value)).subscribe(durationSubscriber);\n }, undefined, () => {\n emit();\n subscriber.complete();\n }, () => {\n lastValue = durationSubscriber = null;\n }));\n });\n}\n//# sourceMappingURL=debounce.js.map"],"sourceRoot":""} \ No newline at end of file diff --git a/public/assets/javascripts/worker/search.8c7e0a7e.min.js b/public/assets/javascripts/worker/search.8c7e0a7e.min.js new file mode 100644 index 0000000..6c2e7b8 --- /dev/null +++ b/public/assets/javascripts/worker/search.8c7e0a7e.min.js @@ -0,0 +1,59 @@ +!function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=5)}([function(e,t,r){"use strict"; +/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var n=/["'&<>]/;e.exports=function(e){var t,r=""+e,i=n.exec(r);if(!i)return r;var s="",o=0,a=0;for(o=i.index;o0){var u=I.utils.clone(t)||{};u.position=[o,a],u.index=i.length,i.push(new I.Token(r.slice(o,s),u))}o=s+1}}return i},I.tokenizer.separator=/[\s\-]+/ +/*! + * lunr.Pipeline + * Copyright (C) 2020 Oliver Nightingale + */,I.Pipeline=function(){this._stack=[]},I.Pipeline.registeredFunctions=Object.create(null),I.Pipeline.registerFunction=function(e,t){t in this.registeredFunctions&&I.utils.warn("Overwriting existing registered function: "+t),e.label=t,I.Pipeline.registeredFunctions[e.label]=e},I.Pipeline.warnIfFunctionNotRegistered=function(e){e.label&&e.label in this.registeredFunctions||I.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},I.Pipeline.load=function(e){var t=new I.Pipeline;return e.forEach((function(e){var r=I.Pipeline.registeredFunctions[e];if(!r)throw new Error("Cannot load unregistered function: "+e);t.add(r)})),t},I.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach((function(e){I.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)}),this)},I.Pipeline.prototype.after=function(e,t){I.Pipeline.warnIfFunctionNotRegistered(t);var r=this._stack.indexOf(e);if(-1==r)throw new Error("Cannot find existingFn");r+=1,this._stack.splice(r,0,t)},I.Pipeline.prototype.before=function(e,t){I.Pipeline.warnIfFunctionNotRegistered(t);var r=this._stack.indexOf(e);if(-1==r)throw new Error("Cannot find existingFn");this._stack.splice(r,0,t)},I.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);-1!=t&&this._stack.splice(t,1)},I.Pipeline.prototype.run=function(e){for(var t=this._stack.length,r=0;r1&&(se&&(r=i),s!=e);)n=r-t,i=t+Math.floor(n/2),s=this.elements[2*i];return s==e||s>e?2*i:sa?l+=2:o==a&&(t+=r[u+1]*n[l+1],u+=2,l+=2);return t},I.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},I.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,r=0;t0){var s,o=i.str.charAt(0);o in i.node.edges?s=i.node.edges[o]:(s=new I.TokenSet,i.node.edges[o]=s),1==i.str.length&&(s.final=!0),n.push({node:s,editsRemaining:i.editsRemaining,str:i.str.slice(1)})}if(0!=i.editsRemaining){if("*"in i.node.edges)var a=i.node.edges["*"];else{a=new I.TokenSet;i.node.edges["*"]=a}if(0==i.str.length&&(a.final=!0),n.push({node:a,editsRemaining:i.editsRemaining-1,str:i.str}),i.str.length>1&&n.push({node:i.node,editsRemaining:i.editsRemaining-1,str:i.str.slice(1)}),1==i.str.length&&(i.node.final=!0),i.str.length>=1){if("*"in i.node.edges)var u=i.node.edges["*"];else{u=new I.TokenSet;i.node.edges["*"]=u}1==i.str.length&&(u.final=!0),n.push({node:u,editsRemaining:i.editsRemaining-1,str:i.str.slice(1)})}if(i.str.length>1){var l,c=i.str.charAt(0),h=i.str.charAt(1);h in i.node.edges?l=i.node.edges[h]:(l=new I.TokenSet,i.node.edges[h]=l),1==i.str.length&&(l.final=!0),n.push({node:l,editsRemaining:i.editsRemaining-1,str:c+i.str.slice(2)})}}}return r},I.TokenSet.fromString=function(e){for(var t=new I.TokenSet,r=t,n=0,i=e.length;n=e;t--){var r=this.uncheckedNodes[t],n=r.child.toString();n in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[n]:(r.child._str=n,this.minimizedNodes[n]=r.child),this.uncheckedNodes.pop()}} +/*! + * lunr.Index + * Copyright (C) 2020 Oliver Nightingale + */,I.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},I.Index.prototype.search=function(e){return this.query((function(t){new I.QueryParser(e,t).parse()}))},I.Index.prototype.query=function(e){for(var t=new I.Query(this.fields),r=Object.create(null),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=0;a1?1:e},I.Builder.prototype.k1=function(e){this._k1=e},I.Builder.prototype.add=function(e,t){var r=e[this._ref],n=Object.keys(this._fields);this._documents[r]=t||{},this.documentCount+=1;for(var i=0;i=this.length)return I.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},I.QueryLexer.prototype.width=function(){return this.pos-this.start},I.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},I.QueryLexer.prototype.backup=function(){this.pos-=1},I.QueryLexer.prototype.acceptDigitRun=function(){var e,t;do{t=(e=this.next()).charCodeAt(0)}while(t>47&&t<58);e!=I.QueryLexer.EOS&&this.backup()},I.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(I.QueryLexer.TERM)),e.ignore(),e.more())return I.QueryLexer.lexText},I.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(I.QueryLexer.EDIT_DISTANCE),I.QueryLexer.lexText},I.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(I.QueryLexer.BOOST),I.QueryLexer.lexText},I.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(I.QueryLexer.TERM)},I.QueryLexer.termSeparator=I.tokenizer.separator,I.QueryLexer.lexText=function(e){for(;;){var t=e.next();if(t==I.QueryLexer.EOS)return I.QueryLexer.lexEOS;if(92!=t.charCodeAt(0)){if(":"==t)return I.QueryLexer.lexField;if("~"==t)return e.backup(),e.width()>0&&e.emit(I.QueryLexer.TERM),I.QueryLexer.lexEditDistance;if("^"==t)return e.backup(),e.width()>0&&e.emit(I.QueryLexer.TERM),I.QueryLexer.lexBoost;if("+"==t&&1===e.width())return e.emit(I.QueryLexer.PRESENCE),I.QueryLexer.lexText;if("-"==t&&1===e.width())return e.emit(I.QueryLexer.PRESENCE),I.QueryLexer.lexText;if(t.match(I.QueryLexer.termSeparator))return I.QueryLexer.lexTerm}else e.escapeCharacter()}},I.QueryParser=function(e,t){this.lexer=new I.QueryLexer(e),this.query=t,this.currentClause={},this.lexemeIdx=0},I.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=I.QueryParser.parseClause;e;)e=e(this);return this.query},I.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},I.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},I.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},I.QueryParser.parseClause=function(e){var t=e.peekLexeme();if(null!=t)switch(t.type){case I.QueryLexer.PRESENCE:return I.QueryParser.parsePresence;case I.QueryLexer.FIELD:return I.QueryParser.parseField;case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+t.type;throw t.str.length>=1&&(r+=" with value '"+t.str+"'"),new I.QueryParseError(r,t.start,t.end)}},I.QueryParser.parsePresence=function(e){var t=e.consumeLexeme();if(null!=t){switch(t.str){case"-":e.currentClause.presence=I.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=I.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+t.str+"'";throw new I.QueryParseError(r,t.start,t.end)}var n=e.peekLexeme();if(null==n){r="expecting term or field, found nothing";throw new I.QueryParseError(r,t.start,t.end)}switch(n.type){case I.QueryLexer.FIELD:return I.QueryParser.parseField;case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:r="expecting term or field, found '"+n.type+"'";throw new I.QueryParseError(r,n.start,n.end)}}},I.QueryParser.parseField=function(e){var t=e.consumeLexeme();if(null!=t){if(-1==e.query.allFields.indexOf(t.str)){var r=e.query.allFields.map((function(e){return"'"+e+"'"})).join(", "),n="unrecognised field '"+t.str+"', possible fields: "+r;throw new I.QueryParseError(n,t.start,t.end)}e.currentClause.fields=[t.str];var i=e.peekLexeme();if(null==i){n="expecting term, found nothing";throw new I.QueryParseError(n,t.start,t.end)}switch(i.type){case I.QueryLexer.TERM:return I.QueryParser.parseTerm;default:n="expecting term, found '"+i.type+"'";throw new I.QueryParseError(n,i.start,i.end)}}},I.QueryParser.parseTerm=function(e){var t=e.consumeLexeme();if(null!=t){e.currentClause.term=t.str.toLowerCase(),-1!=t.str.indexOf("*")&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(null!=r)switch(r.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+r.type+"'";throw new I.QueryParseError(n,r.start,r.end)}else e.nextClause()}},I.QueryParser.parseEditDistance=function(e){var t=e.consumeLexeme();if(null!=t){var r=parseInt(t.str,10);if(isNaN(r)){var n="edit distance must be numeric";throw new I.QueryParseError(n,t.start,t.end)}e.currentClause.editDistance=r;var i=e.peekLexeme();if(null!=i)switch(i.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:n="Unexpected lexeme type '"+i.type+"'";throw new I.QueryParseError(n,i.start,i.end)}else e.nextClause()}},I.QueryParser.parseBoost=function(e){var t=e.consumeLexeme();if(null!=t){var r=parseInt(t.str,10);if(isNaN(r)){var n="boost must be numeric";throw new I.QueryParseError(n,t.start,t.end)}e.currentClause.boost=r;var i=e.peekLexeme();if(null!=i)switch(i.type){case I.QueryLexer.TERM:return e.nextClause(),I.QueryParser.parseTerm;case I.QueryLexer.FIELD:return e.nextClause(),I.QueryParser.parseField;case I.QueryLexer.EDIT_DISTANCE:return I.QueryParser.parseEditDistance;case I.QueryLexer.BOOST:return I.QueryParser.parseBoost;case I.QueryLexer.PRESENCE:return e.nextClause(),I.QueryParser.parsePresence;default:n="Unexpected lexeme type '"+i.type+"'";throw new I.QueryParseError(n,i.start,i.end)}else e.nextClause()}},void 0===(i="function"==typeof(n=function(){return I})?n.call(t,r,t,e):n)||(e.exports=i)}()},function(e,t,r){"use strict";(function(t){e.exports=function(){if("object"==typeof globalThis)return globalThis;var e;try{e=this||new Function("return this")()}catch(e){if("object"==typeof window)return window;if("object"==typeof self)return self;if(void 0!==t)return t}return e}()}).call(this,r(4))},function(e,t){var r;r=function(){return this}();try{r=r||new Function("return this")()}catch(e){"object"==typeof window&&(r=window)}e.exports=r},function(e,t,r){"use strict";r.r(t),r.d(t,"handler",(function(){return u}));function n(e,t,r,n){return new(r||(r=Promise))((function(i,s){function o(e){try{u(n.next(e))}catch(e){s(e)}}function a(e){try{u(n.throw(e))}catch(e){s(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(o,a)}u((n=n.apply(e,t||[])).next())}))}Object.create;Object.create;r(1);var i,s=r(0);class o{constructor({config:e,docs:t,pipeline:r,index:n}){this.documents=function(e){const t=new Map,r=new Set;for(const n of e){const[e,i]=n.location.split("#"),o=n.location,a=n.title,u=s(n.text).replace(/\s+(?=[,.:;!?])/g,"").replace(/\s+/g," ");if(i){const i=t.get(e);r.has(i)?t.set(o,{location:o,title:a,text:u,parent:i}):(i.title=n.title,i.text=u,r.add(i))}else t.set(o,{location:o,title:a,text:u})}return t}(t),this.highlight=function(e){const t=new RegExp(e.separator,"img"),r=(e,t,r)=>`${t}${r}`;return n=>{n=n.replace(/[\s*+\-:~^]+/g," ").trim();const i=new RegExp(`(^|${e.separator})(${n.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(t,"|")})`,"img");return e=>e.replace(i,r).replace(/<\/mark>(\s+)]*>/gim,"$1")}}(e),lunr.tokenizer.separator=new RegExp(e.separator),this.index=void 0===n?lunr((function(){1===e.lang.length&&"en"!==e.lang[0]?this.use(lunr[e.lang[0]]):e.lang.length>1&&this.use(lunr.multiLanguage(...e.lang));const n=function(e,t){const[r,n]=[new Set(e),new Set(t)];return[...new Set([...r].filter(e=>!n.has(e)))]}(["trimmer","stopWordFilter","stemmer"],r);for(const t of e.lang.map(e=>"en"===e?lunr:lunr[e]))for(const e of n)this.pipeline.remove(t[e]),this.searchPipeline.remove(t[e]);this.field("title",{boost:1e3}),this.field("text"),this.ref("location");for(const e of t)this.add(e)})):lunr.Index.load(n)}search(e){if(e)try{const t=this.highlight(e),r=function(e){const t=new lunr.Query(["title","text"]);return new lunr.QueryParser(e,t).parse(),t.clauses}(e).filter(e=>e.presence!==lunr.Query.presence.PROHIBITED);return[...this.index.search(e+"*").reduce((e,{ref:n,score:i,matchData:s})=>{const o=this.documents.get(n);if(void 0!==o){const{location:n,title:a,text:u,parent:l}=o,c=function(e,t){const r=new Set(e),n={};for(let e=0;ee);e.push({location:n,title:t(a),text:t(u),score:i*(1+h),terms:c})}return e},[]).sort((e,t)=>t.score-e.score).reduce((e,t)=>{const r=this.documents.get(t.location);if(void 0!==r){const n="parent"in r?r.parent.location:r.location;e.set(n,[...e.get(n)||[],t])}return e},new Map).values()]}catch(t){console.warn(`Invalid query: ${e} – see https://bit.ly/2s3ChXG`)}return[]}}let a;function u(e){return n(this,void 0,void 0,(function*(){switch(e.type){case i.SETUP:return yield function(e){return n(this,void 0,void 0,(function*(){let t="../lunr";if("undefined"!=typeof parent&&"IFrameWorker"in parent){const e=document.querySelector("script[src]"),[r]=e.src.split("/worker");t=t.replace("..",r)}const r=[];for(const n of e.lang)"ja"===n&&r.push(t+"/tinyseg.min.js"),"en"!==n&&r.push(`${t}/min/lunr.${n}.min.js`);e.lang.length>1&&r.push(t+"/min/lunr.multi.min.js"),r.length&&(yield importScripts(t+"/min/lunr.stemmer.support.min.js",...r))}))}(e.data.config),a=new o(e.data),{type:i.READY};case i.QUERY:return{type:i.RESULT,data:a?a.search(e.data):[]};default:throw new TypeError("Invalid message type")}}))}!function(e){e[e.SETUP=0]="SETUP",e[e.READY=1]="READY",e[e.QUERY=2]="QUERY",e[e.RESULT=3]="RESULT"}(i||(i={})),addEventListener("message",e=>n(void 0,void 0,void 0,(function*(){postMessage(yield u(e.data))})))}]); +//# sourceMappingURL=search.8c7e0a7e.min.js.map \ No newline at end of file diff --git a/public/assets/javascripts/worker/search.8c7e0a7e.min.js.map b/public/assets/javascripts/worker/search.8c7e0a7e.min.js.map new file mode 100644 index 0000000..85a2e5c --- /dev/null +++ b/public/assets/javascripts/worker/search.8c7e0a7e.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./node_modules/escape-html/index.js","webpack:///./node_modules/lunr/lunr-exposed.js","webpack:///./node_modules/lunr/lunr.js","webpack:///./node_modules/expose-loader/dist/runtime/getGlobalThis.js","webpack:///(webpack)/buildin/global.js","webpack:///./node_modules/tslib/tslib.es6.js","webpack:///./src/assets/javascripts/integrations/search/worker/message/index.ts","webpack:///./src/assets/javascripts/integrations/search/_/index.ts","webpack:///./src/assets/javascripts/integrations/search/document/index.ts","webpack:///./src/assets/javascripts/integrations/search/highlighter/index.ts","webpack:///./src/assets/javascripts/integrations/search/query/_/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/main/index.ts"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","matchHtmlRegExp","string","escape","str","match","exec","html","index","lastIndex","length","charCodeAt","substring","___EXPOSE_LOADER_IMPORT___","___EXPOSE_LOADER_GLOBAL_THIS___","global","step2list","step3list","v","C","re_mgr0","re_mgr1","re_meq1","re_s_v","re_1a","re2_1a","re_1b","re2_1b","re_1b_2","re2_1b_2","re3_1b_2","re4_1b_2","re_1c","re_2","re_3","re_4","re2_4","re_5","re_5_1","re3_5","porterStemmer","lunr","config","builder","Builder","pipeline","add","trimmer","stopWordFilter","stemmer","searchPipeline","build","version","utils","warn","this","message","console","asString","obj","toString","clone","keys","val","Array","isArray","slice","TypeError","FieldRef","docRef","fieldName","stringValue","_stringValue","joiner","fromString","indexOf","fieldRef","undefined","Set","elements","complete","intersect","other","union","contains","empty","a","b","intersection","element","push","concat","idf","posting","documentCount","documentsWithTerm","x","Math","log","abs","Token","metadata","update","fn","tokenizer","map","toLowerCase","len","tokens","sliceEnd","sliceStart","sliceLength","charAt","separator","tokenMetadata","Pipeline","_stack","registeredFunctions","registerFunction","label","warnIfFunctionNotRegistered","load","serialised","forEach","fnName","Error","fns","arguments","after","existingFn","newFn","pos","splice","before","remove","run","stackLength","memo","j","result","k","runString","token","reset","toJSON","Vector","_magnitude","positionForIndex","start","end","pivotPoint","floor","pivotIndex","insert","insertIdx","upsert","position","magnitude","sumOfSquares","elementsLength","sqrt","dot","otherVector","dotProduct","aLen","bLen","aVal","bVal","similarity","toArray","output","RegExp","w","stem","suffix","firstch","re","re2","re3","re4","substr","toUpperCase","test","replace","fp","generateStopWordFilter","stopWords","words","reduce","stopWord","TokenSet","final","edges","id","_nextId","fromArray","arr","finish","root","fromClause","clause","fromFuzzyString","term","editDistance","stack","node","editsRemaining","frame","pop","noEditNode","char","insertionNode","substitutionNode","transposeNode","charA","charB","next","prefix","edge","_str","labels","sort","qNode","qEdges","qLen","nEdges","nLen","q","qEdge","nEdge","previousWord","uncheckedNodes","minimizedNodes","word","commonPrefix","minimize","child","nextNode","parent","downTo","childKey","Index","attrs","invertedIndex","fieldVectors","tokenSet","fields","search","queryString","query","QueryParser","parse","Query","matchingFields","queryVectors","termFieldCache","requiredMatches","prohibitedMatches","clauses","terms","clauseMatches","usePipeline","termTokenSet","expandedTerms","presence","REQUIRED","field","expandedTerm","termIndex","_index","fieldPosting","matchingDocumentRefs","termField","matchingDocumentsSet","PROHIBITED","boost","fieldMatch","matchingDocumentRef","matchingFieldRef","MatchData","allRequiredMatches","allProhibitedMatches","matchingFieldRefs","results","matches","isNegated","docMatch","fieldVector","score","matchData","combine","ref","serializedIndex","serializedVectors","serializedInvertedIndex","tokenSetBuilder","tuple","_ref","_fields","_documents","fieldTermFrequencies","fieldLengths","_b","_k1","metadataWhitelist","attributes","RangeError","number","k1","doc","extractor","fieldTerms","metadataKey","calculateAverageFieldLengths","fieldRefs","numberOfFields","accumulator","documentsWithField","averageFieldLength","createFieldVectors","fieldRefsLength","termIdfCache","fieldLength","termFrequencies","termsLength","fieldBoost","docBoost","scoreWithPrecision","tf","round","createTokenSet","use","args","unshift","apply","clonedMetadata","metadataKeys","otherMatchData","allFields","wildcard","String","NONE","LEADING","TRAILING","OPTIONAL","options","QueryParseError","QueryLexer","lexemes","escapeCharPositions","state","lexText","sliceString","subSlices","join","emit","type","escapeCharacter","EOS","width","ignore","backup","acceptDigitRun","charCode","more","FIELD","TERM","EDIT_DISTANCE","BOOST","PRESENCE","lexField","lexer","lexTerm","lexEditDistance","lexBoost","lexEOS","termSeparator","currentClause","lexemeIdx","parseClause","peekLexeme","consumeLexeme","lexeme","nextClause","completedClause","parser","parsePresence","parseField","parseTerm","errorMessage","nextLexeme","possibleFields","f","parseEditDistance","parseBoost","parseInt","isNaN","globalThis","g","Function","e","window","self","__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","step","rejected","done","then","SearchMessageType","docs","documents","Map","parents","path","hash","location","split","title","text","has","set","setupSearchDocumentMap","highlight","_","data","trim","setupSearchHighlighter","lang","multiLanguage","y","filter","difference","language","parseSearchQuery","document","startsWith","delete","getSearchQueryTerms","values","every","handler","SETUP","base","worker","querySelector","src","scripts","importScripts","setupSearchLanguages","READY","QUERY","RESULT","addEventListener","ev","postMessage"],"mappings":"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,IACN,IAEH,OAAO,SAAUK,GACf,GAAIA,GAAS6C,EAAM7C,EAAMlF,cAAgBkF,EAAMlF,WAAY,OAAOkF,IAiBtErG,EAAKO,eAAiBP,EAAKgJ,uBAAuB,CAChD,IACA,OACA,QACA,SACA,QACA,MACA,SACA,OACA,KACA,QACA,KACA,MACA,MACA,MACA,KACA,KACA,KACA,UACA,OACA,MACA,KACA,MACA,SACA,QACA,OACA,MACA,KACA,OACA,SACA,OACA,OACA,QACA,MACA,OACA,MACA,MACA,MACA,MACA,OACA,KACA,MACA,OACA,MACA,MACA,MACA,UACA,IACA,KACA,KACA,OACA,KACA,KACA,MACA,OACA,QACA,MACA,OACA,SACA,MACA,KACA,QACA,OACA,OACA,KACA,UACA,KACA,MACA,MACA,KACA,MACA,QACA,KACA,OACA,KACA,QACA,MACA,MACA,SACA,OACA,MACA,OACA,MACA,SACA,QACA,KACA,OACA,OACA,OACA,MACA,QACA,OACA,OACA,QACA,QACA,OACA,OACA,MACA,KACA,MACA,OACA,KACA,QACA,MACA,KACA,OACA,OACA,OACA,QACA,QACA,QACA,MACA,OACA,MACA,OACA,OACA,QACA,MACA,MACA,SAGFhJ,EAAK0E,SAASG,iBAAiB7E,EAAKO,eAAgB;;;;IAqBpDP,EAAKM,QAAU,SAAU+F,GACvB,OAAOA,EAAMxC,QAAO,SAAUtG,GAC5B,OAAOA,EAAEuL,QAAQ,OAAQ,IAAIA,QAAQ,OAAQ,QAIjD9I,EAAK0E,SAASG,iBAAiB7E,EAAKM,QAAS;;;;IA2B7CN,EAAKqJ,SAAW,WACdvI,KAAKwI,OAAQ,EACbxI,KAAKyI,MAAQ,GACbzI,KAAK0I,GAAKxJ,EAAKqJ,SAASI,QACxBzJ,EAAKqJ,SAASI,SAAW,GAW3BzJ,EAAKqJ,SAASI,QAAU,EASxBzJ,EAAKqJ,SAASK,UAAY,SAAUC,GAGlC,IAFA,IAAIzJ,EAAU,IAAIF,EAAKqJ,SAASlJ,QAEvB3E,EAAI,EAAG0I,EAAMyF,EAAI1L,OAAQzC,EAAI0I,EAAK1I,IACzC0E,EAAQ8G,OAAO2C,E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","file":"assets/javascripts/worker/search.8c7e0a7e.min.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 5);\n","/*!\n * escape-html\n * Copyright(c) 2012-2013 TJ Holowaychuk\n * Copyright(c) 2015 Andreas Lubbe\n * Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n * MIT Licensed\n */\n\n'use strict';\n\n/**\n * Module variables.\n * @private\n */\n\nvar matchHtmlRegExp = /[\"'&<>]/;\n\n/**\n * Module exports.\n * @public\n */\n\nmodule.exports = escapeHtml;\n\n/**\n * Escape special characters in the given string of html.\n *\n * @param {string} string The string to escape for inserting into HTML\n * @return {string}\n * @public\n */\n\nfunction escapeHtml(string) {\n var str = '' + string;\n var match = matchHtmlRegExp.exec(str);\n\n if (!match) {\n return str;\n }\n\n var escape;\n var html = '';\n var index = 0;\n var lastIndex = 0;\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"';\n break;\n case 38: // &\n escape = '&';\n break;\n case 39: // '\n escape = ''';\n break;\n case 60: // <\n escape = '<';\n break;\n case 62: // >\n escape = '>';\n break;\n default:\n continue;\n }\n\n if (lastIndex !== index) {\n html += str.substring(lastIndex, index);\n }\n\n lastIndex = index + 1;\n html += escape;\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html;\n}\n","var ___EXPOSE_LOADER_IMPORT___ = require(\"-!./lunr.js\");\nvar ___EXPOSE_LOADER_GET_GLOBAL_THIS___ = require(\"../expose-loader/dist/runtime/getGlobalThis.js\");\nvar ___EXPOSE_LOADER_GLOBAL_THIS___ = ___EXPOSE_LOADER_GET_GLOBAL_THIS___;\nif (typeof ___EXPOSE_LOADER_GLOBAL_THIS___[\"lunr\"] === 'undefined') ___EXPOSE_LOADER_GLOBAL_THIS___[\"lunr\"] = ___EXPOSE_LOADER_IMPORT___;\nmodule.exports = ___EXPOSE_LOADER_IMPORT___;\n","/**\n * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9\n * Copyright (C) 2020 Oliver Nightingale\n * @license MIT\n */\n\n;(function(){\n\n/**\n * A convenience function for configuring and constructing\n * a new lunr Index.\n *\n * A lunr.Builder instance is created and the pipeline setup\n * with a trimmer, stop word filter and stemmer.\n *\n * This builder object is yielded to the configuration function\n * that is passed as a parameter, allowing the list of fields\n * and other builder parameters to be customised.\n *\n * All documents _must_ be added within the passed config function.\n *\n * @example\n * var idx = lunr(function () {\n * this.field('title')\n * this.field('body')\n * this.ref('id')\n *\n * documents.forEach(function (doc) {\n * this.add(doc)\n * }, this)\n * })\n *\n * @see {@link lunr.Builder}\n * @see {@link lunr.Pipeline}\n * @see {@link lunr.trimmer}\n * @see {@link lunr.stopWordFilter}\n * @see {@link lunr.stemmer}\n * @namespace {function} lunr\n */\nvar lunr = function (config) {\n var builder = new lunr.Builder\n\n builder.pipeline.add(\n lunr.trimmer,\n lunr.stopWordFilter,\n lunr.stemmer\n )\n\n builder.searchPipeline.add(\n lunr.stemmer\n )\n\n config.call(builder, builder)\n return builder.build()\n}\n\nlunr.version = \"2.3.9\"\n/*!\n * lunr.utils\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A namespace containing utils for the rest of the lunr library\n * @namespace lunr.utils\n */\nlunr.utils = {}\n\n/**\n * Print a warning message to the console.\n *\n * @param {String} message The message to be printed.\n * @memberOf lunr.utils\n * @function\n */\nlunr.utils.warn = (function (global) {\n /* eslint-disable no-console */\n return function (message) {\n if (global.console && console.warn) {\n console.warn(message)\n }\n }\n /* eslint-enable no-console */\n})(this)\n\n/**\n * Convert an object to a string.\n *\n * In the case of `null` and `undefined` the function returns\n * the empty string, in all other cases the result of calling\n * `toString` on the passed object is returned.\n *\n * @param {Any} obj The object to convert to a string.\n * @return {String} string representation of the passed object.\n * @memberOf lunr.utils\n */\nlunr.utils.asString = function (obj) {\n if (obj === void 0 || obj === null) {\n return \"\"\n } else {\n return obj.toString()\n }\n}\n\n/**\n * Clones an object.\n *\n * Will create a copy of an existing object such that any mutations\n * on the copy cannot affect the original.\n *\n * Only shallow objects are supported, passing a nested object to this\n * function will cause a TypeError.\n *\n * Objects with primitives, and arrays of primitives are supported.\n *\n * @param {Object} obj The object to clone.\n * @return {Object} a clone of the passed object.\n * @throws {TypeError} when a nested object is passed.\n * @memberOf Utils\n */\nlunr.utils.clone = function (obj) {\n if (obj === null || obj === undefined) {\n return obj\n }\n\n var clone = Object.create(null),\n keys = Object.keys(obj)\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i],\n val = obj[key]\n\n if (Array.isArray(val)) {\n clone[key] = val.slice()\n continue\n }\n\n if (typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean') {\n clone[key] = val\n continue\n }\n\n throw new TypeError(\"clone is not deep and does not support nested objects\")\n }\n\n return clone\n}\nlunr.FieldRef = function (docRef, fieldName, stringValue) {\n this.docRef = docRef\n this.fieldName = fieldName\n this._stringValue = stringValue\n}\n\nlunr.FieldRef.joiner = \"/\"\n\nlunr.FieldRef.fromString = function (s) {\n var n = s.indexOf(lunr.FieldRef.joiner)\n\n if (n === -1) {\n throw \"malformed field ref string\"\n }\n\n var fieldRef = s.slice(0, n),\n docRef = s.slice(n + 1)\n\n return new lunr.FieldRef (docRef, fieldRef, s)\n}\n\nlunr.FieldRef.prototype.toString = function () {\n if (this._stringValue == undefined) {\n this._stringValue = this.fieldName + lunr.FieldRef.joiner + this.docRef\n }\n\n return this._stringValue\n}\n/*!\n * lunr.Set\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A lunr set.\n *\n * @constructor\n */\nlunr.Set = function (elements) {\n this.elements = Object.create(null)\n\n if (elements) {\n this.length = elements.length\n\n for (var i = 0; i < this.length; i++) {\n this.elements[elements[i]] = true\n }\n } else {\n this.length = 0\n }\n}\n\n/**\n * A complete set that contains all elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.complete = {\n intersect: function (other) {\n return other\n },\n\n union: function () {\n return this\n },\n\n contains: function () {\n return true\n }\n}\n\n/**\n * An empty set that contains no elements.\n *\n * @static\n * @readonly\n * @type {lunr.Set}\n */\nlunr.Set.empty = {\n intersect: function () {\n return this\n },\n\n union: function (other) {\n return other\n },\n\n contains: function () {\n return false\n }\n}\n\n/**\n * Returns true if this set contains the specified object.\n *\n * @param {object} object - Object whose presence in this set is to be tested.\n * @returns {boolean} - True if this set contains the specified object.\n */\nlunr.Set.prototype.contains = function (object) {\n return !!this.elements[object]\n}\n\n/**\n * Returns a new set containing only the elements that are present in both\n * this set and the specified set.\n *\n * @param {lunr.Set} other - set to intersect with this set.\n * @returns {lunr.Set} a new set that is the intersection of this and the specified set.\n */\n\nlunr.Set.prototype.intersect = function (other) {\n var a, b, elements, intersection = []\n\n if (other === lunr.Set.complete) {\n return this\n }\n\n if (other === lunr.Set.empty) {\n return other\n }\n\n if (this.length < other.length) {\n a = this\n b = other\n } else {\n a = other\n b = this\n }\n\n elements = Object.keys(a.elements)\n\n for (var i = 0; i < elements.length; i++) {\n var element = elements[i]\n if (element in b.elements) {\n intersection.push(element)\n }\n }\n\n return new lunr.Set (intersection)\n}\n\n/**\n * Returns a new set combining the elements of this and the specified set.\n *\n * @param {lunr.Set} other - set to union with this set.\n * @return {lunr.Set} a new set that is the union of this and the specified set.\n */\n\nlunr.Set.prototype.union = function (other) {\n if (other === lunr.Set.complete) {\n return lunr.Set.complete\n }\n\n if (other === lunr.Set.empty) {\n return this\n }\n\n return new lunr.Set(Object.keys(this.elements).concat(Object.keys(other.elements)))\n}\n/**\n * A function to calculate the inverse document frequency for\n * a posting. This is shared between the builder and the index\n *\n * @private\n * @param {object} posting - The posting for a given term\n * @param {number} documentCount - The total number of documents.\n */\nlunr.idf = function (posting, documentCount) {\n var documentsWithTerm = 0\n\n for (var fieldName in posting) {\n if (fieldName == '_index') continue // Ignore the term index, its not a field\n documentsWithTerm += Object.keys(posting[fieldName]).length\n }\n\n var x = (documentCount - documentsWithTerm + 0.5) / (documentsWithTerm + 0.5)\n\n return Math.log(1 + Math.abs(x))\n}\n\n/**\n * A token wraps a string representation of a token\n * as it is passed through the text processing pipeline.\n *\n * @constructor\n * @param {string} [str=''] - The string token being wrapped.\n * @param {object} [metadata={}] - Metadata associated with this token.\n */\nlunr.Token = function (str, metadata) {\n this.str = str || \"\"\n this.metadata = metadata || {}\n}\n\n/**\n * Returns the token string that is being wrapped by this object.\n *\n * @returns {string}\n */\nlunr.Token.prototype.toString = function () {\n return this.str\n}\n\n/**\n * A token update function is used when updating or optionally\n * when cloning a token.\n *\n * @callback lunr.Token~updateFunction\n * @param {string} str - The string representation of the token.\n * @param {Object} metadata - All metadata associated with this token.\n */\n\n/**\n * Applies the given function to the wrapped string token.\n *\n * @example\n * token.update(function (str, metadata) {\n * return str.toUpperCase()\n * })\n *\n * @param {lunr.Token~updateFunction} fn - A function to apply to the token string.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.update = function (fn) {\n this.str = fn(this.str, this.metadata)\n return this\n}\n\n/**\n * Creates a clone of this token. Optionally a function can be\n * applied to the cloned token.\n *\n * @param {lunr.Token~updateFunction} [fn] - An optional function to apply to the cloned token.\n * @returns {lunr.Token}\n */\nlunr.Token.prototype.clone = function (fn) {\n fn = fn || function (s) { return s }\n return new lunr.Token (fn(this.str, this.metadata), this.metadata)\n}\n/*!\n * lunr.tokenizer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A function for splitting a string into tokens ready to be inserted into\n * the search index. Uses `lunr.tokenizer.separator` to split strings, change\n * the value of this property to change how strings are split into tokens.\n *\n * This tokenizer will convert its parameter to a string by calling `toString` and\n * then will split this string on the character in `lunr.tokenizer.separator`.\n * Arrays will have their elements converted to strings and wrapped in a lunr.Token.\n *\n * Optional metadata can be passed to the tokenizer, this metadata will be cloned and\n * added as metadata to every token that is created from the object to be tokenized.\n *\n * @static\n * @param {?(string|object|object[])} obj - The object to convert into tokens\n * @param {?object} metadata - Optional metadata to associate with every token\n * @returns {lunr.Token[]}\n * @see {@link lunr.Pipeline}\n */\nlunr.tokenizer = function (obj, metadata) {\n if (obj == null || obj == undefined) {\n return []\n }\n\n if (Array.isArray(obj)) {\n return obj.map(function (t) {\n return new lunr.Token(\n lunr.utils.asString(t).toLowerCase(),\n lunr.utils.clone(metadata)\n )\n })\n }\n\n var str = obj.toString().toLowerCase(),\n len = str.length,\n tokens = []\n\n for (var sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) {\n var char = str.charAt(sliceEnd),\n sliceLength = sliceEnd - sliceStart\n\n if ((char.match(lunr.tokenizer.separator) || sliceEnd == len)) {\n\n if (sliceLength > 0) {\n var tokenMetadata = lunr.utils.clone(metadata) || {}\n tokenMetadata[\"position\"] = [sliceStart, sliceLength]\n tokenMetadata[\"index\"] = tokens.length\n\n tokens.push(\n new lunr.Token (\n str.slice(sliceStart, sliceEnd),\n tokenMetadata\n )\n )\n }\n\n sliceStart = sliceEnd + 1\n }\n\n }\n\n return tokens\n}\n\n/**\n * The separator used to split a string into tokens. Override this property to change the behaviour of\n * `lunr.tokenizer` behaviour when tokenizing strings. By default this splits on whitespace and hyphens.\n *\n * @static\n * @see lunr.tokenizer\n */\nlunr.tokenizer.separator = /[\\s\\-]+/\n/*!\n * lunr.Pipeline\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Pipelines maintain an ordered list of functions to be applied to all\n * tokens in documents entering the search index and queries being ran against\n * the index.\n *\n * An instance of lunr.Index created with the lunr shortcut will contain a\n * pipeline with a stop word filter and an English language stemmer. Extra\n * functions can be added before or after either of these functions or these\n * default functions can be removed.\n *\n * When run the pipeline will call each function in turn, passing a token, the\n * index of that token in the original list of all tokens and finally a list of\n * all the original tokens.\n *\n * The output of functions in the pipeline will be passed to the next function\n * in the pipeline. To exclude a token from entering the index the function\n * should return undefined, the rest of the pipeline will not be called with\n * this token.\n *\n * For serialisation of pipelines to work, all functions used in an instance of\n * a pipeline should be registered with lunr.Pipeline. Registered functions can\n * then be loaded. If trying to load a serialised pipeline that uses functions\n * that are not registered an error will be thrown.\n *\n * If not planning on serialising the pipeline then registering pipeline functions\n * is not necessary.\n *\n * @constructor\n */\nlunr.Pipeline = function () {\n this._stack = []\n}\n\nlunr.Pipeline.registeredFunctions = Object.create(null)\n\n/**\n * A pipeline function maps lunr.Token to lunr.Token. A lunr.Token contains the token\n * string as well as all known metadata. A pipeline function can mutate the token string\n * or mutate (or add) metadata for a given token.\n *\n * A pipeline function can indicate that the passed token should be discarded by returning\n * null, undefined or an empty string. This token will not be passed to any downstream pipeline\n * functions and will not be added to the index.\n *\n * Multiple tokens can be returned by returning an array of tokens. Each token will be passed\n * to any downstream pipeline functions and all will returned tokens will be added to the index.\n *\n * Any number of pipeline functions may be chained together using a lunr.Pipeline.\n *\n * @interface lunr.PipelineFunction\n * @param {lunr.Token} token - A token from the document being processed.\n * @param {number} i - The index of this token in the complete list of tokens for this document/field.\n * @param {lunr.Token[]} tokens - All tokens for this document/field.\n * @returns {(?lunr.Token|lunr.Token[])}\n */\n\n/**\n * Register a function with the pipeline.\n *\n * Functions that are used in the pipeline should be registered if the pipeline\n * needs to be serialised, or a serialised pipeline needs to be loaded.\n *\n * Registering a function does not add it to a pipeline, functions must still be\n * added to instances of the pipeline for them to be used when running a pipeline.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @param {String} label - The label to register this function with\n */\nlunr.Pipeline.registerFunction = function (fn, label) {\n if (label in this.registeredFunctions) {\n lunr.utils.warn('Overwriting existing registered function: ' + label)\n }\n\n fn.label = label\n lunr.Pipeline.registeredFunctions[fn.label] = fn\n}\n\n/**\n * Warns if the function is not registered as a Pipeline function.\n *\n * @param {lunr.PipelineFunction} fn - The function to check for.\n * @private\n */\nlunr.Pipeline.warnIfFunctionNotRegistered = function (fn) {\n var isRegistered = fn.label && (fn.label in this.registeredFunctions)\n\n if (!isRegistered) {\n lunr.utils.warn('Function is not registered with pipeline. This may cause problems when serialising the index.\\n', fn)\n }\n}\n\n/**\n * Loads a previously serialised pipeline.\n *\n * All functions to be loaded must already be registered with lunr.Pipeline.\n * If any function from the serialised data has not been registered then an\n * error will be thrown.\n *\n * @param {Object} serialised - The serialised pipeline to load.\n * @returns {lunr.Pipeline}\n */\nlunr.Pipeline.load = function (serialised) {\n var pipeline = new lunr.Pipeline\n\n serialised.forEach(function (fnName) {\n var fn = lunr.Pipeline.registeredFunctions[fnName]\n\n if (fn) {\n pipeline.add(fn)\n } else {\n throw new Error('Cannot load unregistered function: ' + fnName)\n }\n })\n\n return pipeline\n}\n\n/**\n * Adds new functions to the end of the pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction[]} functions - Any number of functions to add to the pipeline.\n */\nlunr.Pipeline.prototype.add = function () {\n var fns = Array.prototype.slice.call(arguments)\n\n fns.forEach(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n this._stack.push(fn)\n }, this)\n}\n\n/**\n * Adds a single function after a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.after = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n pos = pos + 1\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Adds a single function before a function that already exists in the\n * pipeline.\n *\n * Logs a warning if the function has not been registered.\n *\n * @param {lunr.PipelineFunction} existingFn - A function that already exists in the pipeline.\n * @param {lunr.PipelineFunction} newFn - The new function to add to the pipeline.\n */\nlunr.Pipeline.prototype.before = function (existingFn, newFn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(newFn)\n\n var pos = this._stack.indexOf(existingFn)\n if (pos == -1) {\n throw new Error('Cannot find existingFn')\n }\n\n this._stack.splice(pos, 0, newFn)\n}\n\n/**\n * Removes a function from the pipeline.\n *\n * @param {lunr.PipelineFunction} fn The function to remove from the pipeline.\n */\nlunr.Pipeline.prototype.remove = function (fn) {\n var pos = this._stack.indexOf(fn)\n if (pos == -1) {\n return\n }\n\n this._stack.splice(pos, 1)\n}\n\n/**\n * Runs the current list of functions that make up the pipeline against the\n * passed tokens.\n *\n * @param {Array} tokens The tokens to run through the pipeline.\n * @returns {Array}\n */\nlunr.Pipeline.prototype.run = function (tokens) {\n var stackLength = this._stack.length\n\n for (var i = 0; i < stackLength; i++) {\n var fn = this._stack[i]\n var memo = []\n\n for (var j = 0; j < tokens.length; j++) {\n var result = fn(tokens[j], j, tokens)\n\n if (result === null || result === void 0 || result === '') continue\n\n if (Array.isArray(result)) {\n for (var k = 0; k < result.length; k++) {\n memo.push(result[k])\n }\n } else {\n memo.push(result)\n }\n }\n\n tokens = memo\n }\n\n return tokens\n}\n\n/**\n * Convenience method for passing a string through a pipeline and getting\n * strings out. This method takes care of wrapping the passed string in a\n * token and mapping the resulting tokens back to strings.\n *\n * @param {string} str - The string to pass through the pipeline.\n * @param {?object} metadata - Optional metadata to associate with the token\n * passed to the pipeline.\n * @returns {string[]}\n */\nlunr.Pipeline.prototype.runString = function (str, metadata) {\n var token = new lunr.Token (str, metadata)\n\n return this.run([token]).map(function (t) {\n return t.toString()\n })\n}\n\n/**\n * Resets the pipeline by removing any existing processors.\n *\n */\nlunr.Pipeline.prototype.reset = function () {\n this._stack = []\n}\n\n/**\n * Returns a representation of the pipeline ready for serialisation.\n *\n * Logs a warning if the function has not been registered.\n *\n * @returns {Array}\n */\nlunr.Pipeline.prototype.toJSON = function () {\n return this._stack.map(function (fn) {\n lunr.Pipeline.warnIfFunctionNotRegistered(fn)\n\n return fn.label\n })\n}\n/*!\n * lunr.Vector\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A vector is used to construct the vector space of documents and queries. These\n * vectors support operations to determine the similarity between two documents or\n * a document and a query.\n *\n * Normally no parameters are required for initializing a vector, but in the case of\n * loading a previously dumped vector the raw elements can be provided to the constructor.\n *\n * For performance reasons vectors are implemented with a flat array, where an elements\n * index is immediately followed by its value. E.g. [index, value, index, value]. This\n * allows the underlying array to be as sparse as possible and still offer decent\n * performance when being used for vector calculations.\n *\n * @constructor\n * @param {Number[]} [elements] - The flat list of element index and element value pairs.\n */\nlunr.Vector = function (elements) {\n this._magnitude = 0\n this.elements = elements || []\n}\n\n\n/**\n * Calculates the position within the vector to insert a given index.\n *\n * This is used internally by insert and upsert. If there are duplicate indexes then\n * the position is returned as if the value for that index were to be updated, but it\n * is the callers responsibility to check whether there is a duplicate at that index\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @returns {Number}\n */\nlunr.Vector.prototype.positionForIndex = function (index) {\n // For an empty vector the tuple can be inserted at the beginning\n if (this.elements.length == 0) {\n return 0\n }\n\n var start = 0,\n end = this.elements.length / 2,\n sliceLength = end - start,\n pivotPoint = Math.floor(sliceLength / 2),\n pivotIndex = this.elements[pivotPoint * 2]\n\n while (sliceLength > 1) {\n if (pivotIndex < index) {\n start = pivotPoint\n }\n\n if (pivotIndex > index) {\n end = pivotPoint\n }\n\n if (pivotIndex == index) {\n break\n }\n\n sliceLength = end - start\n pivotPoint = start + Math.floor(sliceLength / 2)\n pivotIndex = this.elements[pivotPoint * 2]\n }\n\n if (pivotIndex == index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex > index) {\n return pivotPoint * 2\n }\n\n if (pivotIndex < index) {\n return (pivotPoint + 1) * 2\n }\n}\n\n/**\n * Inserts an element at an index within the vector.\n *\n * Does not allow duplicates, will throw an error if there is already an entry\n * for this index.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n */\nlunr.Vector.prototype.insert = function (insertIdx, val) {\n this.upsert(insertIdx, val, function () {\n throw \"duplicate index\"\n })\n}\n\n/**\n * Inserts or updates an existing index within the vector.\n *\n * @param {Number} insertIdx - The index at which the element should be inserted.\n * @param {Number} val - The value to be inserted into the vector.\n * @param {function} fn - A function that is called for updates, the existing value and the\n * requested value are passed as arguments\n */\nlunr.Vector.prototype.upsert = function (insertIdx, val, fn) {\n this._magnitude = 0\n var position = this.positionForIndex(insertIdx)\n\n if (this.elements[position] == insertIdx) {\n this.elements[position + 1] = fn(this.elements[position + 1], val)\n } else {\n this.elements.splice(position, 0, insertIdx, val)\n }\n}\n\n/**\n * Calculates the magnitude of this vector.\n *\n * @returns {Number}\n */\nlunr.Vector.prototype.magnitude = function () {\n if (this._magnitude) return this._magnitude\n\n var sumOfSquares = 0,\n elementsLength = this.elements.length\n\n for (var i = 1; i < elementsLength; i += 2) {\n var val = this.elements[i]\n sumOfSquares += val * val\n }\n\n return this._magnitude = Math.sqrt(sumOfSquares)\n}\n\n/**\n * Calculates the dot product of this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The vector to compute the dot product with.\n * @returns {Number}\n */\nlunr.Vector.prototype.dot = function (otherVector) {\n var dotProduct = 0,\n a = this.elements, b = otherVector.elements,\n aLen = a.length, bLen = b.length,\n aVal = 0, bVal = 0,\n i = 0, j = 0\n\n while (i < aLen && j < bLen) {\n aVal = a[i], bVal = b[j]\n if (aVal < bVal) {\n i += 2\n } else if (aVal > bVal) {\n j += 2\n } else if (aVal == bVal) {\n dotProduct += a[i + 1] * b[j + 1]\n i += 2\n j += 2\n }\n }\n\n return dotProduct\n}\n\n/**\n * Calculates the similarity between this vector and another vector.\n *\n * @param {lunr.Vector} otherVector - The other vector to calculate the\n * similarity with.\n * @returns {Number}\n */\nlunr.Vector.prototype.similarity = function (otherVector) {\n return this.dot(otherVector) / this.magnitude() || 0\n}\n\n/**\n * Converts the vector to an array of the elements within the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toArray = function () {\n var output = new Array (this.elements.length / 2)\n\n for (var i = 1, j = 0; i < this.elements.length; i += 2, j++) {\n output[j] = this.elements[i]\n }\n\n return output\n}\n\n/**\n * A JSON serializable representation of the vector.\n *\n * @returns {Number[]}\n */\nlunr.Vector.prototype.toJSON = function () {\n return this.elements\n}\n/* eslint-disable */\n/*!\n * lunr.stemmer\n * Copyright (C) 2020 Oliver Nightingale\n * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt\n */\n\n/**\n * lunr.stemmer is an english language stemmer, this is a JavaScript\n * implementation of the PorterStemmer taken from http://tartarus.org/~martin\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token - The string to stem\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n * @function\n */\nlunr.stemmer = (function(){\n var step2list = {\n \"ational\" : \"ate\",\n \"tional\" : \"tion\",\n \"enci\" : \"ence\",\n \"anci\" : \"ance\",\n \"izer\" : \"ize\",\n \"bli\" : \"ble\",\n \"alli\" : \"al\",\n \"entli\" : \"ent\",\n \"eli\" : \"e\",\n \"ousli\" : \"ous\",\n \"ization\" : \"ize\",\n \"ation\" : \"ate\",\n \"ator\" : \"ate\",\n \"alism\" : \"al\",\n \"iveness\" : \"ive\",\n \"fulness\" : \"ful\",\n \"ousness\" : \"ous\",\n \"aliti\" : \"al\",\n \"iviti\" : \"ive\",\n \"biliti\" : \"ble\",\n \"logi\" : \"log\"\n },\n\n step3list = {\n \"icate\" : \"ic\",\n \"ative\" : \"\",\n \"alize\" : \"al\",\n \"iciti\" : \"ic\",\n \"ical\" : \"ic\",\n \"ful\" : \"\",\n \"ness\" : \"\"\n },\n\n c = \"[^aeiou]\", // consonant\n v = \"[aeiouy]\", // vowel\n C = c + \"[^aeiouy]*\", // consonant sequence\n V = v + \"[aeiou]*\", // vowel sequence\n\n mgr0 = \"^(\" + C + \")?\" + V + C, // [C]VC... is m>0\n meq1 = \"^(\" + C + \")?\" + V + C + \"(\" + V + \")?$\", // [C]VC[V] is m=1\n mgr1 = \"^(\" + C + \")?\" + V + C + V + C, // [C]VCVC... is m>1\n s_v = \"^(\" + C + \")?\" + v; // vowel in stem\n\n var re_mgr0 = new RegExp(mgr0);\n var re_mgr1 = new RegExp(mgr1);\n var re_meq1 = new RegExp(meq1);\n var re_s_v = new RegExp(s_v);\n\n var re_1a = /^(.+?)(ss|i)es$/;\n var re2_1a = /^(.+?)([^s])s$/;\n var re_1b = /^(.+?)eed$/;\n var re2_1b = /^(.+?)(ed|ing)$/;\n var re_1b_2 = /.$/;\n var re2_1b_2 = /(at|bl|iz)$/;\n var re3_1b_2 = new RegExp(\"([^aeiouylsz])\\\\1$\");\n var re4_1b_2 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var re_1c = /^(.+?[^aeiou])y$/;\n var re_2 = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;\n\n var re_3 = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;\n\n var re_4 = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;\n var re2_4 = /^(.+?)(s|t)(ion)$/;\n\n var re_5 = /^(.+?)e$/;\n var re_5_1 = /ll$/;\n var re3_5 = new RegExp(\"^\" + C + v + \"[^aeiouwxy]$\");\n\n var porterStemmer = function porterStemmer(w) {\n var stem,\n suffix,\n firstch,\n re,\n re2,\n re3,\n re4;\n\n if (w.length < 3) { return w; }\n\n firstch = w.substr(0,1);\n if (firstch == \"y\") {\n w = firstch.toUpperCase() + w.substr(1);\n }\n\n // Step 1a\n re = re_1a\n re2 = re2_1a;\n\n if (re.test(w)) { w = w.replace(re,\"$1$2\"); }\n else if (re2.test(w)) { w = w.replace(re2,\"$1$2\"); }\n\n // Step 1b\n re = re_1b;\n re2 = re2_1b;\n if (re.test(w)) {\n var fp = re.exec(w);\n re = re_mgr0;\n if (re.test(fp[1])) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1];\n re2 = re_s_v;\n if (re2.test(stem)) {\n w = stem;\n re2 = re2_1b_2;\n re3 = re3_1b_2;\n re4 = re4_1b_2;\n if (re2.test(w)) { w = w + \"e\"; }\n else if (re3.test(w)) { re = re_1b_2; w = w.replace(re,\"\"); }\n else if (re4.test(w)) { w = w + \"e\"; }\n }\n }\n\n // Step 1c - replace suffix y or Y by i if preceded by a non-vowel which is not the first letter of the word (so cry -> cri, by -> by, say -> say)\n re = re_1c;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n w = stem + \"i\";\n }\n\n // Step 2\n re = re_2;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step2list[suffix];\n }\n }\n\n // Step 3\n re = re_3;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n suffix = fp[2];\n re = re_mgr0;\n if (re.test(stem)) {\n w = stem + step3list[suffix];\n }\n }\n\n // Step 4\n re = re_4;\n re2 = re2_4;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n if (re.test(stem)) {\n w = stem;\n }\n } else if (re2.test(w)) {\n var fp = re2.exec(w);\n stem = fp[1] + fp[2];\n re2 = re_mgr1;\n if (re2.test(stem)) {\n w = stem;\n }\n }\n\n // Step 5\n re = re_5;\n if (re.test(w)) {\n var fp = re.exec(w);\n stem = fp[1];\n re = re_mgr1;\n re2 = re_meq1;\n re3 = re3_5;\n if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) {\n w = stem;\n }\n }\n\n re = re_5_1;\n re2 = re_mgr1;\n if (re.test(w) && re2.test(w)) {\n re = re_1b_2;\n w = w.replace(re,\"\");\n }\n\n // and turn initial Y back to y\n\n if (firstch == \"y\") {\n w = firstch.toLowerCase() + w.substr(1);\n }\n\n return w;\n };\n\n return function (token) {\n return token.update(porterStemmer);\n }\n})();\n\nlunr.Pipeline.registerFunction(lunr.stemmer, 'stemmer')\n/*!\n * lunr.stopWordFilter\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.generateStopWordFilter builds a stopWordFilter function from the provided\n * list of stop words.\n *\n * The built in lunr.stopWordFilter is built using this generator and can be used\n * to generate custom stopWordFilters for applications or non English languages.\n *\n * @function\n * @param {Array} token The token to pass through the filter\n * @returns {lunr.PipelineFunction}\n * @see lunr.Pipeline\n * @see lunr.stopWordFilter\n */\nlunr.generateStopWordFilter = function (stopWords) {\n var words = stopWords.reduce(function (memo, stopWord) {\n memo[stopWord] = stopWord\n return memo\n }, {})\n\n return function (token) {\n if (token && words[token.toString()] !== token.toString()) return token\n }\n}\n\n/**\n * lunr.stopWordFilter is an English language stop word list filter, any words\n * contained in the list will not be passed through the filter.\n *\n * This is intended to be used in the Pipeline. If the token does not pass the\n * filter then undefined will be returned.\n *\n * @function\n * @implements {lunr.PipelineFunction}\n * @params {lunr.Token} token - A token to check for being a stop word.\n * @returns {lunr.Token}\n * @see {@link lunr.Pipeline}\n */\nlunr.stopWordFilter = lunr.generateStopWordFilter([\n 'a',\n 'able',\n 'about',\n 'across',\n 'after',\n 'all',\n 'almost',\n 'also',\n 'am',\n 'among',\n 'an',\n 'and',\n 'any',\n 'are',\n 'as',\n 'at',\n 'be',\n 'because',\n 'been',\n 'but',\n 'by',\n 'can',\n 'cannot',\n 'could',\n 'dear',\n 'did',\n 'do',\n 'does',\n 'either',\n 'else',\n 'ever',\n 'every',\n 'for',\n 'from',\n 'get',\n 'got',\n 'had',\n 'has',\n 'have',\n 'he',\n 'her',\n 'hers',\n 'him',\n 'his',\n 'how',\n 'however',\n 'i',\n 'if',\n 'in',\n 'into',\n 'is',\n 'it',\n 'its',\n 'just',\n 'least',\n 'let',\n 'like',\n 'likely',\n 'may',\n 'me',\n 'might',\n 'most',\n 'must',\n 'my',\n 'neither',\n 'no',\n 'nor',\n 'not',\n 'of',\n 'off',\n 'often',\n 'on',\n 'only',\n 'or',\n 'other',\n 'our',\n 'own',\n 'rather',\n 'said',\n 'say',\n 'says',\n 'she',\n 'should',\n 'since',\n 'so',\n 'some',\n 'than',\n 'that',\n 'the',\n 'their',\n 'them',\n 'then',\n 'there',\n 'these',\n 'they',\n 'this',\n 'tis',\n 'to',\n 'too',\n 'twas',\n 'us',\n 'wants',\n 'was',\n 'we',\n 'were',\n 'what',\n 'when',\n 'where',\n 'which',\n 'while',\n 'who',\n 'whom',\n 'why',\n 'will',\n 'with',\n 'would',\n 'yet',\n 'you',\n 'your'\n])\n\nlunr.Pipeline.registerFunction(lunr.stopWordFilter, 'stopWordFilter')\n/*!\n * lunr.trimmer\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.trimmer is a pipeline function for trimming non word\n * characters from the beginning and end of tokens before they\n * enter the index.\n *\n * This implementation may not work correctly for non latin\n * characters and should either be removed or adapted for use\n * with languages with non-latin characters.\n *\n * @static\n * @implements {lunr.PipelineFunction}\n * @param {lunr.Token} token The token to pass through the filter\n * @returns {lunr.Token}\n * @see lunr.Pipeline\n */\nlunr.trimmer = function (token) {\n return token.update(function (s) {\n return s.replace(/^\\W+/, '').replace(/\\W+$/, '')\n })\n}\n\nlunr.Pipeline.registerFunction(lunr.trimmer, 'trimmer')\n/*!\n * lunr.TokenSet\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * A token set is used to store the unique list of all tokens\n * within an index. Token sets are also used to represent an\n * incoming query to the index, this query token set and index\n * token set are then intersected to find which tokens to look\n * up in the inverted index.\n *\n * A token set can hold multiple tokens, as in the case of the\n * index token set, or it can hold a single token as in the\n * case of a simple query token set.\n *\n * Additionally token sets are used to perform wildcard matching.\n * Leading, contained and trailing wildcards are supported, and\n * from this edit distance matching can also be provided.\n *\n * Token sets are implemented as a minimal finite state automata,\n * where both common prefixes and suffixes are shared between tokens.\n * This helps to reduce the space used for storing the token set.\n *\n * @constructor\n */\nlunr.TokenSet = function () {\n this.final = false\n this.edges = {}\n this.id = lunr.TokenSet._nextId\n lunr.TokenSet._nextId += 1\n}\n\n/**\n * Keeps track of the next, auto increment, identifier to assign\n * to a new tokenSet.\n *\n * TokenSets require a unique identifier to be correctly minimised.\n *\n * @private\n */\nlunr.TokenSet._nextId = 1\n\n/**\n * Creates a TokenSet instance from the given sorted array of words.\n *\n * @param {String[]} arr - A sorted array of strings to create the set from.\n * @returns {lunr.TokenSet}\n * @throws Will throw an error if the input array is not sorted.\n */\nlunr.TokenSet.fromArray = function (arr) {\n var builder = new lunr.TokenSet.Builder\n\n for (var i = 0, len = arr.length; i < len; i++) {\n builder.insert(arr[i])\n }\n\n builder.finish()\n return builder.root\n}\n\n/**\n * Creates a token set from a query clause.\n *\n * @private\n * @param {Object} clause - A single clause from lunr.Query.\n * @param {string} clause.term - The query clause term.\n * @param {number} [clause.editDistance] - The optional edit distance for the term.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromClause = function (clause) {\n if ('editDistance' in clause) {\n return lunr.TokenSet.fromFuzzyString(clause.term, clause.editDistance)\n } else {\n return lunr.TokenSet.fromString(clause.term)\n }\n}\n\n/**\n * Creates a token set representing a single string with a specified\n * edit distance.\n *\n * Insertions, deletions, substitutions and transpositions are each\n * treated as an edit distance of 1.\n *\n * Increasing the allowed edit distance will have a dramatic impact\n * on the performance of both creating and intersecting these TokenSets.\n * It is advised to keep the edit distance less than 3.\n *\n * @param {string} str - The string to create the token set from.\n * @param {number} editDistance - The allowed edit distance to match.\n * @returns {lunr.Vector}\n */\nlunr.TokenSet.fromFuzzyString = function (str, editDistance) {\n var root = new lunr.TokenSet\n\n var stack = [{\n node: root,\n editsRemaining: editDistance,\n str: str\n }]\n\n while (stack.length) {\n var frame = stack.pop()\n\n // no edit\n if (frame.str.length > 0) {\n var char = frame.str.charAt(0),\n noEditNode\n\n if (char in frame.node.edges) {\n noEditNode = frame.node.edges[char]\n } else {\n noEditNode = new lunr.TokenSet\n frame.node.edges[char] = noEditNode\n }\n\n if (frame.str.length == 1) {\n noEditNode.final = true\n }\n\n stack.push({\n node: noEditNode,\n editsRemaining: frame.editsRemaining,\n str: frame.str.slice(1)\n })\n }\n\n if (frame.editsRemaining == 0) {\n continue\n }\n\n // insertion\n if (\"*\" in frame.node.edges) {\n var insertionNode = frame.node.edges[\"*\"]\n } else {\n var insertionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = insertionNode\n }\n\n if (frame.str.length == 0) {\n insertionNode.final = true\n }\n\n stack.push({\n node: insertionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str\n })\n\n // deletion\n // can only do a deletion if we have enough edits remaining\n // and if there are characters left to delete in the string\n if (frame.str.length > 1) {\n stack.push({\n node: frame.node,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // deletion\n // just removing the last character from the str\n if (frame.str.length == 1) {\n frame.node.final = true\n }\n\n // substitution\n // can only do a substitution if we have enough edits remaining\n // and if there are characters left to substitute\n if (frame.str.length >= 1) {\n if (\"*\" in frame.node.edges) {\n var substitutionNode = frame.node.edges[\"*\"]\n } else {\n var substitutionNode = new lunr.TokenSet\n frame.node.edges[\"*\"] = substitutionNode\n }\n\n if (frame.str.length == 1) {\n substitutionNode.final = true\n }\n\n stack.push({\n node: substitutionNode,\n editsRemaining: frame.editsRemaining - 1,\n str: frame.str.slice(1)\n })\n }\n\n // transposition\n // can only do a transposition if there are edits remaining\n // and there are enough characters to transpose\n if (frame.str.length > 1) {\n var charA = frame.str.charAt(0),\n charB = frame.str.charAt(1),\n transposeNode\n\n if (charB in frame.node.edges) {\n transposeNode = frame.node.edges[charB]\n } else {\n transposeNode = new lunr.TokenSet\n frame.node.edges[charB] = transposeNode\n }\n\n if (frame.str.length == 1) {\n transposeNode.final = true\n }\n\n stack.push({\n node: transposeNode,\n editsRemaining: frame.editsRemaining - 1,\n str: charA + frame.str.slice(2)\n })\n }\n }\n\n return root\n}\n\n/**\n * Creates a TokenSet from a string.\n *\n * The string may contain one or more wildcard characters (*)\n * that will allow wildcard matching when intersecting with\n * another TokenSet.\n *\n * @param {string} str - The string to create a TokenSet from.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.fromString = function (str) {\n var node = new lunr.TokenSet,\n root = node\n\n /*\n * Iterates through all characters within the passed string\n * appending a node for each character.\n *\n * When a wildcard character is found then a self\n * referencing edge is introduced to continually match\n * any number of any characters.\n */\n for (var i = 0, len = str.length; i < len; i++) {\n var char = str[i],\n final = (i == len - 1)\n\n if (char == \"*\") {\n node.edges[char] = node\n node.final = final\n\n } else {\n var next = new lunr.TokenSet\n next.final = final\n\n node.edges[char] = next\n node = next\n }\n }\n\n return root\n}\n\n/**\n * Converts this TokenSet into an array of strings\n * contained within the TokenSet.\n *\n * This is not intended to be used on a TokenSet that\n * contains wildcards, in these cases the results are\n * undefined and are likely to cause an infinite loop.\n *\n * @returns {string[]}\n */\nlunr.TokenSet.prototype.toArray = function () {\n var words = []\n\n var stack = [{\n prefix: \"\",\n node: this\n }]\n\n while (stack.length) {\n var frame = stack.pop(),\n edges = Object.keys(frame.node.edges),\n len = edges.length\n\n if (frame.node.final) {\n /* In Safari, at this point the prefix is sometimes corrupted, see:\n * https://github.com/olivernn/lunr.js/issues/279 Calling any\n * String.prototype method forces Safari to \"cast\" this string to what\n * it's supposed to be, fixing the bug. */\n frame.prefix.charAt(0)\n words.push(frame.prefix)\n }\n\n for (var i = 0; i < len; i++) {\n var edge = edges[i]\n\n stack.push({\n prefix: frame.prefix.concat(edge),\n node: frame.node.edges[edge]\n })\n }\n }\n\n return words\n}\n\n/**\n * Generates a string representation of a TokenSet.\n *\n * This is intended to allow TokenSets to be used as keys\n * in objects, largely to aid the construction and minimisation\n * of a TokenSet. As such it is not designed to be a human\n * friendly representation of the TokenSet.\n *\n * @returns {string}\n */\nlunr.TokenSet.prototype.toString = function () {\n // NOTE: Using Object.keys here as this.edges is very likely\n // to enter 'hash-mode' with many keys being added\n //\n // avoiding a for-in loop here as it leads to the function\n // being de-optimised (at least in V8). From some simple\n // benchmarks the performance is comparable, but allowing\n // V8 to optimize may mean easy performance wins in the future.\n\n if (this._str) {\n return this._str\n }\n\n var str = this.final ? '1' : '0',\n labels = Object.keys(this.edges).sort(),\n len = labels.length\n\n for (var i = 0; i < len; i++) {\n var label = labels[i],\n node = this.edges[label]\n\n str = str + label + node.id\n }\n\n return str\n}\n\n/**\n * Returns a new TokenSet that is the intersection of\n * this TokenSet and the passed TokenSet.\n *\n * This intersection will take into account any wildcards\n * contained within the TokenSet.\n *\n * @param {lunr.TokenSet} b - An other TokenSet to intersect with.\n * @returns {lunr.TokenSet}\n */\nlunr.TokenSet.prototype.intersect = function (b) {\n var output = new lunr.TokenSet,\n frame = undefined\n\n var stack = [{\n qNode: b,\n output: output,\n node: this\n }]\n\n while (stack.length) {\n frame = stack.pop()\n\n // NOTE: As with the #toString method, we are using\n // Object.keys and a for loop instead of a for-in loop\n // as both of these objects enter 'hash' mode, causing\n // the function to be de-optimised in V8\n var qEdges = Object.keys(frame.qNode.edges),\n qLen = qEdges.length,\n nEdges = Object.keys(frame.node.edges),\n nLen = nEdges.length\n\n for (var q = 0; q < qLen; q++) {\n var qEdge = qEdges[q]\n\n for (var n = 0; n < nLen; n++) {\n var nEdge = nEdges[n]\n\n if (nEdge == qEdge || qEdge == '*') {\n var node = frame.node.edges[nEdge],\n qNode = frame.qNode.edges[qEdge],\n final = node.final && qNode.final,\n next = undefined\n\n if (nEdge in frame.output.edges) {\n // an edge already exists for this character\n // no need to create a new node, just set the finality\n // bit unless this node is already final\n next = frame.output.edges[nEdge]\n next.final = next.final || final\n\n } else {\n // no edge exists yet, must create one\n // set the finality bit and insert it\n // into the output\n next = new lunr.TokenSet\n next.final = final\n frame.output.edges[nEdge] = next\n }\n\n stack.push({\n qNode: qNode,\n output: next,\n node: node\n })\n }\n }\n }\n }\n\n return output\n}\nlunr.TokenSet.Builder = function () {\n this.previousWord = \"\"\n this.root = new lunr.TokenSet\n this.uncheckedNodes = []\n this.minimizedNodes = {}\n}\n\nlunr.TokenSet.Builder.prototype.insert = function (word) {\n var node,\n commonPrefix = 0\n\n if (word < this.previousWord) {\n throw new Error (\"Out of order word insertion\")\n }\n\n for (var i = 0; i < word.length && i < this.previousWord.length; i++) {\n if (word[i] != this.previousWord[i]) break\n commonPrefix++\n }\n\n this.minimize(commonPrefix)\n\n if (this.uncheckedNodes.length == 0) {\n node = this.root\n } else {\n node = this.uncheckedNodes[this.uncheckedNodes.length - 1].child\n }\n\n for (var i = commonPrefix; i < word.length; i++) {\n var nextNode = new lunr.TokenSet,\n char = word[i]\n\n node.edges[char] = nextNode\n\n this.uncheckedNodes.push({\n parent: node,\n char: char,\n child: nextNode\n })\n\n node = nextNode\n }\n\n node.final = true\n this.previousWord = word\n}\n\nlunr.TokenSet.Builder.prototype.finish = function () {\n this.minimize(0)\n}\n\nlunr.TokenSet.Builder.prototype.minimize = function (downTo) {\n for (var i = this.uncheckedNodes.length - 1; i >= downTo; i--) {\n var node = this.uncheckedNodes[i],\n childKey = node.child.toString()\n\n if (childKey in this.minimizedNodes) {\n node.parent.edges[node.char] = this.minimizedNodes[childKey]\n } else {\n // Cache the key for this node since\n // we know it can't change anymore\n node.child._str = childKey\n\n this.minimizedNodes[childKey] = node.child\n }\n\n this.uncheckedNodes.pop()\n }\n}\n/*!\n * lunr.Index\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * An index contains the built index of all documents and provides a query interface\n * to the index.\n *\n * Usually instances of lunr.Index will not be created using this constructor, instead\n * lunr.Builder should be used to construct new indexes, or lunr.Index.load should be\n * used to load previously built and serialized indexes.\n *\n * @constructor\n * @param {Object} attrs - The attributes of the built search index.\n * @param {Object} attrs.invertedIndex - An index of term/field to document reference.\n * @param {Object} attrs.fieldVectors - Field vectors\n * @param {lunr.TokenSet} attrs.tokenSet - An set of all corpus tokens.\n * @param {string[]} attrs.fields - The names of indexed document fields.\n * @param {lunr.Pipeline} attrs.pipeline - The pipeline to use for search terms.\n */\nlunr.Index = function (attrs) {\n this.invertedIndex = attrs.invertedIndex\n this.fieldVectors = attrs.fieldVectors\n this.tokenSet = attrs.tokenSet\n this.fields = attrs.fields\n this.pipeline = attrs.pipeline\n}\n\n/**\n * A result contains details of a document matching a search query.\n * @typedef {Object} lunr.Index~Result\n * @property {string} ref - The reference of the document this result represents.\n * @property {number} score - A number between 0 and 1 representing how similar this document is to the query.\n * @property {lunr.MatchData} matchData - Contains metadata about this match including which term(s) caused the match.\n */\n\n/**\n * Although lunr provides the ability to create queries using lunr.Query, it also provides a simple\n * query language which itself is parsed into an instance of lunr.Query.\n *\n * For programmatically building queries it is advised to directly use lunr.Query, the query language\n * is best used for human entered text rather than program generated text.\n *\n * At its simplest queries can just be a single term, e.g. `hello`, multiple terms are also supported\n * and will be combined with OR, e.g `hello world` will match documents that contain either 'hello'\n * or 'world', though those that contain both will rank higher in the results.\n *\n * Wildcards can be included in terms to match one or more unspecified characters, these wildcards can\n * be inserted anywhere within the term, and more than one wildcard can exist in a single term. Adding\n * wildcards will increase the number of documents that will be found but can also have a negative\n * impact on query performance, especially with wildcards at the beginning of a term.\n *\n * Terms can be restricted to specific fields, e.g. `title:hello`, only documents with the term\n * hello in the title field will match this query. Using a field not present in the index will lead\n * to an error being thrown.\n *\n * Modifiers can also be added to terms, lunr supports edit distance and boost modifiers on terms. A term\n * boost will make documents matching that term score higher, e.g. `foo^5`. Edit distance is also supported\n * to provide fuzzy matching, e.g. 'hello~2' will match documents with hello with an edit distance of 2.\n * Avoid large values for edit distance to improve query performance.\n *\n * Each term also supports a presence modifier. By default a term's presence in document is optional, however\n * this can be changed to either required or prohibited. For a term's presence to be required in a document the\n * term should be prefixed with a '+', e.g. `+foo bar` is a search for documents that must contain 'foo' and\n * optionally contain 'bar'. Conversely a leading '-' sets the terms presence to prohibited, i.e. it must not\n * appear in a document, e.g. `-foo bar` is a search for documents that do not contain 'foo' but may contain 'bar'.\n *\n * To escape special characters the backslash character '\\' can be used, this allows searches to include\n * characters that would normally be considered modifiers, e.g. `foo\\~2` will search for a term \"foo~2\" instead\n * of attempting to apply a boost of 2 to the search term \"foo\".\n *\n * @typedef {string} lunr.Index~QueryString\n * @example Simple single term query\n * hello\n * @example Multiple term query\n * hello world\n * @example term scoped to a field\n * title:hello\n * @example term with a boost of 10\n * hello^10\n * @example term with an edit distance of 2\n * hello~2\n * @example terms with presence modifiers\n * -foo +bar baz\n */\n\n/**\n * Performs a search against the index using lunr query syntax.\n *\n * Results will be returned sorted by their score, the most relevant results\n * will be returned first. For details on how the score is calculated, please see\n * the {@link https://lunrjs.com/guides/searching.html#scoring|guide}.\n *\n * For more programmatic querying use lunr.Index#query.\n *\n * @param {lunr.Index~QueryString} queryString - A string containing a lunr query.\n * @throws {lunr.QueryParseError} If the passed query string cannot be parsed.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.search = function (queryString) {\n return this.query(function (query) {\n var parser = new lunr.QueryParser(queryString, query)\n parser.parse()\n })\n}\n\n/**\n * A query builder callback provides a query object to be used to express\n * the query to perform on the index.\n *\n * @callback lunr.Index~queryBuilder\n * @param {lunr.Query} query - The query object to build up.\n * @this lunr.Query\n */\n\n/**\n * Performs a query against the index using the yielded lunr.Query object.\n *\n * If performing programmatic queries against the index, this method is preferred\n * over lunr.Index#search so as to avoid the additional query parsing overhead.\n *\n * A query object is yielded to the supplied function which should be used to\n * express the query to be run against the index.\n *\n * Note that although this function takes a callback parameter it is _not_ an\n * asynchronous operation, the callback is just yielded a query object to be\n * customized.\n *\n * @param {lunr.Index~queryBuilder} fn - A function that is used to build the query.\n * @returns {lunr.Index~Result[]}\n */\nlunr.Index.prototype.query = function (fn) {\n // for each query clause\n // * process terms\n // * expand terms from token set\n // * find matching documents and metadata\n // * get document vectors\n // * score documents\n\n var query = new lunr.Query(this.fields),\n matchingFields = Object.create(null),\n queryVectors = Object.create(null),\n termFieldCache = Object.create(null),\n requiredMatches = Object.create(null),\n prohibitedMatches = Object.create(null)\n\n /*\n * To support field level boosts a query vector is created per\n * field. An empty vector is eagerly created to support negated\n * queries.\n */\n for (var i = 0; i < this.fields.length; i++) {\n queryVectors[this.fields[i]] = new lunr.Vector\n }\n\n fn.call(query, query)\n\n for (var i = 0; i < query.clauses.length; i++) {\n /*\n * Unless the pipeline has been disabled for this term, which is\n * the case for terms with wildcards, we need to pass the clause\n * term through the search pipeline. A pipeline returns an array\n * of processed terms. Pipeline functions may expand the passed\n * term, which means we may end up performing multiple index lookups\n * for a single query term.\n */\n var clause = query.clauses[i],\n terms = null,\n clauseMatches = lunr.Set.empty\n\n if (clause.usePipeline) {\n terms = this.pipeline.runString(clause.term, {\n fields: clause.fields\n })\n } else {\n terms = [clause.term]\n }\n\n for (var m = 0; m < terms.length; m++) {\n var term = terms[m]\n\n /*\n * Each term returned from the pipeline needs to use the same query\n * clause object, e.g. the same boost and or edit distance. The\n * simplest way to do this is to re-use the clause object but mutate\n * its term property.\n */\n clause.term = term\n\n /*\n * From the term in the clause we create a token set which will then\n * be used to intersect the indexes token set to get a list of terms\n * to lookup in the inverted index\n */\n var termTokenSet = lunr.TokenSet.fromClause(clause),\n expandedTerms = this.tokenSet.intersect(termTokenSet).toArray()\n\n /*\n * If a term marked as required does not exist in the tokenSet it is\n * impossible for the search to return any matches. We set all the field\n * scoped required matches set to empty and stop examining any further\n * clauses.\n */\n if (expandedTerms.length === 0 && clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = lunr.Set.empty\n }\n\n break\n }\n\n for (var j = 0; j < expandedTerms.length; j++) {\n /*\n * For each term get the posting and termIndex, this is required for\n * building the query vector.\n */\n var expandedTerm = expandedTerms[j],\n posting = this.invertedIndex[expandedTerm],\n termIndex = posting._index\n\n for (var k = 0; k < clause.fields.length; k++) {\n /*\n * For each field that this query term is scoped by (by default\n * all fields are in scope) we need to get all the document refs\n * that have this term in that field.\n *\n * The posting is the entry in the invertedIndex for the matching\n * term from above.\n */\n var field = clause.fields[k],\n fieldPosting = posting[field],\n matchingDocumentRefs = Object.keys(fieldPosting),\n termField = expandedTerm + \"/\" + field,\n matchingDocumentsSet = new lunr.Set(matchingDocumentRefs)\n\n /*\n * if the presence of this term is required ensure that the matching\n * documents are added to the set of required matches for this clause.\n *\n */\n if (clause.presence == lunr.Query.presence.REQUIRED) {\n clauseMatches = clauseMatches.union(matchingDocumentsSet)\n\n if (requiredMatches[field] === undefined) {\n requiredMatches[field] = lunr.Set.complete\n }\n }\n\n /*\n * if the presence of this term is prohibited ensure that the matching\n * documents are added to the set of prohibited matches for this field,\n * creating that set if it does not yet exist.\n */\n if (clause.presence == lunr.Query.presence.PROHIBITED) {\n if (prohibitedMatches[field] === undefined) {\n prohibitedMatches[field] = lunr.Set.empty\n }\n\n prohibitedMatches[field] = prohibitedMatches[field].union(matchingDocumentsSet)\n\n /*\n * Prohibited matches should not be part of the query vector used for\n * similarity scoring and no metadata should be extracted so we continue\n * to the next field\n */\n continue\n }\n\n /*\n * The query field vector is populated using the termIndex found for\n * the term and a unit value with the appropriate boost applied.\n * Using upsert because there could already be an entry in the vector\n * for the term we are working with. In that case we just add the scores\n * together.\n */\n queryVectors[field].upsert(termIndex, clause.boost, function (a, b) { return a + b })\n\n /**\n * If we've already seen this term, field combo then we've already collected\n * the matching documents and metadata, no need to go through all that again\n */\n if (termFieldCache[termField]) {\n continue\n }\n\n for (var l = 0; l < matchingDocumentRefs.length; l++) {\n /*\n * All metadata for this term/field/document triple\n * are then extracted and collected into an instance\n * of lunr.MatchData ready to be returned in the query\n * results\n */\n var matchingDocumentRef = matchingDocumentRefs[l],\n matchingFieldRef = new lunr.FieldRef (matchingDocumentRef, field),\n metadata = fieldPosting[matchingDocumentRef],\n fieldMatch\n\n if ((fieldMatch = matchingFields[matchingFieldRef]) === undefined) {\n matchingFields[matchingFieldRef] = new lunr.MatchData (expandedTerm, field, metadata)\n } else {\n fieldMatch.add(expandedTerm, field, metadata)\n }\n\n }\n\n termFieldCache[termField] = true\n }\n }\n }\n\n /**\n * If the presence was required we need to update the requiredMatches field sets.\n * We do this after all fields for the term have collected their matches because\n * the clause terms presence is required in _any_ of the fields not _all_ of the\n * fields.\n */\n if (clause.presence === lunr.Query.presence.REQUIRED) {\n for (var k = 0; k < clause.fields.length; k++) {\n var field = clause.fields[k]\n requiredMatches[field] = requiredMatches[field].intersect(clauseMatches)\n }\n }\n }\n\n /**\n * Need to combine the field scoped required and prohibited\n * matching documents into a global set of required and prohibited\n * matches\n */\n var allRequiredMatches = lunr.Set.complete,\n allProhibitedMatches = lunr.Set.empty\n\n for (var i = 0; i < this.fields.length; i++) {\n var field = this.fields[i]\n\n if (requiredMatches[field]) {\n allRequiredMatches = allRequiredMatches.intersect(requiredMatches[field])\n }\n\n if (prohibitedMatches[field]) {\n allProhibitedMatches = allProhibitedMatches.union(prohibitedMatches[field])\n }\n }\n\n var matchingFieldRefs = Object.keys(matchingFields),\n results = [],\n matches = Object.create(null)\n\n /*\n * If the query is negated (contains only prohibited terms)\n * we need to get _all_ fieldRefs currently existing in the\n * index. This is only done when we know that the query is\n * entirely prohibited terms to avoid any cost of getting all\n * fieldRefs unnecessarily.\n *\n * Additionally, blank MatchData must be created to correctly\n * populate the results.\n */\n if (query.isNegated()) {\n matchingFieldRefs = Object.keys(this.fieldVectors)\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n var matchingFieldRef = matchingFieldRefs[i]\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRef)\n matchingFields[matchingFieldRef] = new lunr.MatchData\n }\n }\n\n for (var i = 0; i < matchingFieldRefs.length; i++) {\n /*\n * Currently we have document fields that match the query, but we\n * need to return documents. The matchData and scores are combined\n * from multiple fields belonging to the same document.\n *\n * Scores are calculated by field, using the query vectors created\n * above, and combined into a final document score using addition.\n */\n var fieldRef = lunr.FieldRef.fromString(matchingFieldRefs[i]),\n docRef = fieldRef.docRef\n\n if (!allRequiredMatches.contains(docRef)) {\n continue\n }\n\n if (allProhibitedMatches.contains(docRef)) {\n continue\n }\n\n var fieldVector = this.fieldVectors[fieldRef],\n score = queryVectors[fieldRef.fieldName].similarity(fieldVector),\n docMatch\n\n if ((docMatch = matches[docRef]) !== undefined) {\n docMatch.score += score\n docMatch.matchData.combine(matchingFields[fieldRef])\n } else {\n var match = {\n ref: docRef,\n score: score,\n matchData: matchingFields[fieldRef]\n }\n matches[docRef] = match\n results.push(match)\n }\n }\n\n /*\n * Sort the results objects by score, highest first.\n */\n return results.sort(function (a, b) {\n return b.score - a.score\n })\n}\n\n/**\n * Prepares the index for JSON serialization.\n *\n * The schema for this JSON blob will be described in a\n * separate JSON schema file.\n *\n * @returns {Object}\n */\nlunr.Index.prototype.toJSON = function () {\n var invertedIndex = Object.keys(this.invertedIndex)\n .sort()\n .map(function (term) {\n return [term, this.invertedIndex[term]]\n }, this)\n\n var fieldVectors = Object.keys(this.fieldVectors)\n .map(function (ref) {\n return [ref, this.fieldVectors[ref].toJSON()]\n }, this)\n\n return {\n version: lunr.version,\n fields: this.fields,\n fieldVectors: fieldVectors,\n invertedIndex: invertedIndex,\n pipeline: this.pipeline.toJSON()\n }\n}\n\n/**\n * Loads a previously serialized lunr.Index\n *\n * @param {Object} serializedIndex - A previously serialized lunr.Index\n * @returns {lunr.Index}\n */\nlunr.Index.load = function (serializedIndex) {\n var attrs = {},\n fieldVectors = {},\n serializedVectors = serializedIndex.fieldVectors,\n invertedIndex = Object.create(null),\n serializedInvertedIndex = serializedIndex.invertedIndex,\n tokenSetBuilder = new lunr.TokenSet.Builder,\n pipeline = lunr.Pipeline.load(serializedIndex.pipeline)\n\n if (serializedIndex.version != lunr.version) {\n lunr.utils.warn(\"Version mismatch when loading serialised index. Current version of lunr '\" + lunr.version + \"' does not match serialized index '\" + serializedIndex.version + \"'\")\n }\n\n for (var i = 0; i < serializedVectors.length; i++) {\n var tuple = serializedVectors[i],\n ref = tuple[0],\n elements = tuple[1]\n\n fieldVectors[ref] = new lunr.Vector(elements)\n }\n\n for (var i = 0; i < serializedInvertedIndex.length; i++) {\n var tuple = serializedInvertedIndex[i],\n term = tuple[0],\n posting = tuple[1]\n\n tokenSetBuilder.insert(term)\n invertedIndex[term] = posting\n }\n\n tokenSetBuilder.finish()\n\n attrs.fields = serializedIndex.fields\n\n attrs.fieldVectors = fieldVectors\n attrs.invertedIndex = invertedIndex\n attrs.tokenSet = tokenSetBuilder.root\n attrs.pipeline = pipeline\n\n return new lunr.Index(attrs)\n}\n/*!\n * lunr.Builder\n * Copyright (C) 2020 Oliver Nightingale\n */\n\n/**\n * lunr.Builder performs indexing on a set of documents and\n * returns instances of lunr.Index ready for querying.\n *\n * All configuration of the index is done via the builder, the\n * fields to index, the document reference, the text processing\n * pipeline and document scoring parameters are all set on the\n * builder before indexing.\n *\n * @constructor\n * @property {string} _ref - Internal reference to the document reference field.\n * @property {string[]} _fields - Internal reference to the document fields to index.\n * @property {object} invertedIndex - The inverted index maps terms to document fields.\n * @property {object} documentTermFrequencies - Keeps track of document term frequencies.\n * @property {object} documentLengths - Keeps track of the length of documents added to the index.\n * @property {lunr.tokenizer} tokenizer - Function for splitting strings into tokens for indexing.\n * @property {lunr.Pipeline} pipeline - The pipeline performs text processing on tokens before indexing.\n * @property {lunr.Pipeline} searchPipeline - A pipeline for processing search terms before querying the index.\n * @property {number} documentCount - Keeps track of the total number of documents indexed.\n * @property {number} _b - A parameter to control field length normalization, setting this to 0 disabled normalization, 1 fully normalizes field lengths, the default value is 0.75.\n * @property {number} _k1 - A parameter to control how quickly an increase in term frequency results in term frequency saturation, the default value is 1.2.\n * @property {number} termIndex - A counter incremented for each unique term, used to identify a terms position in the vector space.\n * @property {array} metadataWhitelist - A list of metadata keys that have been whitelisted for entry in the index.\n */\nlunr.Builder = function () {\n this._ref = \"id\"\n this._fields = Object.create(null)\n this._documents = Object.create(null)\n this.invertedIndex = Object.create(null)\n this.fieldTermFrequencies = {}\n this.fieldLengths = {}\n this.tokenizer = lunr.tokenizer\n this.pipeline = new lunr.Pipeline\n this.searchPipeline = new lunr.Pipeline\n this.documentCount = 0\n this._b = 0.75\n this._k1 = 1.2\n this.termIndex = 0\n this.metadataWhitelist = []\n}\n\n/**\n * Sets the document field used as the document reference. Every document must have this field.\n * The type of this field in the document should be a string, if it is not a string it will be\n * coerced into a string by calling toString.\n *\n * The default ref is 'id'.\n *\n * The ref should _not_ be changed during indexing, it should be set before any documents are\n * added to the index. Changing it during indexing can lead to inconsistent results.\n *\n * @param {string} ref - The name of the reference field in the document.\n */\nlunr.Builder.prototype.ref = function (ref) {\n this._ref = ref\n}\n\n/**\n * A function that is used to extract a field from a document.\n *\n * Lunr expects a field to be at the top level of a document, if however the field\n * is deeply nested within a document an extractor function can be used to extract\n * the right field for indexing.\n *\n * @callback fieldExtractor\n * @param {object} doc - The document being added to the index.\n * @returns {?(string|object|object[])} obj - The object that will be indexed for this field.\n * @example Extracting a nested field\n * function (doc) { return doc.nested.field }\n */\n\n/**\n * Adds a field to the list of document fields that will be indexed. Every document being\n * indexed should have this field. Null values for this field in indexed documents will\n * not cause errors but will limit the chance of that document being retrieved by searches.\n *\n * All fields should be added before adding documents to the index. Adding fields after\n * a document has been indexed will have no effect on already indexed documents.\n *\n * Fields can be boosted at build time. This allows terms within that field to have more\n * importance when ranking search results. Use a field boost to specify that matches within\n * one field are more important than other fields.\n *\n * @param {string} fieldName - The name of a field to index in all documents.\n * @param {object} attributes - Optional attributes associated with this field.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this field.\n * @param {fieldExtractor} [attributes.extractor] - Function to extract a field from a document.\n * @throws {RangeError} fieldName cannot contain unsupported characters '/'\n */\nlunr.Builder.prototype.field = function (fieldName, attributes) {\n if (/\\//.test(fieldName)) {\n throw new RangeError (\"Field '\" + fieldName + \"' contains illegal character '/'\")\n }\n\n this._fields[fieldName] = attributes || {}\n}\n\n/**\n * A parameter to tune the amount of field length normalisation that is applied when\n * calculating relevance scores. A value of 0 will completely disable any normalisation\n * and a value of 1 will fully normalise field lengths. The default is 0.75. Values of b\n * will be clamped to the range 0 - 1.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.b = function (number) {\n if (number < 0) {\n this._b = 0\n } else if (number > 1) {\n this._b = 1\n } else {\n this._b = number\n }\n}\n\n/**\n * A parameter that controls the speed at which a rise in term frequency results in term\n * frequency saturation. The default value is 1.2. Setting this to a higher value will give\n * slower saturation levels, a lower value will result in quicker saturation.\n *\n * @param {number} number - The value to set for this tuning parameter.\n */\nlunr.Builder.prototype.k1 = function (number) {\n this._k1 = number\n}\n\n/**\n * Adds a document to the index.\n *\n * Before adding fields to the index the index should have been fully setup, with the document\n * ref and all fields to index already having been specified.\n *\n * The document must have a field name as specified by the ref (by default this is 'id') and\n * it should have all fields defined for indexing, though null or undefined values will not\n * cause errors.\n *\n * Entire documents can be boosted at build time. Applying a boost to a document indicates that\n * this document should rank higher in search results than other documents.\n *\n * @param {object} doc - The document to add to the index.\n * @param {object} attributes - Optional attributes associated with this document.\n * @param {number} [attributes.boost=1] - Boost applied to all terms within this document.\n */\nlunr.Builder.prototype.add = function (doc, attributes) {\n var docRef = doc[this._ref],\n fields = Object.keys(this._fields)\n\n this._documents[docRef] = attributes || {}\n this.documentCount += 1\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i],\n extractor = this._fields[fieldName].extractor,\n field = extractor ? extractor(doc) : doc[fieldName],\n tokens = this.tokenizer(field, {\n fields: [fieldName]\n }),\n terms = this.pipeline.run(tokens),\n fieldRef = new lunr.FieldRef (docRef, fieldName),\n fieldTerms = Object.create(null)\n\n this.fieldTermFrequencies[fieldRef] = fieldTerms\n this.fieldLengths[fieldRef] = 0\n\n // store the length of this field for this document\n this.fieldLengths[fieldRef] += terms.length\n\n // calculate term frequencies for this field\n for (var j = 0; j < terms.length; j++) {\n var term = terms[j]\n\n if (fieldTerms[term] == undefined) {\n fieldTerms[term] = 0\n }\n\n fieldTerms[term] += 1\n\n // add to inverted index\n // create an initial posting if one doesn't exist\n if (this.invertedIndex[term] == undefined) {\n var posting = Object.create(null)\n posting[\"_index\"] = this.termIndex\n this.termIndex += 1\n\n for (var k = 0; k < fields.length; k++) {\n posting[fields[k]] = Object.create(null)\n }\n\n this.invertedIndex[term] = posting\n }\n\n // add an entry for this term/fieldName/docRef to the invertedIndex\n if (this.invertedIndex[term][fieldName][docRef] == undefined) {\n this.invertedIndex[term][fieldName][docRef] = Object.create(null)\n }\n\n // store all whitelisted metadata about this token in the\n // inverted index\n for (var l = 0; l < this.metadataWhitelist.length; l++) {\n var metadataKey = this.metadataWhitelist[l],\n metadata = term.metadata[metadataKey]\n\n if (this.invertedIndex[term][fieldName][docRef][metadataKey] == undefined) {\n this.invertedIndex[term][fieldName][docRef][metadataKey] = []\n }\n\n this.invertedIndex[term][fieldName][docRef][metadataKey].push(metadata)\n }\n }\n\n }\n}\n\n/**\n * Calculates the average document length for this index\n *\n * @private\n */\nlunr.Builder.prototype.calculateAverageFieldLengths = function () {\n\n var fieldRefs = Object.keys(this.fieldLengths),\n numberOfFields = fieldRefs.length,\n accumulator = {},\n documentsWithField = {}\n\n for (var i = 0; i < numberOfFields; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n field = fieldRef.fieldName\n\n documentsWithField[field] || (documentsWithField[field] = 0)\n documentsWithField[field] += 1\n\n accumulator[field] || (accumulator[field] = 0)\n accumulator[field] += this.fieldLengths[fieldRef]\n }\n\n var fields = Object.keys(this._fields)\n\n for (var i = 0; i < fields.length; i++) {\n var fieldName = fields[i]\n accumulator[fieldName] = accumulator[fieldName] / documentsWithField[fieldName]\n }\n\n this.averageFieldLength = accumulator\n}\n\n/**\n * Builds a vector space model of every document using lunr.Vector\n *\n * @private\n */\nlunr.Builder.prototype.createFieldVectors = function () {\n var fieldVectors = {},\n fieldRefs = Object.keys(this.fieldTermFrequencies),\n fieldRefsLength = fieldRefs.length,\n termIdfCache = Object.create(null)\n\n for (var i = 0; i < fieldRefsLength; i++) {\n var fieldRef = lunr.FieldRef.fromString(fieldRefs[i]),\n fieldName = fieldRef.fieldName,\n fieldLength = this.fieldLengths[fieldRef],\n fieldVector = new lunr.Vector,\n termFrequencies = this.fieldTermFrequencies[fieldRef],\n terms = Object.keys(termFrequencies),\n termsLength = terms.length\n\n\n var fieldBoost = this._fields[fieldName].boost || 1,\n docBoost = this._documents[fieldRef.docRef].boost || 1\n\n for (var j = 0; j < termsLength; j++) {\n var term = terms[j],\n tf = termFrequencies[term],\n termIndex = this.invertedIndex[term]._index,\n idf, score, scoreWithPrecision\n\n if (termIdfCache[term] === undefined) {\n idf = lunr.idf(this.invertedIndex[term], this.documentCount)\n termIdfCache[term] = idf\n } else {\n idf = termIdfCache[term]\n }\n\n score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[fieldName])) + tf)\n score *= fieldBoost\n score *= docBoost\n scoreWithPrecision = Math.round(score * 1000) / 1000\n // Converts 1.23456789 to 1.234.\n // Reducing the precision so that the vectors take up less\n // space when serialised. Doing it now so that they behave\n // the same before and after serialisation. Also, this is\n // the fastest approach to reducing a number's precision in\n // JavaScript.\n\n fieldVector.insert(termIndex, scoreWithPrecision)\n }\n\n fieldVectors[fieldRef] = fieldVector\n }\n\n this.fieldVectors = fieldVectors\n}\n\n/**\n * Creates a token set of all tokens in the index using lunr.TokenSet\n *\n * @private\n */\nlunr.Builder.prototype.createTokenSet = function () {\n this.tokenSet = lunr.TokenSet.fromArray(\n Object.keys(this.invertedIndex).sort()\n )\n}\n\n/**\n * Builds the index, creating an instance of lunr.Index.\n *\n * This completes the indexing process and should only be called\n * once all documents have been added to the index.\n *\n * @returns {lunr.Index}\n */\nlunr.Builder.prototype.build = function () {\n this.calculateAverageFieldLengths()\n this.createFieldVectors()\n this.createTokenSet()\n\n return new lunr.Index({\n invertedIndex: this.invertedIndex,\n fieldVectors: this.fieldVectors,\n tokenSet: this.tokenSet,\n fields: Object.keys(this._fields),\n pipeline: this.searchPipeline\n })\n}\n\n/**\n * Applies a plugin to the index builder.\n *\n * A plugin is a function that is called with the index builder as its context.\n * Plugins can be used to customise or extend the behaviour of the index\n * in some way. A plugin is just a function, that encapsulated the custom\n * behaviour that should be applied when building the index.\n *\n * The plugin function will be called with the index builder as its argument, additional\n * arguments can also be passed when calling use. The function will be called\n * with the index builder as its context.\n *\n * @param {Function} plugin The plugin to apply.\n */\nlunr.Builder.prototype.use = function (fn) {\n var args = Array.prototype.slice.call(arguments, 1)\n args.unshift(this)\n fn.apply(this, args)\n}\n/**\n * Contains and collects metadata about a matching document.\n * A single instance of lunr.MatchData is returned as part of every\n * lunr.Index~Result.\n *\n * @constructor\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n * @property {object} metadata - A cloned collection of metadata associated with this document.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData = function (term, field, metadata) {\n var clonedMetadata = Object.create(null),\n metadataKeys = Object.keys(metadata || {})\n\n // Cloning the metadata to prevent the original\n // being mutated during match data combination.\n // Metadata is kept in an array within the inverted\n // index so cloning the data can be done with\n // Array#slice\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n clonedMetadata[key] = metadata[key].slice()\n }\n\n this.metadata = Object.create(null)\n\n if (term !== undefined) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = clonedMetadata\n }\n}\n\n/**\n * An instance of lunr.MatchData will be created for every term that matches a\n * document. However only one instance is required in a lunr.Index~Result. This\n * method combines metadata from another instance of lunr.MatchData with this\n * objects metadata.\n *\n * @param {lunr.MatchData} otherMatchData - Another instance of match data to merge with this one.\n * @see {@link lunr.Index~Result}\n */\nlunr.MatchData.prototype.combine = function (otherMatchData) {\n var terms = Object.keys(otherMatchData.metadata)\n\n for (var i = 0; i < terms.length; i++) {\n var term = terms[i],\n fields = Object.keys(otherMatchData.metadata[term])\n\n if (this.metadata[term] == undefined) {\n this.metadata[term] = Object.create(null)\n }\n\n for (var j = 0; j < fields.length; j++) {\n var field = fields[j],\n keys = Object.keys(otherMatchData.metadata[term][field])\n\n if (this.metadata[term][field] == undefined) {\n this.metadata[term][field] = Object.create(null)\n }\n\n for (var k = 0; k < keys.length; k++) {\n var key = keys[k]\n\n if (this.metadata[term][field][key] == undefined) {\n this.metadata[term][field][key] = otherMatchData.metadata[term][field][key]\n } else {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(otherMatchData.metadata[term][field][key])\n }\n\n }\n }\n }\n}\n\n/**\n * Add metadata for a term/field pair to this instance of match data.\n *\n * @param {string} term - The term this match data is associated with\n * @param {string} field - The field in which the term was found\n * @param {object} metadata - The metadata recorded about this term in this field\n */\nlunr.MatchData.prototype.add = function (term, field, metadata) {\n if (!(term in this.metadata)) {\n this.metadata[term] = Object.create(null)\n this.metadata[term][field] = metadata\n return\n }\n\n if (!(field in this.metadata[term])) {\n this.metadata[term][field] = metadata\n return\n }\n\n var metadataKeys = Object.keys(metadata)\n\n for (var i = 0; i < metadataKeys.length; i++) {\n var key = metadataKeys[i]\n\n if (key in this.metadata[term][field]) {\n this.metadata[term][field][key] = this.metadata[term][field][key].concat(metadata[key])\n } else {\n this.metadata[term][field][key] = metadata[key]\n }\n }\n}\n/**\n * A lunr.Query provides a programmatic way of defining queries to be performed\n * against a {@link lunr.Index}.\n *\n * Prefer constructing a lunr.Query using the {@link lunr.Index#query} method\n * so the query object is pre-initialized with the right index fields.\n *\n * @constructor\n * @property {lunr.Query~Clause[]} clauses - An array of query clauses.\n * @property {string[]} allFields - An array of all available fields in a lunr.Index.\n */\nlunr.Query = function (allFields) {\n this.clauses = []\n this.allFields = allFields\n}\n\n/**\n * Constants for indicating what kind of automatic wildcard insertion will be used when constructing a query clause.\n *\n * This allows wildcards to be added to the beginning and end of a term without having to manually do any string\n * concatenation.\n *\n * The wildcard constants can be bitwise combined to select both leading and trailing wildcards.\n *\n * @constant\n * @default\n * @property {number} wildcard.NONE - The term will have no wildcards inserted, this is the default behaviour\n * @property {number} wildcard.LEADING - Prepend the term with a wildcard, unless a leading wildcard already exists\n * @property {number} wildcard.TRAILING - Append a wildcard to the term, unless a trailing wildcard already exists\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example query term with trailing wildcard\n * query.term('foo', { wildcard: lunr.Query.wildcard.TRAILING })\n * @example query term with leading and trailing wildcard\n * query.term('foo', {\n * wildcard: lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING\n * })\n */\n\nlunr.Query.wildcard = new String (\"*\")\nlunr.Query.wildcard.NONE = 0\nlunr.Query.wildcard.LEADING = 1\nlunr.Query.wildcard.TRAILING = 2\n\n/**\n * Constants for indicating what kind of presence a term must have in matching documents.\n *\n * @constant\n * @enum {number}\n * @see lunr.Query~Clause\n * @see lunr.Query#clause\n * @see lunr.Query#term\n * @example query term with required presence\n * query.term('foo', { presence: lunr.Query.presence.REQUIRED })\n */\nlunr.Query.presence = {\n /**\n * Term's presence in a document is optional, this is the default value.\n */\n OPTIONAL: 1,\n\n /**\n * Term's presence in a document is required, documents that do not contain\n * this term will not be returned.\n */\n REQUIRED: 2,\n\n /**\n * Term's presence in a document is prohibited, documents that do contain\n * this term will not be returned.\n */\n PROHIBITED: 3\n}\n\n/**\n * A single clause in a {@link lunr.Query} contains a term and details on how to\n * match that term against a {@link lunr.Index}.\n *\n * @typedef {Object} lunr.Query~Clause\n * @property {string[]} fields - The fields in an index this clause should be matched against.\n * @property {number} [boost=1] - Any boost that should be applied when matching this clause.\n * @property {number} [editDistance] - Whether the term should have fuzzy matching applied, and how fuzzy the match should be.\n * @property {boolean} [usePipeline] - Whether the term should be passed through the search pipeline.\n * @property {number} [wildcard=lunr.Query.wildcard.NONE] - Whether the term should have wildcards appended or prepended.\n * @property {number} [presence=lunr.Query.presence.OPTIONAL] - The terms presence in any matching documents.\n */\n\n/**\n * Adds a {@link lunr.Query~Clause} to this query.\n *\n * Unless the clause contains the fields to be matched all fields will be matched. In addition\n * a default boost of 1 is applied to the clause.\n *\n * @param {lunr.Query~Clause} clause - The clause to add to this query.\n * @see lunr.Query~Clause\n * @returns {lunr.Query}\n */\nlunr.Query.prototype.clause = function (clause) {\n if (!('fields' in clause)) {\n clause.fields = this.allFields\n }\n\n if (!('boost' in clause)) {\n clause.boost = 1\n }\n\n if (!('usePipeline' in clause)) {\n clause.usePipeline = true\n }\n\n if (!('wildcard' in clause)) {\n clause.wildcard = lunr.Query.wildcard.NONE\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.LEADING) && (clause.term.charAt(0) != lunr.Query.wildcard)) {\n clause.term = \"*\" + clause.term\n }\n\n if ((clause.wildcard & lunr.Query.wildcard.TRAILING) && (clause.term.slice(-1) != lunr.Query.wildcard)) {\n clause.term = \"\" + clause.term + \"*\"\n }\n\n if (!('presence' in clause)) {\n clause.presence = lunr.Query.presence.OPTIONAL\n }\n\n this.clauses.push(clause)\n\n return this\n}\n\n/**\n * A negated query is one in which every clause has a presence of\n * prohibited. These queries require some special processing to return\n * the expected results.\n *\n * @returns boolean\n */\nlunr.Query.prototype.isNegated = function () {\n for (var i = 0; i < this.clauses.length; i++) {\n if (this.clauses[i].presence != lunr.Query.presence.PROHIBITED) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Adds a term to the current query, under the covers this will create a {@link lunr.Query~Clause}\n * to the list of clauses that make up this query.\n *\n * The term is used as is, i.e. no tokenization will be performed by this method. Instead conversion\n * to a token or token-like string should be done before calling this method.\n *\n * The term will be converted to a string by calling `toString`. Multiple terms can be passed as an\n * array, each term in the array will share the same options.\n *\n * @param {object|object[]} term - The term(s) to add to the query.\n * @param {object} [options] - Any additional properties to add to the query clause.\n * @returns {lunr.Query}\n * @see lunr.Query#clause\n * @see lunr.Query~Clause\n * @example adding a single term to a query\n * query.term(\"foo\")\n * @example adding a single term to a query and specifying search fields, term boost and automatic trailing wildcard\n * query.term(\"foo\", {\n * fields: [\"title\"],\n * boost: 10,\n * wildcard: lunr.Query.wildcard.TRAILING\n * })\n * @example using lunr.tokenizer to convert a string to tokens before using them as terms\n * query.term(lunr.tokenizer(\"foo bar\"))\n */\nlunr.Query.prototype.term = function (term, options) {\n if (Array.isArray(term)) {\n term.forEach(function (t) { this.term(t, lunr.utils.clone(options)) }, this)\n return this\n }\n\n var clause = options || {}\n clause.term = term.toString()\n\n this.clause(clause)\n\n return this\n}\nlunr.QueryParseError = function (message, start, end) {\n this.name = \"QueryParseError\"\n this.message = message\n this.start = start\n this.end = end\n}\n\nlunr.QueryParseError.prototype = new Error\nlunr.QueryLexer = function (str) {\n this.lexemes = []\n this.str = str\n this.length = str.length\n this.pos = 0\n this.start = 0\n this.escapeCharPositions = []\n}\n\nlunr.QueryLexer.prototype.run = function () {\n var state = lunr.QueryLexer.lexText\n\n while (state) {\n state = state(this)\n }\n}\n\nlunr.QueryLexer.prototype.sliceString = function () {\n var subSlices = [],\n sliceStart = this.start,\n sliceEnd = this.pos\n\n for (var i = 0; i < this.escapeCharPositions.length; i++) {\n sliceEnd = this.escapeCharPositions[i]\n subSlices.push(this.str.slice(sliceStart, sliceEnd))\n sliceStart = sliceEnd + 1\n }\n\n subSlices.push(this.str.slice(sliceStart, this.pos))\n this.escapeCharPositions.length = 0\n\n return subSlices.join('')\n}\n\nlunr.QueryLexer.prototype.emit = function (type) {\n this.lexemes.push({\n type: type,\n str: this.sliceString(),\n start: this.start,\n end: this.pos\n })\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.escapeCharacter = function () {\n this.escapeCharPositions.push(this.pos - 1)\n this.pos += 1\n}\n\nlunr.QueryLexer.prototype.next = function () {\n if (this.pos >= this.length) {\n return lunr.QueryLexer.EOS\n }\n\n var char = this.str.charAt(this.pos)\n this.pos += 1\n return char\n}\n\nlunr.QueryLexer.prototype.width = function () {\n return this.pos - this.start\n}\n\nlunr.QueryLexer.prototype.ignore = function () {\n if (this.start == this.pos) {\n this.pos += 1\n }\n\n this.start = this.pos\n}\n\nlunr.QueryLexer.prototype.backup = function () {\n this.pos -= 1\n}\n\nlunr.QueryLexer.prototype.acceptDigitRun = function () {\n var char, charCode\n\n do {\n char = this.next()\n charCode = char.charCodeAt(0)\n } while (charCode > 47 && charCode < 58)\n\n if (char != lunr.QueryLexer.EOS) {\n this.backup()\n }\n}\n\nlunr.QueryLexer.prototype.more = function () {\n return this.pos < this.length\n}\n\nlunr.QueryLexer.EOS = 'EOS'\nlunr.QueryLexer.FIELD = 'FIELD'\nlunr.QueryLexer.TERM = 'TERM'\nlunr.QueryLexer.EDIT_DISTANCE = 'EDIT_DISTANCE'\nlunr.QueryLexer.BOOST = 'BOOST'\nlunr.QueryLexer.PRESENCE = 'PRESENCE'\n\nlunr.QueryLexer.lexField = function (lexer) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.FIELD)\n lexer.ignore()\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexTerm = function (lexer) {\n if (lexer.width() > 1) {\n lexer.backup()\n lexer.emit(lunr.QueryLexer.TERM)\n }\n\n lexer.ignore()\n\n if (lexer.more()) {\n return lunr.QueryLexer.lexText\n }\n}\n\nlunr.QueryLexer.lexEditDistance = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.EDIT_DISTANCE)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexBoost = function (lexer) {\n lexer.ignore()\n lexer.acceptDigitRun()\n lexer.emit(lunr.QueryLexer.BOOST)\n return lunr.QueryLexer.lexText\n}\n\nlunr.QueryLexer.lexEOS = function (lexer) {\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n}\n\n// This matches the separator used when tokenising fields\n// within a document. These should match otherwise it is\n// not possible to search for some tokens within a document.\n//\n// It is possible for the user to change the separator on the\n// tokenizer so it _might_ clash with any other of the special\n// characters already used within the search string, e.g. :.\n//\n// This means that it is possible to change the separator in\n// such a way that makes some words unsearchable using a search\n// string.\nlunr.QueryLexer.termSeparator = lunr.tokenizer.separator\n\nlunr.QueryLexer.lexText = function (lexer) {\n while (true) {\n var char = lexer.next()\n\n if (char == lunr.QueryLexer.EOS) {\n return lunr.QueryLexer.lexEOS\n }\n\n // Escape character is '\\'\n if (char.charCodeAt(0) == 92) {\n lexer.escapeCharacter()\n continue\n }\n\n if (char == \":\") {\n return lunr.QueryLexer.lexField\n }\n\n if (char == \"~\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexEditDistance\n }\n\n if (char == \"^\") {\n lexer.backup()\n if (lexer.width() > 0) {\n lexer.emit(lunr.QueryLexer.TERM)\n }\n return lunr.QueryLexer.lexBoost\n }\n\n // \"+\" indicates term presence is required\n // checking for length to ensure that only\n // leading \"+\" are considered\n if (char == \"+\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n // \"-\" indicates term presence is prohibited\n // checking for length to ensure that only\n // leading \"-\" are considered\n if (char == \"-\" && lexer.width() === 1) {\n lexer.emit(lunr.QueryLexer.PRESENCE)\n return lunr.QueryLexer.lexText\n }\n\n if (char.match(lunr.QueryLexer.termSeparator)) {\n return lunr.QueryLexer.lexTerm\n }\n }\n}\n\nlunr.QueryParser = function (str, query) {\n this.lexer = new lunr.QueryLexer (str)\n this.query = query\n this.currentClause = {}\n this.lexemeIdx = 0\n}\n\nlunr.QueryParser.prototype.parse = function () {\n this.lexer.run()\n this.lexemes = this.lexer.lexemes\n\n var state = lunr.QueryParser.parseClause\n\n while (state) {\n state = state(this)\n }\n\n return this.query\n}\n\nlunr.QueryParser.prototype.peekLexeme = function () {\n return this.lexemes[this.lexemeIdx]\n}\n\nlunr.QueryParser.prototype.consumeLexeme = function () {\n var lexeme = this.peekLexeme()\n this.lexemeIdx += 1\n return lexeme\n}\n\nlunr.QueryParser.prototype.nextClause = function () {\n var completedClause = this.currentClause\n this.query.clause(completedClause)\n this.currentClause = {}\n}\n\nlunr.QueryParser.parseClause = function (parser) {\n var lexeme = parser.peekLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.type) {\n case lunr.QueryLexer.PRESENCE:\n return lunr.QueryParser.parsePresence\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expected either a field or a term, found \" + lexeme.type\n\n if (lexeme.str.length >= 1) {\n errorMessage += \" with value '\" + lexeme.str + \"'\"\n }\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n}\n\nlunr.QueryParser.parsePresence = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n switch (lexeme.str) {\n case \"-\":\n parser.currentClause.presence = lunr.Query.presence.PROHIBITED\n break\n case \"+\":\n parser.currentClause.presence = lunr.Query.presence.REQUIRED\n break\n default:\n var errorMessage = \"unrecognised presence operator'\" + lexeme.str + \"'\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term or field, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.FIELD:\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term or field, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseField = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n if (parser.query.allFields.indexOf(lexeme.str) == -1) {\n var possibleFields = parser.query.allFields.map(function (f) { return \"'\" + f + \"'\" }).join(', '),\n errorMessage = \"unrecognised field '\" + lexeme.str + \"', possible fields: \" + possibleFields\n\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.fields = [lexeme.str]\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n var errorMessage = \"expecting term, found nothing\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n return lunr.QueryParser.parseTerm\n default:\n var errorMessage = \"expecting term, found '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseTerm = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n parser.currentClause.term = lexeme.str.toLowerCase()\n\n if (lexeme.str.indexOf(\"*\") != -1) {\n parser.currentClause.usePipeline = false\n }\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseEditDistance = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var editDistance = parseInt(lexeme.str, 10)\n\n if (isNaN(editDistance)) {\n var errorMessage = \"edit distance must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.editDistance = editDistance\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\nlunr.QueryParser.parseBoost = function (parser) {\n var lexeme = parser.consumeLexeme()\n\n if (lexeme == undefined) {\n return\n }\n\n var boost = parseInt(lexeme.str, 10)\n\n if (isNaN(boost)) {\n var errorMessage = \"boost must be numeric\"\n throw new lunr.QueryParseError (errorMessage, lexeme.start, lexeme.end)\n }\n\n parser.currentClause.boost = boost\n\n var nextLexeme = parser.peekLexeme()\n\n if (nextLexeme == undefined) {\n parser.nextClause()\n return\n }\n\n switch (nextLexeme.type) {\n case lunr.QueryLexer.TERM:\n parser.nextClause()\n return lunr.QueryParser.parseTerm\n case lunr.QueryLexer.FIELD:\n parser.nextClause()\n return lunr.QueryParser.parseField\n case lunr.QueryLexer.EDIT_DISTANCE:\n return lunr.QueryParser.parseEditDistance\n case lunr.QueryLexer.BOOST:\n return lunr.QueryParser.parseBoost\n case lunr.QueryLexer.PRESENCE:\n parser.nextClause()\n return lunr.QueryParser.parsePresence\n default:\n var errorMessage = \"Unexpected lexeme type '\" + nextLexeme.type + \"'\"\n throw new lunr.QueryParseError (errorMessage, nextLexeme.start, nextLexeme.end)\n }\n}\n\n /**\n * export the module via AMD, CommonJS or as a browser global\n * Export code from https://github.com/umdjs/umd/blob/master/returnExports.js\n */\n ;(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(factory)\n } else if (typeof exports === 'object') {\n /**\n * Node. Does not work with strict CommonJS, but\n * only CommonJS-like enviroments that support module.exports,\n * like Node.\n */\n module.exports = factory()\n } else {\n // Browser globals (root is window)\n root.lunr = factory()\n }\n }(this, function () {\n /**\n * Just return a value to define the module export.\n * This example returns an object, but the module\n * can return a function as the exported value.\n */\n return lunr\n }))\n})();\n","\"use strict\";\n\n// eslint-disable-next-line func-names\nmodule.exports = function () {\n if (typeof globalThis === \"object\") {\n return globalThis;\n }\n\n var g;\n\n try {\n // This works if eval is allowed (see CSP)\n // eslint-disable-next-line no-new-func\n g = this || new Function(\"return this\")();\n } catch (e) {\n // This works if the window reference is available\n if (typeof window === \"object\") {\n return window;\n } // This works if the self reference is available\n\n\n if (typeof self === \"object\") {\n return self;\n } // This works if the global reference is available\n\n\n if (typeof global !== \"undefined\") {\n return global;\n }\n }\n\n return g;\n}();","var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n","/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, privateMap) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to get private field on non-instance\");\r\n }\r\n return privateMap.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, privateMap, value) {\r\n if (!privateMap.has(receiver)) {\r\n throw new TypeError(\"attempted to set private field on non-instance\");\r\n }\r\n privateMap.set(receiver, value);\r\n return value;\r\n}\r\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndex, SearchResult } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search message type\n */\nexport const enum SearchMessageType {\n SETUP, /* Search index setup */\n READY, /* Search index ready */\n QUERY, /* Search query */\n RESULT /* Search results */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message containing the data necessary to setup the search index\n */\nexport interface SearchSetupMessage {\n type: SearchMessageType.SETUP /* Message type */\n data: SearchIndex /* Message data */\n}\n\n/**\n * A message indicating the search index is ready\n */\nexport interface SearchReadyMessage {\n type: SearchMessageType.READY /* Message type */\n}\n\n/**\n * A message containing a search query\n */\nexport interface SearchQueryMessage {\n type: SearchMessageType.QUERY /* Message type */\n data: string /* Message data */\n}\n\n/**\n * A message containing results for a search query\n */\nexport interface SearchResultMessage {\n type: SearchMessageType.RESULT /* Message type */\n data: SearchResult[] /* Message data */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message exchanged with the search worker\n */\nexport type SearchMessage =\n | SearchSetupMessage\n | SearchReadyMessage\n | SearchQueryMessage\n | SearchResultMessage\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Type guard for search setup messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchSetupMessage(\n message: SearchMessage\n): message is SearchSetupMessage {\n return message.type === SearchMessageType.SETUP\n}\n\n/**\n * Type guard for search ready messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchReadyMessage(\n message: SearchMessage\n): message is SearchReadyMessage {\n return message.type === SearchMessageType.READY\n}\n\n/**\n * Type guard for search query messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchQueryMessage(\n message: SearchMessage\n): message is SearchQueryMessage {\n return message.type === SearchMessageType.QUERY\n}\n\n/**\n * Type guard for search result messages\n *\n * @param message - Search worker message\n *\n * @return Test result\n */\nexport function isSearchResultMessage(\n message: SearchMessage\n): message is SearchResultMessage {\n return message.type === SearchMessageType.RESULT\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n SearchDocument,\n SearchDocumentMap,\n setupSearchDocumentMap\n} from \"../document\"\nimport {\n SearchHighlightFactoryFn,\n setupSearchHighlighter\n} from \"../highlighter\"\nimport {\n SearchQueryTerms,\n getSearchQueryTerms,\n parseSearchQuery\n} from \"../query\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search index configuration\n */\nexport interface SearchIndexConfig {\n lang: string[] /* Search languages */\n separator: string /* Search separator */\n}\n\n/**\n * Search index document\n */\nexport interface SearchIndexDocument {\n location: string /* Document location */\n title: string /* Document title */\n text: string /* Document text */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search index pipeline function\n */\nexport type SearchIndexPipelineFn =\n | \"trimmer\" /* Trimmer */\n | \"stopWordFilter\" /* Stop word filter */\n | \"stemmer\" /* Stemmer */\n\n/**\n * Search index pipeline\n */\nexport type SearchIndexPipeline = SearchIndexPipelineFn[]\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search index\n *\n * This interfaces describes the format of the `search_index.json` file which\n * is automatically built by the MkDocs search plugin.\n */\nexport interface SearchIndex {\n config: SearchIndexConfig /* Search index configuration */\n docs: SearchIndexDocument[] /* Search index documents */\n index?: object /* Prebuilt index */\n pipeline?: SearchIndexPipeline /* Search index pipeline */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search metadata\n */\nexport interface SearchMetadata {\n score: number /* Score (relevance) */\n terms: SearchQueryTerms /* Search query terms */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search result\n */\nexport type SearchResult = Array<\n SearchDocument & SearchMetadata\n> // tslint:disable-line\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Compute the difference of two lists of strings\n *\n * @param a - 1st list of strings\n * @param b - 2nd list of strings\n *\n * @return Difference\n */\nfunction difference(a: string[], b: string[]): string[] {\n const [x, y] = [new Set(a), new Set(b)]\n return [\n ...new Set([...x].filter(value => !y.has(value)))\n ]\n}\n\n/* ----------------------------------------------------------------------------\n * Class\n * ------------------------------------------------------------------------- */\n\n/**\n * Search index\n *\n * Note that `lunr` is injected via Webpack, as it will otherwise also be\n * bundled in the application bundle.\n */\nexport class Search {\n\n /**\n * Search document mapping\n *\n * A mapping of URLs (including hash fragments) to the actual articles and\n * sections of the documentation. The search document mapping must be created\n * regardless of whether the index was prebuilt or not, as `lunr` itself will\n * only store the actual index.\n */\n protected documents: SearchDocumentMap\n\n /**\n * Search highlight factory function\n */\n protected highlight: SearchHighlightFactoryFn\n\n /**\n * The underlying `lunr` search index\n */\n protected index: lunr.Index\n\n /**\n * Create the search integration\n *\n * @param data - Search index\n */\n public constructor({ config, docs, pipeline, index }: SearchIndex) {\n this.documents = setupSearchDocumentMap(docs)\n this.highlight = setupSearchHighlighter(config)\n\n /* Set separator for tokenizer */\n lunr.tokenizer.separator = new RegExp(config.separator)\n\n /* If no index was given, create it */\n if (typeof index === \"undefined\") {\n this.index = lunr(function() {\n\n /* Set up multi-language support */\n if (config.lang.length === 1 && config.lang[0] !== \"en\") {\n this.use((lunr as any)[config.lang[0]])\n } else if (config.lang.length > 1) {\n this.use((lunr as any).multiLanguage(...config.lang))\n }\n\n /* Compute functions to be removed from the pipeline */\n const fns = difference([\n \"trimmer\", \"stopWordFilter\", \"stemmer\"\n ], pipeline!)\n\n /* Remove functions from the pipeline for registered languages */\n for (const lang of config.lang.map(language => (\n language === \"en\" ? lunr : (lunr as any)[language]\n ))) {\n for (const fn of fns) {\n this.pipeline.remove(lang[fn])\n this.searchPipeline.remove(lang[fn])\n }\n }\n\n /* Set up fields and reference */\n this.field(\"title\", { boost: 1000 })\n this.field(\"text\")\n this.ref(\"location\")\n\n /* Index documents */\n for (const doc of docs)\n this.add(doc)\n })\n\n /* Handle prebuilt index */\n } else {\n this.index = lunr.Index.load(index)\n }\n }\n\n /**\n * Search for matching documents\n *\n * The search index which MkDocs provides is divided up into articles, which\n * contain the whole content of the individual pages, and sections, which only\n * contain the contents of the subsections obtained by breaking the individual\n * pages up at `h1` ... `h6`. As there may be many sections on different pages\n * with identical titles (for example within this very project, e.g. \"Usage\"\n * or \"Installation\"), they need to be put into the context of the containing\n * page. For this reason, section results are grouped within their respective\n * articles which are the top-level results that are returned.\n *\n * @param query - Query value\n *\n * @return Search results\n */\n public search(query: string): SearchResult[] {\n if (query) {\n try {\n const highlight = this.highlight(query)\n\n /* Parse query to extract clauses for analysis */\n const clauses = parseSearchQuery(query)\n .filter(clause => (\n clause.presence !== lunr.Query.presence.PROHIBITED\n ))\n\n /* Perform search and post-process results */\n const groups = this.index.search(`${query}*`)\n\n /* Apply post-query boosts based on title and search query terms */\n .reduce((results, { ref, score, matchData }) => {\n const document = this.documents.get(ref)\n if (typeof document !== \"undefined\") {\n const { location, title, text, parent } = document\n\n /* Compute and analyze search query terms */\n const terms = getSearchQueryTerms(\n clauses,\n Object.keys(matchData.metadata)\n )\n\n /* Highlight title and text and apply post-query boosts */\n const boost = +!parent + +Object.values(terms).every(t => t)\n results.push({\n location,\n title: highlight(title),\n text: highlight(text),\n score: score * (1 + boost),\n terms\n })\n }\n return results\n }, [])\n\n /* Sort search results again after applying boosts */\n .sort((a, b) => b.score - a.score)\n\n /* Group search results by page */\n .reduce((results, result) => {\n const document = this.documents.get(result.location)\n if (typeof document !== \"undefined\") {\n const ref = \"parent\" in document\n ? document.parent!.location\n : document.location\n results.set(ref, [...results.get(ref) || [], result])\n }\n return results\n }, new Map())\n\n /* Expand grouped search results */\n return [...groups.values()]\n\n /* Log errors to console (for now) */\n } catch {\n // tslint:disable-next-line no-console\n console.warn(`Invalid query: ${query} – see https://bit.ly/2s3ChXG`)\n }\n }\n\n /* Return nothing in case of error or empty query */\n return []\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n// @ts-ignore\nimport * as escapeHTML from \"escape-html\"\n\nimport { SearchIndexDocument } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search document\n */\nexport interface SearchDocument extends SearchIndexDocument {\n parent?: SearchIndexDocument /* Parent article */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search document mapping\n */\nexport type SearchDocumentMap = Map\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create a search document mapping\n *\n * @param docs - Search index documents\n *\n * @return Search document map\n */\nexport function setupSearchDocumentMap(\n docs: SearchIndexDocument[]\n): SearchDocumentMap {\n const documents = new Map()\n const parents = new Set()\n for (const doc of docs) {\n const [path, hash] = doc.location.split(\"#\")\n\n /* Extract location and title */\n const location = doc.location\n const title = doc.title\n\n /* Escape and cleanup text */\n const text = escapeHTML(doc.text)\n .replace(/\\s+(?=[,.:;!?])/g, \"\")\n .replace(/\\s+/g, \" \")\n\n /* Handle section */\n if (hash) {\n const parent = documents.get(path)!\n\n /* Ignore first section, override article */\n if (!parents.has(parent)) {\n parent.title = doc.title\n parent.text = text\n\n /* Remember that we processed the article */\n parents.add(parent)\n\n /* Add subsequent section */\n } else {\n documents.set(location, {\n location,\n title,\n text,\n parent\n })\n }\n\n /* Add article */\n } else {\n documents.set(location, {\n location,\n title,\n text\n })\n }\n }\n return documents\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndexConfig } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search highlight function\n *\n * @param value - Value\n *\n * @return Highlighted value\n */\nexport type SearchHighlightFn = (value: string) => string\n\n/**\n * Search highlight factory function\n *\n * @param query - Query value\n *\n * @return Search highlight function\n */\nexport type SearchHighlightFactoryFn = (query: string) => SearchHighlightFn\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create a search highlighter\n *\n * @param config - Search index configuration\n *\n * @return Search highlight factory function\n */\nexport function setupSearchHighlighter(\n config: SearchIndexConfig\n): SearchHighlightFactoryFn {\n const separator = new RegExp(config.separator, \"img\")\n const highlight = (_: unknown, data: string, term: string) => {\n return `${data}${term}`\n }\n\n /* Return factory function */\n return (query: string) => {\n query = query\n .replace(/[\\s*+\\-:~^]+/g, \" \")\n .trim()\n\n /* Create search term match expression */\n const match = new RegExp(`(^|${config.separator})(${\n query\n .replace(/[|\\\\{}()[\\]^$+*?.-]/g, \"\\\\$&\")\n .replace(separator, \"|\")\n })`, \"img\")\n\n /* Highlight string value */\n return value => value\n .replace(match, highlight)\n .replace(/<\\/mark>(\\s+)]*>/img, \"\\$1\")\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search query clause\n */\nexport interface SearchQueryClause {\n presence: lunr.Query.presence /* Clause presence */\n term: string /* Clause term */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Search query terms\n */\nexport type SearchQueryTerms = Record\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Parse a search query for analysis\n *\n * @param value - Query value\n *\n * @return Search query clauses\n */\nexport function parseSearchQuery(\n value: string\n): SearchQueryClause[] {\n const query = new (lunr as any).Query([\"title\", \"text\"])\n const parser = new (lunr as any).QueryParser(value, query)\n\n /* Parse and return query clauses */\n parser.parse()\n return query.clauses\n}\n\n/**\n * Analyze the search query clauses in regard to the search terms found\n *\n * @param query - Search query clauses\n * @param terms - Search terms\n *\n * @return Search query terms\n */\nexport function getSearchQueryTerms(\n query: SearchQueryClause[], terms: string[]\n): SearchQueryTerms {\n const clauses = new Set(query)\n\n /* Match query clauses against terms */\n const result: SearchQueryTerms = {}\n for (let t = 0; t < terms.length; t++)\n for (const clause of clauses)\n if (terms[t].startsWith(clause.term)) {\n result[clause.term] = true\n clauses.delete(clause)\n }\n\n /* Annotate unmatched query clauses */\n for (const clause of clauses)\n result[clause.term] = false\n\n /* Return query terms */\n return result\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"lunr\"\n\nimport { Search, SearchIndexConfig } from \"../../_\"\nimport {\n SearchMessage,\n SearchMessageType\n} from \"../message\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Add support for usage with `iframe-worker` polyfill\n *\n * While `importScripts` is synchronous when executed inside of a web worker,\n * it's not possible to provide a synchronous polyfilled implementation. The\n * cool thing is that awaiting a non-Promise is a noop, so extending the type\n * definition to return a `Promise` shouldn't break anything.\n *\n * @see https://bit.ly/2PjDnXi - GitHub comment\n */\ndeclare global {\n function importScripts(...urls: string[]): Promise | void\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Search index\n */\nlet index: Search\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch (= import) multi-language support through `lunr-languages`\n *\n * This function will automatically import the stemmers necessary to process\n * the languages which were given through the search index configuration.\n *\n * If the worker runs inside of an `iframe` (when using `iframe-worker` as\n * a shim), the base URL for the stemmers to be loaded must be determined by\n * searching for the first `script` element with a `src` attribute, which will\n * contain the contents of this script.\n *\n * @param config - Search index configuration\n *\n * @return Promise resolving with no result\n */\nasync function setupSearchLanguages(\n config: SearchIndexConfig\n): Promise {\n let base = \"../lunr\"\n\n /* Detect `iframe-worker` and fix base URL */\n if (typeof parent !== \"undefined\" && \"IFrameWorker\" in parent) {\n const worker = document.querySelector(\"script[src]\")!\n const [path] = worker.src.split(\"/worker\")\n\n /* Prefix base with path */\n base = base.replace(\"..\", path)\n }\n\n /* Add scripts for languages */\n const scripts = []\n for (const lang of config.lang) {\n if (lang === \"ja\") scripts.push(`${base}/tinyseg.min.js`)\n if (lang !== \"en\") scripts.push(`${base}/min/lunr.${lang}.min.js`)\n }\n\n /* Add multi-language support */\n if (config.lang.length > 1)\n scripts.push(`${base}/min/lunr.multi.min.js`)\n\n /* Load scripts synchronously */\n if (scripts.length)\n await importScripts(\n `${base}/min/lunr.stemmer.support.min.js`,\n ...scripts\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Message handler\n *\n * @param message - Source message\n *\n * @return Target message\n */\nexport async function handler(\n message: SearchMessage\n): Promise {\n switch (message.type) {\n\n /* Search setup message */\n case SearchMessageType.SETUP:\n await setupSearchLanguages(message.data.config)\n index = new Search(message.data)\n return {\n type: SearchMessageType.READY\n }\n\n /* Search query message */\n case SearchMessageType.QUERY:\n return {\n type: SearchMessageType.RESULT,\n data: index ? index.search(message.data) : []\n }\n\n /* All other messages */\n default:\n throw new TypeError(\"Invalid message type\")\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Worker\n * ------------------------------------------------------------------------- */\n\naddEventListener(\"message\", async ev => {\n postMessage(await handler(ev.data))\n})\n"],"sourceRoot":""} \ No newline at end of file diff --git a/public/assets/stylesheets/main.15aa0b43.min.css b/public/assets/stylesheets/main.15aa0b43.min.css new file mode 100644 index 0000000..97e31c1 --- /dev/null +++ b/public/assets/stylesheets/main.15aa0b43.min.css @@ -0,0 +1,3 @@ +html{box-sizing:border-box;-webkit-text-size-adjust:none;-moz-text-size-adjust:none;-ms-text-size-adjust:none;text-size-adjust:none}*,*::before,*::after{box-sizing:inherit}body{margin:0}a,button,label,input{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{display:block;box-sizing:content-box;height:.05rem;padding:0;overflow:visible;border:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:separate;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{margin:0;padding:0;font-size:inherit;background:transparent;border:0}input{border:0;outline:none}:root{--md-default-fg-color: hsla(0, 0%, 0%, 0.87);--md-default-fg-color--light: hsla(0, 0%, 0%, 0.54);--md-default-fg-color--lighter: hsla(0, 0%, 0%, 0.32);--md-default-fg-color--lightest: hsla(0, 0%, 0%, 0.07);--md-default-bg-color: hsla(0, 0%, 100%, 1);--md-default-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-default-bg-color--lighter: hsla(0, 0%, 100%, 0.3);--md-default-bg-color--lightest: hsla(0, 0%, 100%, 0.12);--md-primary-fg-color: hsla(231, 48%, 48%, 1);--md-primary-fg-color--light: hsla(231, 44%, 56%, 1);--md-primary-fg-color--dark: hsla(232, 54%, 41%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-accent-fg-color: hsla(231, 99%, 66%, 1);--md-accent-fg-color--transparent: hsla(231, 99%, 66%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}:root>*{--md-code-fg-color: hsla(200, 18%, 26%, 1);--md-code-bg-color: hsla(0, 0%, 96%, 1);--md-code-hl-color: hsla(60, 100%, 50%, 0.5);--md-code-hl-number-color: hsla(0, 67%, 50%, 1);--md-code-hl-special-color: hsla(340, 83%, 47%, 1);--md-code-hl-function-color: hsla(291, 45%, 50%, 1);--md-code-hl-constant-color: hsla(250, 63%, 60%, 1);--md-code-hl-keyword-color: hsla(219, 54%, 51%, 1);--md-code-hl-string-color: hsla(150, 63%, 30%, 1);--md-code-hl-name-color: var(--md-code-fg-color);--md-code-hl-operator-color: var(--md-default-fg-color--light);--md-code-hl-punctuation-color: var(--md-default-fg-color--light);--md-code-hl-comment-color: var(--md-default-fg-color--light);--md-code-hl-generic-color: var(--md-default-fg-color--light);--md-code-hl-variable-color: var(--md-default-fg-color--light);--md-typeset-color: var(--md-default-fg-color);--md-typeset-a-color: var(--md-primary-fg-color);--md-typeset-mark-color: hsla(60, 100%, 50%, 0.5);--md-typeset-del-color: hsla(6, 90%, 60%, 0.15);--md-typeset-ins-color: hsla(150, 90%, 44%, 0.15);--md-typeset-kbd-color: hsla(0, 0%, 98%, 1);--md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1);--md-typeset-kbd-border-color: hsla(0, 0%, 72%, 1);--md-admonition-fg-color: var(--md-default-fg-color);--md-admonition-bg-color: var(--md-default-bg-color);--md-footer-fg-color: hsla(0, 0%, 100%, 1);--md-footer-fg-color--light: hsla(0, 0%, 100%, 0.7);--md-footer-fg-color--lighter: hsla(0, 0%, 100%, 0.3);--md-footer-bg-color: hsla(0, 0%, 0%, 0.87);--md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.32)}.md-icon svg{display:block;width:1.2rem;height:1.2rem;fill:currentColor}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body,input{color:var(--md-typeset-color);font-feature-settings:"kern","liga";font-family:-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif}code,pre,kbd{color:var(--md-typeset-color);font-feature-settings:"kern";font-family:SFMono-Regular,Consolas,Menlo,monospace}:root{--md-typeset-table--ascending: url("data:image/svg+xml;charset=utf-8,");--md-typeset-table--descending: url("data:image/svg+xml;charset=utf-8,")}.md-typeset{font-size:.8rem;line-height:1.6;-webkit-print-color-adjust:exact;color-adjust:exact}@media print{.md-typeset{font-size:.68rem}}.md-typeset p,.md-typeset ul,.md-typeset ol,.md-typeset dl,.md-typeset blockquote{margin:1em 0}.md-typeset h1{margin:0 0 1.25em;color:var(--md-default-fg-color--light);font-weight:300;font-size:2em;line-height:1.3;letter-spacing:-0.01em}.md-typeset h2{margin:1.6em 0 .64em;font-weight:300;font-size:1.5625em;line-height:1.4;letter-spacing:-0.01em}.md-typeset h3{margin:1.6em 0 .8em;font-weight:400;font-size:1.25em;line-height:1.5;letter-spacing:-0.01em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{margin:1em 0;font-weight:700;letter-spacing:-0.01em}.md-typeset h5,.md-typeset h6{margin:1.25em 0;color:var(--md-default-fg-color--light);font-weight:700;font-size:.8em;letter-spacing:-0.01em}.md-typeset h5{text-transform:uppercase}.md-typeset hr{margin:1.5em 0;border-bottom:.05rem solid var(--md-default-fg-color--lightest)}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a::before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset code,.md-typeset pre,.md-typeset kbd{color:var(--md-code-fg-color);direction:ltr}@media print{.md-typeset code,.md-typeset pre,.md-typeset kbd{white-space:pre-wrap}}.md-typeset code{padding:0 .2941176471em;font-size:.85em;word-break:break-word;background-color:var(--md-code-bg-color);border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset code:not(.focus-visible){outline:none;-webkit-tap-highlight-color:transparent}.md-typeset h1 code,.md-typeset h2 code,.md-typeset h3 code,.md-typeset h4 code,.md-typeset h5 code,.md-typeset h6 code{margin:initial;padding:initial;background-color:transparent;box-shadow:none}.md-typeset a>code{color:currentColor}.md-typeset pre{position:relative;margin:1em 0;line-height:1.4}.md-typeset pre>code{display:block;margin:0;padding:.7720588235em 1.1764705882em;overflow:auto;word-break:normal;box-shadow:none;-webkit-box-decoration-break:slice;box-decoration-break:slice;touch-action:auto;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-typeset pre>code::-webkit-scrollbar{width:.2rem;height:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width: 44.9375em){.md-typeset>pre{margin:1em -0.8rem}.md-typeset>pre code{border-radius:0}}.md-typeset kbd{display:inline-block;padding:0 .6666666667em;color:var(--md-default-fg-color);font-size:.75em;vertical-align:text-top;word-break:break-word;background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -0.1rem .2rem var(--md-typeset-kbd-accent-color) inset}.md-typeset mark{color:inherit;word-break:break-word;background-color:var(--md-typeset-mark-color);-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset abbr{text-decoration:none;border-bottom:.05rem dotted var(--md-default-fg-color--light);cursor:help}@media(hover: none){.md-typeset abbr{position:relative}.md-typeset abbr[title]:focus::after,.md-typeset abbr[title]:hover::after{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);position:absolute;left:0;display:inline-block;width:auto;min-width:-webkit-max-content;min-width:-moz-max-content;min-width:max-content;max-width:80%;margin-top:2em;padding:.2rem .3rem;color:var(--md-default-bg-color);font-size:.7rem;background-color:var(--md-default-fg-color);border-radius:.1rem;content:attr(title)}}.md-typeset small{opacity:.75}.md-typeset sup,.md-typeset sub{margin-left:.078125em}[dir=rtl] .md-typeset sup,[dir=rtl] .md-typeset sub{margin-right:.078125em;margin-left:initial}.md-typeset blockquote{padding-left:.6rem;color:var(--md-default-fg-color--light);border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{padding-right:.6rem;padding-left:initial;border-right:.2rem solid var(--md-default-fg-color--lighter);border-left:initial}.md-typeset ul{list-style-type:disc}.md-typeset ul,.md-typeset ol{margin-left:.625em;padding:0}[dir=rtl] .md-typeset ul,[dir=rtl] .md-typeset ol{margin-right:.625em;margin-left:initial}.md-typeset ul ol,.md-typeset ol ol{list-style-type:lower-alpha}.md-typeset ul ol ol,.md-typeset ol ol ol{list-style-type:lower-roman}.md-typeset ul li,.md-typeset ol li{margin-bottom:.5em;margin-left:1.25em}[dir=rtl] .md-typeset ul li,[dir=rtl] .md-typeset ol li{margin-right:1.25em;margin-left:initial}.md-typeset ul li p,.md-typeset ul li blockquote,.md-typeset ol li p,.md-typeset ol li blockquote{margin:.5em 0}.md-typeset ul li:last-child,.md-typeset ol li:last-child{margin-bottom:0}.md-typeset ul li ul,.md-typeset ul li ol,.md-typeset ol li ul,.md-typeset ol li ol{margin:.5em 0 .5em .625em}[dir=rtl] .md-typeset ul li ul,[dir=rtl] .md-typeset ul li ol,[dir=rtl] .md-typeset ol li ul,[dir=rtl] .md-typeset ol li ol{margin-right:.625em;margin-left:initial}.md-typeset dd{margin:1em 0 1.5em 1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em;margin-left:initial}.md-typeset img,.md-typeset svg{max-width:100%;height:auto}.md-typeset img[align=left],.md-typeset svg[align=left]{margin:1em;margin-left:0}.md-typeset img[align=right],.md-typeset svg[align=right]{margin:1em;margin-right:0}.md-typeset img[align]:only-child,.md-typeset svg[align]:only-child{margin-top:0}.md-typeset figure{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;max-width:100%;margin:0 auto;text-align:center}.md-typeset figure img{display:block}.md-typeset figcaption{max-width:24rem;margin:1em auto 2em;font-style:italic}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){display:inline-block;max-width:100%;overflow:auto;font-size:.64rem;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .05rem rgba(0,0,0,.1);touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) th>*:first-child,.md-typeset table:not([class]) td>*:first-child{margin-top:0}.md-typeset table:not([class]) th>*:last-child,.md-typeset table:not([class]) td>*:last-child{margin-bottom:0}.md-typeset table:not([class]) th:not([align]),.md-typeset table:not([class]) td:not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) th:not([align]),[dir=rtl] .md-typeset table:not([class]) td:not([align]){text-align:right}.md-typeset table:not([class]) th{min-width:5rem;padding:.9375em 1.25em;color:var(--md-default-bg-color);vertical-align:top;background-color:var(--md-default-fg-color--light)}.md-typeset table:not([class]) th a{color:inherit}.md-typeset table:not([class]) td{padding:.9375em 1.25em;vertical-align:top;border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-typeset table:not([class]) tr{transition:background-color 125ms}.md-typeset table:not([class]) tr:hover{background-color:rgba(0,0,0,.035);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) tr:first-child td{border-top:0}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}.md-typeset table th[role=columnheader]::after{display:inline-block;width:1.2em;height:1.2em;margin-left:.5em;vertical-align:sub;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-typeset table th[role=columnheader][aria-sort=ascending]::after{background-color:currentColor;-webkit-mask-image:var(--md-typeset-table--ascending);mask-image:var(--md-typeset-table--ascending)}.md-typeset table th[role=columnheader][aria-sort=descending]::after{background-color:currentColor;-webkit-mask-image:var(--md-typeset-table--descending);mask-image:var(--md-typeset-table--descending)}.md-typeset__scrollwrap{margin:1em -0.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;width:100%;margin:0;overflow:hidden}html{height:100%;overflow-x:hidden;font-size:125%}@media screen and (min-width: 100em){html{font-size:137.5%}}@media screen and (min-width: 125em){html{font-size:150%}}body{position:relative;display:flex;flex-direction:column;width:100%;min-height:100%;font-size:.5rem;background-color:var(--md-default-bg-color)}@media print{body{display:block}}@media screen and (max-width: 59.9375em){body[data-md-state=lock]{position:fixed}}.md-grid{max-width:61rem;margin-right:auto;margin-left:auto}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.md-toggle{display:none}.md-skip{position:fixed;z-index:-1;margin:.5rem;padding:.3rem .5rem;color:var(--md-default-bg-color);font-size:.64rem;background-color:var(--md-default-fg-color);border-radius:.1rem;transform:translateY(0.4rem);opacity:0}.md-skip:focus{z-index:10;transform:translateY(0);opacity:1;transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),opacity 175ms 75ms}@page{margin:25mm}.md-announce{overflow:auto;background-color:var(--md-footer-bg-color)}@media print{.md-announce{display:none}}.md-announce__inner{margin:.6rem auto;padding:0 .8rem;color:var(--md-footer-fg-color);font-size:.7rem}.md-typeset .md-button{display:inline-block;padding:.625em 2em;color:var(--md-primary-fg-color);font-weight:700;border:.1rem solid currentColor;border-radius:.1rem;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color)}.md-typeset .md-button:focus,.md-typeset .md-button:hover{color:var(--md-accent-bg-color);background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color)}:root{--md-clipboard-icon: url("data:image/svg+xml;charset=utf-8,")}.md-clipboard{position:absolute;top:.5em;right:.5em;z-index:1;width:1.5em;height:1.5em;color:var(--md-default-fg-color--lightest);border-radius:.1rem;cursor:pointer;transition:color 250ms}@media print{.md-clipboard{display:none}}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:focus,.md-clipboard:hover{color:var(--md-accent-fg-color)}.md-clipboard::after{display:block;width:1.125em;height:1.125em;margin:0 auto;background-color:currentColor;-webkit-mask-image:var(--md-clipboard-icon);mask-image:var(--md-clipboard-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-content{flex-grow:1;overflow:hidden;scroll-padding-top:51.2rem}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width: 76.25em){.md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem;margin-left:.8rem}.md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-right:.8rem;margin-left:1.2rem}}.md-content__inner::before{display:block;height:.4rem;content:""}.md-content__inner>:last-child{margin-bottom:0}.md-content__button{float:right;margin:.4rem 0;margin-left:.4rem;padding:0}@media print{.md-content__button{display:none}}[dir=rtl] .md-content__button{float:left;margin-right:.4rem;margin-left:initial}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}.md-dialog{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);position:fixed;right:.8rem;bottom:.8rem;left:initial;z-index:2;display:block;min-width:11.1rem;padding:.4rem .6rem;color:var(--md-default-bg-color);font-size:.7rem;background-color:var(--md-default-fg-color);border:none;border-radius:.1rem;transform:translateY(100%);opacity:0;transition:transform 0ms 400ms,opacity 400ms}@media print{.md-dialog{display:none}}[dir=rtl] .md-dialog{right:initial;left:.8rem}.md-dialog[data-md-state=open]{transform:translateY(0);opacity:1;transition:transform 400ms cubic-bezier(0.075, 0.85, 0.175, 1),opacity 400ms}.md-header{position:-webkit-sticky;position:sticky;top:0;right:0;left:0;z-index:2;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem rgba(0,0,0,0),0 .2rem .4rem rgba(0,0,0,0);transition:color 250ms,background-color 250ms}@media print{.md-header{display:none}}.md-header[data-md-state=shadow]{box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2);transition:transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1),color 250ms,background-color 250ms,box-shadow 250ms}.md-header[data-md-state=hidden]{transform:translateY(-100%);transition:transform 250ms cubic-bezier(0.8, 0, 0.6, 1),color 250ms,background-color 250ms,box-shadow 250ms}.md-header-nav{display:flex;align-items:center;padding:0 .2rem}.md-header-nav__button{position:relative;z-index:1;display:inline-block;margin:.2rem;padding:.4rem;color:currentColor;vertical-align:middle;cursor:pointer;transition:opacity 250ms}.md-header-nav__button:focus,.md-header-nav__button:hover{opacity:.7}.md-header-nav__button:not(.focus-visible){outline:none}.md-header-nav__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width: 76.1875em){.md-header-nav__button.md-logo{display:none}}.md-header-nav__button.md-logo img,.md-header-nav__button.md-logo svg{display:block;width:1.2rem;height:1.2rem;fill:currentColor}@media screen and (min-width: 60em){.md-header-nav__button[for=__search]{display:none}}.no-js .md-header-nav__button[for=__search]{display:none}[dir=rtl] .md-header-nav__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width: 76.25em){.md-header-nav__button[for=__drawer]{display:none}}.md-header-nav__topic{position:absolute;display:flex;max-width:100%;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms}.md-header-nav__topic+.md-header-nav__topic{z-index:-1;transform:translateX(1.25rem);opacity:0;transition:transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),opacity 150ms;pointer-events:none}[dir=rtl] .md-header-nav__topic+.md-header-nav__topic{transform:translateX(-1.25rem)}.md-header-nav__title{flex-grow:1;height:2.4rem;margin-right:.4rem;margin-left:1rem;font-size:.9rem;line-height:2.4rem}.md-header-nav__title[data-md-state=active] .md-header-nav__topic{z-index:-1;transform:translateX(-1.25rem);opacity:0;transition:transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),opacity 150ms;pointer-events:none}[dir=rtl] .md-header-nav__title[data-md-state=active] .md-header-nav__topic{transform:translateX(1.25rem)}.md-header-nav__title[data-md-state=active] .md-header-nav__topic+.md-header-nav__topic{z-index:0;transform:translateX(0);opacity:1;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms;pointer-events:initial}.md-header-nav__title>.md-header-nav__ellipsis{position:relative;width:100%;height:100%}.md-header-nav__source{display:none}@media screen and (min-width: 60em){.md-header-nav__source{display:block;width:11.7rem;max-width:11.7rem;margin-left:1rem}[dir=rtl] .md-header-nav__source{margin-right:1rem;margin-left:initial}}@media screen and (min-width: 76.25em){.md-header-nav__source{margin-left:1.4rem}[dir=rtl] .md-header-nav__source{margin-right:1.4rem}}.md-footer{color:var(--md-footer-fg-color);background-color:var(--md-footer-bg-color)}@media print{.md-footer{display:none}}.md-footer-nav__inner{padding:.2rem;overflow:auto}.md-footer-nav__link{display:flex;padding-top:1.4rem;padding-bottom:.4rem;transition:opacity 250ms}@media screen and (min-width: 45em){.md-footer-nav__link{width:50%}}.md-footer-nav__link:focus,.md-footer-nav__link:hover{opacity:.7}.md-footer-nav__link--prev{float:left}@media screen and (max-width: 44.9375em){.md-footer-nav__link--prev{width:25%}.md-footer-nav__link--prev .md-footer-nav__title{display:none}}[dir=rtl] .md-footer-nav__link--prev{float:right}[dir=rtl] .md-footer-nav__link--prev svg{transform:scaleX(-1)}.md-footer-nav__link--next{float:right;text-align:right}@media screen and (max-width: 44.9375em){.md-footer-nav__link--next{width:75%}}[dir=rtl] .md-footer-nav__link--next{float:left;text-align:left}[dir=rtl] .md-footer-nav__link--next svg{transform:scaleX(-1)}.md-footer-nav__title{position:relative;flex-grow:1;max-width:calc(100% - 2.4rem);padding:0 1rem;font-size:.9rem;line-height:2.4rem}.md-footer-nav__button{margin:.2rem;padding:.4rem}.md-footer-nav__direction{position:absolute;right:0;left:0;margin-top:-1rem;padding:0 1rem;font-size:.64rem;opacity:.7}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:focus,html .md-footer-meta.md-typeset a:hover{color:var(--md-footer-fg-color)}.md-footer-copyright{width:100%;margin:auto .6rem;padding:.4rem 0;color:var(--md-footer-fg-color--lighter);font-size:.64rem}@media screen and (min-width: 45em){.md-footer-copyright{width:auto}}.md-footer-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-footer-social{margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width: 45em){.md-footer-social{padding:.6rem 0}}.md-footer-social__link{display:inline-block;width:1.6rem;height:1.6rem;text-align:center}.md-footer-social__link::before{line-height:1.9}.md-footer-social__link svg{max-height:.8rem;vertical-align:-25%;fill:currentColor}:root{--md-nav-icon--prev: url("data:image/svg+xml;charset=utf-8,");--md-nav-icon--next: url("data:image/svg+xml;charset=utf-8,");--md-toc-icon: url("data:image/svg+xml;charset=utf-8,")}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{display:block;padding:0 .6rem;overflow:hidden;font-weight:700;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{width:auto;height:100%}.md-nav__title .md-nav__button.md-logo img,.md-nav__title .md-nav__button.md-logo svg{display:block;width:2.4rem;height:2.4rem;fill:currentColor}.md-nav__list{margin:0;padding:0;list-style:none}.md-nav__item{padding:0 .6rem}.md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-right:.6rem;padding-left:0}.md-nav__link{display:block;margin-top:.625em;overflow:hidden;text-overflow:ellipsis;cursor:pointer;transition:color 125ms;scroll-snap-align:start}.md-nav__link[data-md-state=blur]{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active{color:var(--md-typeset-a-color)}.md-nav__item--nested>.md-nav__link{color:inherit}.md-nav__link:focus,.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon::after{display:block;width:100%;height:100%;-webkit-mask-image:var(--md-toc-icon);mask-image:var(--md-toc-icon);background-color:currentColor}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__source{display:none}@media screen and (max-width: 76.1875em){.md-nav--primary,.md-nav--primary .md-nav{position:absolute;top:0;right:0;left:0;z-index:1;display:flex;flex-direction:column;height:100%;background-color:var(--md-default-bg-color)}.md-nav--primary .md-nav__title,.md-nav--primary .md-nav__item{font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{position:relative;height:5.6rem;padding:3rem .8rem .2rem;color:var(--md-default-fg-color--light);font-weight:400;line-height:2.4rem;white-space:nowrap;background-color:var(--md-default-fg-color--lightest);cursor:pointer}.md-nav--primary .md-nav__title .md-nav__icon{position:absolute;top:.4rem;left:.4rem;display:block;width:1.2rem;height:1.2rem;margin:.2rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem;left:initial}.md-nav--primary .md-nav__title .md-nav__icon::after{display:block;width:100%;height:100%;background-color:currentColor;-webkit-mask-image:var(--md-nav-icon--prev);mask-image:var(--md-nav-icon--prev);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-nav--primary .md-nav__title~.md-nav__list{overflow-y:auto;background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;-webkit-scroll-snap-type:y mandatory;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color)}.md-nav--primary .md-nav__title .md-logo{position:absolute;top:.2rem;left:.2rem;display:block;margin:.2rem;padding:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-logo{right:.2rem;left:initial}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{padding:0;border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:2.4rem}[dir=rtl] .md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:.8rem;padding-left:2.4rem}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:focus,.md-nav--primary .md-nav__item--active>.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{position:relative;margin-top:0;padding:.6rem .8rem}.md-nav--primary .md-nav__link .md-nav__icon{position:absolute;top:50%;right:.6rem;width:1.2rem;height:1.2rem;margin-top:-0.6rem;color:inherit;font-size:1.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{right:initial;left:.6rem}.md-nav--primary .md-nav__link .md-nav__icon::after{display:block;width:100%;height:100%;background-color:currentColor;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-nav--primary .md-nav__icon::after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav__link{position:static}.md-nav--primary .md-nav--secondary .md-nav{position:static;background-color:transparent}.md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem;padding-left:initial}.md-nav--secondary{background-color:transparent}.md-nav__toggle~.md-nav{display:flex;transform:translateX(100%);opacity:0;transition:transform 250ms cubic-bezier(0.8, 0, 0.6, 1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{transform:translateX(0);opacity:1;transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{-webkit-backface-visibility:hidden;backface-visibility:hidden}}@media screen and (max-width: 59.9375em){.md-nav--primary .md-nav__link[for=__toc]{display:block;padding-right:2.4rem}[dir=rtl] .md-nav--primary .md-nav__link[for=__toc]{padding-right:.8rem;padding-left:2.4rem}.md-nav--primary .md-nav__link[for=__toc] .md-icon::after{content:""}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{display:block;padding:0 .2rem;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color--dark)}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-nav--integrated .md-nav__link[for=__toc]{display:block;padding-right:2.4rem;scroll-snap-align:initial}[dir=rtl] .md-nav--integrated .md-nav__link[for=__toc]{padding-right:.8rem;padding-left:2.4rem}.md-nav--integrated .md-nav__link[for=__toc] .md-icon::after{content:""}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width: 60em){.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}}@media screen and (min-width: 76.25em){.md-nav{transition:max-height 250ms cubic-bezier(0.86, 0, 0.07, 1)}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon{display:none}.md-nav__toggle~.md-nav{display:none}.md-nav__toggle:checked~.md-nav,.md-nav__toggle:indeterminate~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{display:none}.md-nav__item--section>.md-nav{display:block}.md-nav__item--section>.md-nav>.md-nav__title{display:block;padding:0;pointer-events:none;scroll-snap-align:start}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{float:right;width:.9rem;height:.9rem;transition:transform 250ms}[dir=rtl] .md-nav__icon{float:left;transform:rotate(180deg)}.md-nav__icon::after{display:inline-block;width:100%;height:100%;vertical-align:-0.1rem;background-color:currentColor;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon,.md-nav__item--nested .md-nav__toggle:indeterminate~.md-nav__link .md-nav__icon{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item--nested,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block;padding:0}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav>.md-nav__title{display:block;padding:0 .6rem;pointer-events:none;scroll-snap-align:start}.md-nav--lifted>.md-nav__list>.md-nav__item>.md-nav__item{padding-right:.6rem}.md-nav--lifted .md-nav[data-md-level="1"]{display:block}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:block;margin-bottom:1.25em;border-left:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav>.md-nav__title{display:none}}:root{--md-search-result-icon: url("data:image/svg+xml;charset=utf-8,")}.md-search{position:relative}@media screen and (min-width: 60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{z-index:1;opacity:0}@media screen and (max-width: 59.9375em){.md-search__overlay{position:absolute;top:.2rem;left:-2.2rem;width:2rem;height:2rem;overflow:hidden;background-color:var(--md-default-bg-color);border-radius:1rem;transform-origin:center;transition:transform 300ms 100ms,opacity 200ms 200ms;pointer-events:none}[dir=rtl] .md-search__overlay{right:-2.2rem;left:initial}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform 400ms,opacity 100ms}}@media screen and (min-width: 60em){.md-search__overlay{position:fixed;top:0;left:0;width:0;height:0;background-color:rgba(0,0,0,.54);cursor:pointer;transition:width 0ms 250ms,height 0ms 250ms,opacity 250ms}[dir=rtl] .md-search__overlay{right:0;left:initial}[data-md-toggle=search]:checked~.md-header .md-search__overlay{width:100%;height:100%;opacity:1;transition:width 0ms,height 0ms,opacity 250ms}}@media screen and (max-width: 29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width: 30em)and (max-width: 44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width: 45em)and (max-width: 59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{-webkit-backface-visibility:hidden;backface-visibility:hidden}@media screen and (max-width: 59.9375em){.md-search__inner{position:fixed;top:0;left:100%;z-index:2;width:100%;height:100%;transform:translateX(5%);opacity:0;transition:right 0ms 300ms,left 0ms 300ms,transform 150ms 150ms cubic-bezier(0.4, 0, 0.2, 1),opacity 150ms 150ms}[data-md-toggle=search]:checked~.md-header .md-search__inner{left:0;transform:translateX(0);opacity:1;transition:right 0ms 0ms,left 0ms 0ms,transform 150ms 150ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms 150ms}[dir=rtl] [data-md-toggle=search]:checked~.md-header .md-search__inner{right:0;left:initial}html [dir=rtl] .md-search__inner{right:100%;left:initial;transform:translateX(-5%)}}@media screen and (min-width: 60em){.md-search__inner{position:relative;float:right;width:11.7rem;padding:.1rem 0;transition:width 250ms cubic-bezier(0.1, 0.7, 0.1, 1)}[dir=rtl] .md-search__inner{float:left}}@media screen and (min-width: 60em)and (max-width: 76.1875em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width: 76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{position:relative}@media screen and (min-width: 60em){.md-search__form{border-radius:.1rem}}.md-search__input{position:relative;z-index:2;padding:0 2.2rem 0 3.6rem;text-overflow:ellipsis;background-color:var(--md-default-bg-color);transition:color 250ms,background-color 250ms}[dir=rtl] .md-search__input{padding:0 3.6rem 0 2.2rem}.md-search__input::-webkit-input-placeholder{-webkit-transition:color 250ms;transition:color 250ms}.md-search__input::-moz-placeholder{-moz-transition:color 250ms;transition:color 250ms}.md-search__input::-ms-input-placeholder{-ms-transition:color 250ms;transition:color 250ms}.md-search__input::placeholder{transition:color 250ms}.md-search__input::-webkit-input-placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-moz-placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}.md-search__input~.md-search__icon,.md-search__input::placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width: 59.9375em){.md-search__input{width:100%;height:2.4rem;font-size:.9rem}}@media screen and (min-width: 60em){.md-search__input{width:100%;height:1.8rem;padding-left:2.2rem;color:inherit;font-size:.8rem;background-color:rgba(0,0,0,.26);border-radius:.1rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}.md-search__input::-webkit-input-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::-moz-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::-ms-input-placeholder{color:var(--md-primary-bg-color--light)}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input:hover{background-color:rgba(255,255,255,.12)}[data-md-toggle=search]:checked~.md-header .md-search__input{color:var(--md-default-fg-color);text-overflow:clip;background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0}[data-md-toggle=search]:checked~.md-header .md-search__input::-webkit-input-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::-moz-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::-ms-input-placeholder{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon,[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:var(--md-default-fg-color--light)}}.md-search__icon{position:absolute;z-index:2;width:1.2rem;height:1.2rem;cursor:pointer;transition:color 250ms,opacity 250ms}.md-search__icon:hover{opacity:.7}.md-search__icon[for=__search]{top:.3rem;left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem;left:initial}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width: 59.9375em){.md-search__icon[for=__search]{top:.6rem;left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem;left:initial}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width: 60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}.md-search__icon[type=reset]{top:.3rem;right:.5rem;transform:scale(0.75);opacity:0;transition:transform 150ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms;pointer-events:none}[dir=rtl] .md-search__icon[type=reset]{right:initial;left:.5rem}@media screen and (max-width: 59.9375em){.md-search__icon[type=reset]{top:.6rem;right:.8rem}[dir=rtl] .md-search__icon[type=reset]{right:initial;left:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]{transform:scale(1);opacity:1;pointer-events:initial}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]:hover{opacity:.7}.md-search__output{position:absolute;z-index:1;width:100%;overflow:hidden;border-radius:0 0 .1rem .1rem}@media screen and (max-width: 59.9375em){.md-search__output{top:2.4rem;bottom:0}}@media screen and (min-width: 60em){.md-search__output{top:1.9rem;opacity:0;transition:opacity 400ms}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12),0 3px 5px -1px rgba(0,0,0,.4);opacity:1}}.md-search__scrollwrap{height:100%;overflow-y:auto;background-color:var(--md-default-bg-color);-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-scroll-snap-type:y mandatory;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;touch-action:pan-y}@media(-webkit-max-device-pixel-ratio: 1), (max-resolution: 1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width: 76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width: 60em){.md-search__scrollwrap{max-height:0;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-search__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{padding:0 .8rem;color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;background-color:var(--md-default-fg-color--lightest);scroll-snap-align:start}@media screen and (min-width: 60em){.md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem;padding-left:initial}}.md-search-result__list{margin:0;padding:0;list-style:none}.md-search-result__item{box-shadow:0 -0.05rem 0 var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;transition:background-color 250ms;scroll-snap-align:start}.md-search-result__link:focus,.md-search-result__link:hover{background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more summary{display:block;padding:.75em .8rem;color:var(--md-typeset-a-color);font-size:.64rem;outline:0;cursor:pointer;transition:color 250ms,background-color 250ms;scroll-snap-align:start}@media screen and (min-width: 60em){.md-search-result__more summary{padding-left:2.2rem}[dir=rtl] .md-search-result__more summary{padding-right:2.2rem;padding-left:.8rem}}.md-search-result__more summary:focus,.md-search-result__more summary:hover{color:var(--md-accent-fg-color);background-color:var(--md-accent-fg-color--transparent)}.md-search-result__more summary::-webkit-details-marker{display:none}.md-search-result__more summary~*>*{opacity:.65}.md-search-result__article{position:relative;padding:0 .8rem;overflow:hidden}@media screen and (min-width: 60em){.md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem;padding-left:.8rem}}.md-search-result__article--document .md-search-result__title{margin:.55rem 0;font-weight:400;font-size:.8rem;line-height:1.4}.md-search-result__icon{position:absolute;left:0;width:1.2rem;height:1.2rem;margin:.5rem;color:var(--md-default-fg-color--light)}@media screen and (max-width: 59.9375em){.md-search-result__icon{display:none}}.md-search-result__icon::after{display:inline-block;width:100%;height:100%;background-color:currentColor;-webkit-mask-image:var(--md-search-result-icon);mask-image:var(--md-search-result-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-search-result__icon{right:0;left:initial}[dir=rtl] .md-search-result__icon::after{transform:scaleX(-1)}.md-search-result__title{margin:.5em 0;font-weight:700;font-size:.64rem;line-height:1.6}.md-search-result__teaser{display:-webkit-box;max-height:2rem;margin:.5em 0;overflow:hidden;color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.6;text-overflow:ellipsis;-webkit-box-orient:vertical;-webkit-line-clamp:2}@media screen and (max-width: 44.9375em){.md-search-result__teaser{max-height:3rem;-webkit-line-clamp:3}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-search-result__teaser{max-height:3rem;-webkit-line-clamp:3}}.md-search-result__teaser mark{text-decoration:underline;background-color:transparent}.md-search-result__terms{margin:.5em 0;font-size:.64rem;font-style:italic}.md-search-result mark{color:var(--md-accent-fg-color);background-color:transparent}.md-sidebar{position:-webkit-sticky;position:sticky;top:2.4rem;flex-shrink:0;align-self:flex-start;width:12.1rem;height:0;padding:1.2rem 0}@media print{.md-sidebar{display:none}}@media screen and (max-width: 76.1875em){.md-sidebar--primary{position:fixed;top:0;left:-12.1rem;z-index:3;display:block;width:12.1rem;height:100%;background-color:var(--md-default-bg-color);transform:translateX(0);transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),box-shadow 250ms}[dir=rtl] .md-sidebar--primary{right:-12.1rem;left:initial}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12),0 5px 5px -3px rgba(0,0,0,.4);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{position:absolute;top:0;right:0;bottom:0;left:0;margin:0;-webkit-scroll-snap-type:none;-ms-scroll-snap-type:none;scroll-snap-type:none;overflow:hidden}}@media screen and (min-width: 76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width: 60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{margin:0 .2rem;overflow-y:auto;-webkit-backface-visibility:hidden;backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-sidebar__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width: 76.1875em){.md-overlay{position:fixed;top:0;z-index:3;width:0;height:0;background-color:rgba(0,0,0,.54);opacity:0;transition:width 0ms 250ms,height 0ms 250ms,opacity 250ms}[data-md-toggle=drawer]:checked~.md-overlay{width:100%;height:100%;opacity:1;transition:width 0ms,height 0ms,opacity 250ms}}@-webkit-keyframes md-source__facts--done{0%{height:0}100%{height:.65rem}}@keyframes md-source__facts--done{0%{height:0}100%{height:.65rem}}@-webkit-keyframes md-source__fact--done{0%{transform:translateY(100%);opacity:0}50%{opacity:0}100%{transform:translateY(0%);opacity:1}}@keyframes md-source__fact--done{0%{transform:translateY(100%);opacity:0}50%{opacity:0}100%{transform:translateY(0%);opacity:1}}.md-source{display:block;font-size:.65rem;line-height:1.2;white-space:nowrap;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:opacity 250ms}.md-source:focus,.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;width:2.4rem;height:2.4rem;vertical-align:middle}.md-source__icon svg{margin-top:.6rem;margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem;margin-left:initial}.md-source__icon+.md-source__repository{margin-left:-2rem;padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem;margin-left:initial;padding-right:2rem;padding-left:initial}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);margin-left:.6rem;overflow:hidden;font-weight:700;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{margin:0;padding:0;overflow:hidden;font-weight:700;font-size:.55rem;list-style-type:none;opacity:.75}[data-md-state=done] .md-source__facts{-webkit-animation:md-source__facts--done 250ms ease-in;animation:md-source__facts--done 250ms ease-in}.md-source__fact{float:left}[dir=rtl] .md-source__fact{float:right}[data-md-state=done] .md-source__fact{-webkit-animation:md-source__fact--done 400ms ease-out;animation:md-source__fact--done 400ms ease-out}.md-source__fact::before{margin:0 .1rem;content:"·"}.md-source__fact:first-child::before{display:none}.md-tabs{width:100%;overflow:auto;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);transition:background-color 250ms}@media print{.md-tabs{display:none}}@media screen and (max-width: 76.1875em){.md-tabs{display:none}}.md-tabs[data-md-state=hidden]{pointer-events:none}.md-tabs__list{margin:0;margin-left:.2rem;padding:0;white-space:nowrap;list-style:none;contain:content}[dir=rtl] .md-tabs__list{margin-right:.2rem;margin-left:initial}.md-tabs__item{display:inline-block;height:2.4rem;padding-right:.6rem;padding-left:.6rem}.md-tabs__link{display:block;margin-top:.8rem;font-size:.7rem;-webkit-backface-visibility:hidden;backface-visibility:hidden;opacity:.7;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 250ms}.md-tabs__link--active,.md-tabs__link:focus,.md-tabs__link:hover{color:inherit;opacity:1}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:100ms}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:120ms}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:140ms}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:160ms}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:180ms}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:200ms}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:220ms}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:240ms}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:260ms}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:280ms}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:300ms}.md-tabs[data-md-state=hidden] .md-tabs__link{transform:translateY(50%);opacity:0;transition:transform 0ms 100ms,opacity 100ms}:root{--md-admonition-icon--note: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--abstract: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--info: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--tip: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--success: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--question: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--warning: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--failure: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--danger: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--bug: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--example: url( "data:image/svg+xml;charset=utf-8," );--md-admonition-icon--quote: url( "data:image/svg+xml;charset=utf-8," )}.md-typeset .admonition,.md-typeset details{margin:1.5625em 0;padding:0 .6rem;overflow:hidden;color:var(--md-admonition-fg-color);font-size:.64rem;page-break-inside:avoid;background-color:var(--md-admonition-bg-color);border-left:.2rem solid #448aff;border-radius:.1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 .025rem .05rem rgba(0,0,0,.05)}@media print{.md-typeset .admonition,.md-typeset details{box-shadow:none}}[dir=rtl] .md-typeset .admonition,[dir=rtl] .md-typeset details{border-right:.2rem solid #448aff;border-left:none}.md-typeset .admonition .admonition,.md-typeset details .admonition,.md-typeset .admonition details,.md-typeset details details{margin:1em 0}.md-typeset .admonition .md-typeset__scrollwrap,.md-typeset details .md-typeset__scrollwrap{margin:1em -0.6rem}.md-typeset .admonition .md-typeset__table,.md-typeset details .md-typeset__table{padding:0 .6rem}.md-typeset .admonition>.tabbed-set:only-child,.md-typeset details>.tabbed-set:only-child{margin-top:0}html .md-typeset .admonition>:last-child,html .md-typeset details>:last-child{margin-bottom:.6rem}.md-typeset .admonition-title,.md-typeset summary{position:relative;margin:0 -0.6rem 0 -0.8rem;padding:.4rem .6rem .4rem 2rem;font-weight:700;background-color:rgba(68,138,255,.1);border-left:.2rem solid #448aff}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{margin:0 -0.8rem 0 -0.6rem;padding:.4rem 2rem .4rem .6rem;border-right:.2rem solid #448aff;border-left:none}html .md-typeset .admonition-title:last-child,html .md-typeset summary:last-child{margin-bottom:0}.md-typeset .admonition-title::before,.md-typeset summary::before{position:absolute;left:.6rem;width:1rem;height:1rem;background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-typeset .admonition-title::before,[dir=rtl] .md-typeset summary::before{right:.6rem;left:initial}.md-typeset .admonition-title code,.md-typeset summary code{margin:initial;padding:initial;color:currentColor;background-color:transparent;border-radius:initial;box-shadow:none}.md-typeset .admonition-title+.tabbed-set:last-child,.md-typeset summary+.tabbed-set:last-child{margin-top:0}.md-typeset .admonition.note,.md-typeset details.note{border-color:#448aff}.md-typeset .note>.admonition-title,.md-typeset .note>summary{background-color:rgba(68,138,255,.1);border-color:#448aff}.md-typeset .note>.admonition-title::before,.md-typeset .note>summary::before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.abstract,.md-typeset details.abstract,.md-typeset .admonition.tldr,.md-typeset details.tldr,.md-typeset .admonition.summary,.md-typeset details.summary{border-color:#00b0ff}.md-typeset .abstract>.admonition-title,.md-typeset .abstract>summary,.md-typeset .tldr>.admonition-title,.md-typeset .tldr>summary,.md-typeset .summary>.admonition-title,.md-typeset .summary>summary{background-color:rgba(0,176,255,.1);border-color:#00b0ff}.md-typeset .abstract>.admonition-title::before,.md-typeset .abstract>summary::before,.md-typeset .tldr>.admonition-title::before,.md-typeset .tldr>summary::before,.md-typeset .summary>.admonition-title::before,.md-typeset .summary>summary::before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.info,.md-typeset details.info,.md-typeset .admonition.todo,.md-typeset details.todo{border-color:#00b8d4}.md-typeset .info>.admonition-title,.md-typeset .info>summary,.md-typeset .todo>.admonition-title,.md-typeset .todo>summary{background-color:rgba(0,184,212,.1);border-color:#00b8d4}.md-typeset .info>.admonition-title::before,.md-typeset .info>summary::before,.md-typeset .todo>.admonition-title::before,.md-typeset .todo>summary::before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.tip,.md-typeset details.tip,.md-typeset .admonition.important,.md-typeset details.important,.md-typeset .admonition.hint,.md-typeset details.hint{border-color:#00bfa5}.md-typeset .tip>.admonition-title,.md-typeset .tip>summary,.md-typeset .important>.admonition-title,.md-typeset .important>summary,.md-typeset .hint>.admonition-title,.md-typeset .hint>summary{background-color:rgba(0,191,165,.1);border-color:#00bfa5}.md-typeset .tip>.admonition-title::before,.md-typeset .tip>summary::before,.md-typeset .important>.admonition-title::before,.md-typeset .important>summary::before,.md-typeset .hint>.admonition-title::before,.md-typeset .hint>summary::before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.success,.md-typeset details.success,.md-typeset .admonition.done,.md-typeset details.done,.md-typeset .admonition.check,.md-typeset details.check{border-color:#00c853}.md-typeset .success>.admonition-title,.md-typeset .success>summary,.md-typeset .done>.admonition-title,.md-typeset .done>summary,.md-typeset .check>.admonition-title,.md-typeset .check>summary{background-color:rgba(0,200,83,.1);border-color:#00c853}.md-typeset .success>.admonition-title::before,.md-typeset .success>summary::before,.md-typeset .done>.admonition-title::before,.md-typeset .done>summary::before,.md-typeset .check>.admonition-title::before,.md-typeset .check>summary::before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.question,.md-typeset details.question,.md-typeset .admonition.faq,.md-typeset details.faq,.md-typeset .admonition.help,.md-typeset details.help{border-color:#64dd17}.md-typeset .question>.admonition-title,.md-typeset .question>summary,.md-typeset .faq>.admonition-title,.md-typeset .faq>summary,.md-typeset .help>.admonition-title,.md-typeset .help>summary{background-color:rgba(100,221,23,.1);border-color:#64dd17}.md-typeset .question>.admonition-title::before,.md-typeset .question>summary::before,.md-typeset .faq>.admonition-title::before,.md-typeset .faq>summary::before,.md-typeset .help>.admonition-title::before,.md-typeset .help>summary::before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.warning,.md-typeset details.warning,.md-typeset .admonition.attention,.md-typeset details.attention,.md-typeset .admonition.caution,.md-typeset details.caution{border-color:#ff9100}.md-typeset .warning>.admonition-title,.md-typeset .warning>summary,.md-typeset .attention>.admonition-title,.md-typeset .attention>summary,.md-typeset .caution>.admonition-title,.md-typeset .caution>summary{background-color:rgba(255,145,0,.1);border-color:#ff9100}.md-typeset .warning>.admonition-title::before,.md-typeset .warning>summary::before,.md-typeset .attention>.admonition-title::before,.md-typeset .attention>summary::before,.md-typeset .caution>.admonition-title::before,.md-typeset .caution>summary::before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.failure,.md-typeset details.failure,.md-typeset .admonition.missing,.md-typeset details.missing,.md-typeset .admonition.fail,.md-typeset details.fail{border-color:#ff5252}.md-typeset .failure>.admonition-title,.md-typeset .failure>summary,.md-typeset .missing>.admonition-title,.md-typeset .missing>summary,.md-typeset .fail>.admonition-title,.md-typeset .fail>summary{background-color:rgba(255,82,82,.1);border-color:#ff5252}.md-typeset .failure>.admonition-title::before,.md-typeset .failure>summary::before,.md-typeset .missing>.admonition-title::before,.md-typeset .missing>summary::before,.md-typeset .fail>.admonition-title::before,.md-typeset .fail>summary::before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.danger,.md-typeset details.danger,.md-typeset .admonition.error,.md-typeset details.error{border-color:#ff1744}.md-typeset .danger>.admonition-title,.md-typeset .danger>summary,.md-typeset .error>.admonition-title,.md-typeset .error>summary{background-color:rgba(255,23,68,.1);border-color:#ff1744}.md-typeset .danger>.admonition-title::before,.md-typeset .danger>summary::before,.md-typeset .error>.admonition-title::before,.md-typeset .error>summary::before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.bug,.md-typeset details.bug{border-color:#f50057}.md-typeset .bug>.admonition-title,.md-typeset .bug>summary{background-color:rgba(245,0,87,.1);border-color:#f50057}.md-typeset .bug>.admonition-title::before,.md-typeset .bug>summary::before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.example,.md-typeset details.example{border-color:#651fff}.md-typeset .example>.admonition-title,.md-typeset .example>summary{background-color:rgba(101,31,255,.1);border-color:#651fff}.md-typeset .example>.admonition-title::before,.md-typeset .example>summary::before{background-color:#651fff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.md-typeset .admonition.quote,.md-typeset details.quote,.md-typeset .admonition.cite,.md-typeset details.cite{border-color:#9e9e9e}.md-typeset .quote>.admonition-title,.md-typeset .quote>summary,.md-typeset .cite>.admonition-title,.md-typeset .cite>summary{background-color:rgba(158,158,158,.1);border-color:#9e9e9e}.md-typeset .quote>.admonition-title::before,.md-typeset .quote>summary::before,.md-typeset .cite>.admonition-title::before,.md-typeset .cite>summary::before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}:root{--md-footnotes-icon: url("data:image/svg+xml;charset=utf-8,")}.md-typeset [id^="fnref:"]:target{scroll-margin-top:initial;margin-top:-3.4rem;padding-top:3.4rem}.md-typeset [id^="fn:"]:target{scroll-margin-top:initial;margin-top:-3.45rem;padding-top:3.45rem}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}.md-typeset .footnote ol{margin-left:0}.md-typeset .footnote li{transition:color 125ms}.md-typeset .footnote li:target{color:var(--md-default-fg-color)}.md-typeset .footnote li:hover .footnote-backref,.md-typeset .footnote li:target .footnote-backref{transform:translateX(0);opacity:1}.md-typeset .footnote li>:first-child{margin-top:0}.md-typeset .footnote-backref{display:inline-block;color:var(--md-typeset-a-color);font-size:0;vertical-align:text-bottom;transform:translateX(0.25rem);opacity:0;transition:color 250ms,transform 250ms 250ms,opacity 125ms 250ms}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);transform:translateX(0);opacity:1}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-0.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref::before{display:inline-block;width:.8rem;height:.8rem;background-color:currentColor;-webkit-mask-image:var(--md-footnotes-icon);mask-image:var(--md-footnotes-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-typeset .footnote-backref::before svg{transform:scaleX(-1)}.md-typeset .headerlink{display:inline-block;margin-left:.5rem;color:var(--md-default-fg-color--lighter);opacity:0;transition:color 250ms,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem;margin-left:initial}.md-typeset :hover>.headerlink,.md-typeset :target>.headerlink,.md-typeset .headerlink:focus{opacity:1;transition:color 250ms,opacity 125ms}.md-typeset :target>.headerlink,.md-typeset .headerlink:focus,.md-typeset .headerlink:hover{color:var(--md-accent-fg-color)}.md-typeset :target{scroll-margin-top:3.6rem}.md-typeset h1:target,.md-typeset h2:target,.md-typeset h3:target{scroll-margin-top:initial}.md-typeset h1:target::before,.md-typeset h2:target::before,.md-typeset h3:target::before{display:block;margin-top:-3.4rem;padding-top:3.4rem;content:""}.md-typeset h4:target{scroll-margin-top:initial}.md-typeset h4:target::before{display:block;margin-top:-3.45rem;padding-top:3.45rem;content:""}.md-typeset h5:target,.md-typeset h6:target{scroll-margin-top:initial}.md-typeset h5:target::before,.md-typeset h6:target::before{display:block;margin-top:-3.6rem;padding-top:3.6rem;content:""}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width: 44.9375em){.md-typeset div.arithmatex{margin:0 -0.8rem}}.md-typeset div.arithmatex>*{width:-webkit-min-content;width:-moz-min-content;width:min-content;margin:1em auto !important;padding:0 .8rem;touch-action:auto}.md-typeset del.critic,.md-typeset ins.critic,.md-typeset .critic.comment{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment::before{content:"/* "}.md-typeset .critic.comment::after{content:" */"}.md-typeset .critic.block{display:block;margin:1em 0;padding-right:.8rem;padding-left:.8rem;overflow:auto;box-shadow:none}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon: url("data:image/svg+xml;charset=utf-8,")}.md-typeset details{display:block;padding-top:0;overflow:visible}.md-typeset details[open]>summary::after{transform:rotate(90deg)}.md-typeset details:not([open]){padding-bottom:0;box-shadow:none}.md-typeset details:not([open])>summary{border-radius:.1rem}.md-typeset details::after{display:table;content:""}.md-typeset summary{display:block;min-height:1rem;padding:.4rem 1.8rem .4rem 2rem;border-top-left-radius:.1rem;border-top-right-radius:.1rem;cursor:pointer}[dir=rtl] .md-typeset summary{padding:.4rem 2.2rem .4rem 1.8rem}.md-typeset summary:not(.focus-visible){outline:none;-webkit-tap-highlight-color:transparent}.md-typeset summary::after{position:absolute;top:.4rem;right:.4rem;width:1rem;height:1rem;background-color:currentColor;-webkit-mask-image:var(--md-details-icon);mask-image:var(--md-details-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transform:rotate(0deg);transition:transform 250ms;content:""}[dir=rtl] .md-typeset summary::after{right:initial;left:.4rem;transform:rotate(180deg)}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset .emojione,.md-typeset .twemoji,.md-typeset .gemoji{display:inline-block;height:1.125em;vertical-align:text-top}.md-typeset .emojione svg,.md-typeset .twemoji svg,.md-typeset .gemoji svg{width:1.125em;max-height:100%;fill:currentColor}.highlight .o,.highlight .ow{color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight .cpf,.highlight .l,.highlight .s,.highlight .sb,.highlight .sc,.highlight .s2,.highlight .si,.highlight .s1,.highlight .ss{color:var(--md-code-hl-string-color)}.highlight .cp,.highlight .se,.highlight .sh,.highlight .sr,.highlight .sx{color:var(--md-code-hl-special-color)}.highlight .m,.highlight .mb,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .il,.highlight .mo{color:var(--md-code-hl-number-color)}.highlight .k,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:var(--md-code-hl-keyword-color)}.highlight .kc,.highlight .n{color:var(--md-code-hl-name-color)}.highlight .no,.highlight .nb,.highlight .bp{color:var(--md-code-hl-constant-color)}.highlight .nc,.highlight .ne,.highlight .nf,.highlight .nn{color:var(--md-code-hl-function-color)}.highlight .nd,.highlight .ni,.highlight .nl,.highlight .nt{color:var(--md-code-hl-keyword-color)}.highlight .c,.highlight .cm,.highlight .c1,.highlight .ch,.highlight .cs,.highlight .sd{color:var(--md-code-hl-comment-color)}.highlight .na,.highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi{color:var(--md-code-hl-variable-color)}.highlight .ge,.highlight .gr,.highlight .gh,.highlight .go,.highlight .gp,.highlight .gs,.highlight .gu,.highlight .gt{color:var(--md-code-hl-generic-color)}.highlight .gd,.highlight .gi{margin:0 -0.125em;padding:0 .125em;border-radius:.1rem}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em;background-color:var(--md-code-hl-color)}.highlight [data-linenos]::before{position:-webkit-sticky;position:sticky;left:-1.1764705882em;float:left;margin-right:1.1764705882em;margin-left:-1.1764705882em;padding-left:1.1764705882em;color:var(--md-default-fg-color--light);background-color:var(--md-code-bg-color);box-shadow:-0.05rem 0 var(--md-default-fg-color--lightest) inset;content:attr(data-linenos);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.highlighttable{display:flow-root;overflow:hidden}.highlighttable tbody,.highlighttable td{display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable .linenos{padding:.7720588235em 1.1764705882em;padding-right:0;font-size:.85em;background-color:var(--md-code-bg-color);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.highlighttable .linenodiv{padding-right:.5882352941em;box-shadow:-0.05rem 0 var(--md-default-fg-color--lightest) inset}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .code{flex:1;overflow:hidden}.md-typeset .highlighttable{margin:1em 0;direction:ltr;border-radius:.1rem}.md-typeset .highlighttable code{border-radius:0}@media screen and (max-width: 44.9375em){.md-typeset>.highlight{margin:1em -0.8rem}.md-typeset>.highlight .hll{margin:0 -0.8rem;padding:0 .8rem}.md-typeset>.highlight code{border-radius:0}.md-typeset>.highlighttable{margin:1em -0.8rem;border-radius:0}.md-typeset>.highlighttable .hll{margin:0 -0.8rem;padding:0 .8rem}}.md-typeset .keys kbd::before,.md-typeset .keys kbd::after{position:relative;margin:0;color:inherit;-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial}.md-typeset .keys span{padding:0 .2em;color:var(--md-default-fg-color--light)}.md-typeset .keys .key-alt::before{padding-right:.4em;content:"⎇"}.md-typeset .keys .key-left-alt::before{padding-right:.4em;content:"⎇"}.md-typeset .keys .key-right-alt::before{padding-right:.4em;content:"⎇"}.md-typeset .keys .key-command::before{padding-right:.4em;content:"⌘"}.md-typeset .keys .key-left-command::before{padding-right:.4em;content:"⌘"}.md-typeset .keys .key-right-command::before{padding-right:.4em;content:"⌘"}.md-typeset .keys .key-control::before{padding-right:.4em;content:"⌃"}.md-typeset .keys .key-left-control::before{padding-right:.4em;content:"⌃"}.md-typeset .keys .key-right-control::before{padding-right:.4em;content:"⌃"}.md-typeset .keys .key-meta::before{padding-right:.4em;content:"◆"}.md-typeset .keys .key-left-meta::before{padding-right:.4em;content:"◆"}.md-typeset .keys .key-right-meta::before{padding-right:.4em;content:"◆"}.md-typeset .keys .key-option::before{padding-right:.4em;content:"⌥"}.md-typeset .keys .key-left-option::before{padding-right:.4em;content:"⌥"}.md-typeset .keys .key-right-option::before{padding-right:.4em;content:"⌥"}.md-typeset .keys .key-shift::before{padding-right:.4em;content:"⇧"}.md-typeset .keys .key-left-shift::before{padding-right:.4em;content:"⇧"}.md-typeset .keys .key-right-shift::before{padding-right:.4em;content:"⇧"}.md-typeset .keys .key-super::before{padding-right:.4em;content:"❖"}.md-typeset .keys .key-left-super::before{padding-right:.4em;content:"❖"}.md-typeset .keys .key-right-super::before{padding-right:.4em;content:"❖"}.md-typeset .keys .key-windows::before{padding-right:.4em;content:"⊞"}.md-typeset .keys .key-left-windows::before{padding-right:.4em;content:"⊞"}.md-typeset .keys .key-right-windows::before{padding-right:.4em;content:"⊞"}.md-typeset .keys .key-arrow-down::before{padding-right:.4em;content:"↓"}.md-typeset .keys .key-arrow-left::before{padding-right:.4em;content:"←"}.md-typeset .keys .key-arrow-right::before{padding-right:.4em;content:"→"}.md-typeset .keys .key-arrow-up::before{padding-right:.4em;content:"↑"}.md-typeset .keys .key-backspace::before{padding-right:.4em;content:"⌫"}.md-typeset .keys .key-backtab::before{padding-right:.4em;content:"⇤"}.md-typeset .keys .key-caps-lock::before{padding-right:.4em;content:"⇪"}.md-typeset .keys .key-clear::before{padding-right:.4em;content:"⌧"}.md-typeset .keys .key-context-menu::before{padding-right:.4em;content:"☰"}.md-typeset .keys .key-delete::before{padding-right:.4em;content:"⌦"}.md-typeset .keys .key-eject::before{padding-right:.4em;content:"⏏"}.md-typeset .keys .key-end::before{padding-right:.4em;content:"⤓"}.md-typeset .keys .key-escape::before{padding-right:.4em;content:"⎋"}.md-typeset .keys .key-home::before{padding-right:.4em;content:"⤒"}.md-typeset .keys .key-insert::before{padding-right:.4em;content:"⎀"}.md-typeset .keys .key-page-down::before{padding-right:.4em;content:"⇟"}.md-typeset .keys .key-page-up::before{padding-right:.4em;content:"⇞"}.md-typeset .keys .key-print-screen::before{padding-right:.4em;content:"⎙"}.md-typeset .keys .key-tab::after{padding-left:.4em;content:"⇥"}.md-typeset .keys .key-num-enter::after{padding-left:.4em;content:"⌤"}.md-typeset .keys .key-enter::after{padding-left:.4em;content:"⏎"}.md-typeset .tabbed-content{display:none;order:99;width:100%;box-shadow:0 -0.05rem var(--md-default-fg-color--lightest)}@media print{.md-typeset .tabbed-content{display:block;order:initial}}.md-typeset .tabbed-content>pre:only-child,.md-typeset .tabbed-content>.highlight:only-child pre,.md-typeset .tabbed-content>.highlighttable:only-child{margin:0}.md-typeset .tabbed-content>pre:only-child>code,.md-typeset .tabbed-content>.highlight:only-child pre>code,.md-typeset .tabbed-content>.highlighttable:only-child>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-content>.tabbed-set{margin:0}.md-typeset .tabbed-set{position:relative;display:flex;flex-wrap:wrap;margin:1em 0;border-radius:.1rem}.md-typeset .tabbed-set>input{position:absolute;width:0;height:0;opacity:0}.md-typeset .tabbed-set>input:checked+label{color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color)}.md-typeset .tabbed-set>input:checked+label+.tabbed-content{display:block}.md-typeset .tabbed-set>input:focus+label{outline-style:auto}.md-typeset .tabbed-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.md-typeset .tabbed-set>label{z-index:1;width:auto;padding:.9375em 1.25em .78125em;color:var(--md-default-fg-color--light);font-weight:700;font-size:.64rem;border-bottom:.1rem solid transparent;cursor:pointer;transition:color 250ms}.md-typeset .tabbed-set>label:hover{color:var(--md-accent-fg-color)}:root{--md-tasklist-icon: url( "data:image/svg+xml;charset=utf-8," );--md-tasklist-icon--checked: url( "data:image/svg+xml;charset=utf-8," )}.md-typeset .task-list-item{position:relative;list-style-type:none}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em;left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em;left:initial}.md-typeset .task-list-control [type=checkbox]{z-index:-1;opacity:0}.md-typeset .task-list-indicator::before{position:absolute;top:.15em;left:-1.5em;width:1.25em;height:1.25em;background-color:var(--md-default-fg-color--lightest);-webkit-mask-image:var(--md-tasklist-icon);mask-image:var(--md-tasklist-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;content:""}[dir=rtl] .md-typeset .task-list-indicator::before{right:-1.5em;left:initial}.md-typeset [type=checkbox]:checked+.task-list-indicator::before{background-color:#00e676;-webkit-mask-image:var(--md-tasklist-icon--checked);mask-image:var(--md-tasklist-icon--checked)} + +/*# sourceMappingURL=main.15aa0b43.min.css.map*/ \ No newline at end of file diff --git a/public/assets/stylesheets/main.15aa0b43.min.css.map b/public/assets/stylesheets/main.15aa0b43.min.css.map new file mode 100644 index 0000000..e15934f --- /dev/null +++ b/public/assets/stylesheets/main.15aa0b43.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/assets/stylesheets/main.scss","webpack:///./src/assets/stylesheets/main/_reset.scss","webpack:///./src/assets/stylesheets/main/_colors.scss","webpack:///./src/assets/stylesheets/main/_icons.scss","webpack:///./src/assets/stylesheets/main/_typeset.scss","webpack:///./src/assets/stylesheets/utilities/_break.scss","webpack:///./node_modules/material-shadows/material-shadows.scss","webpack:///./src/assets/stylesheets/main/layout/_base.scss","webpack:///./src/assets/stylesheets/main/layout/_announce.scss","webpack:///./src/assets/stylesheets/main/layout/_button.scss","webpack:///./src/assets/stylesheets/main/layout/_clipboard.scss","webpack:///./src/assets/stylesheets/main/layout/_content.scss","webpack:///./src/assets/stylesheets/main/layout/_dialog.scss","webpack:///./src/assets/stylesheets/main/layout/_header.scss","webpack:///./src/assets/stylesheets/main/layout/_footer.scss","webpack:///./src/assets/stylesheets/main/layout/_nav.scss","webpack:///./src/assets/stylesheets/main/layout/_search.scss","webpack:///./src/assets/stylesheets/main/layout/_sidebar.scss","webpack:///./src/assets/stylesheets/main/layout/_source.scss","webpack:///./src/assets/stylesheets/main/layout/_tabs.scss","webpack:///./src/assets/stylesheets/main/extensions/markdown/_admonition.scss","webpack:///./node_modules/material-design-color/material-color.scss","webpack:///./src/assets/stylesheets/main/extensions/markdown/_footnotes.scss","webpack:///./src/assets/stylesheets/main/extensions/markdown/_toc.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_critic.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_details.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_emoji.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_highlight.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_keys.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss","webpack:///./src/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss"],"names":[],"mappings":"AAAA,KC4BA,qBACE,8BACA,CADA,0BACA,CADA,yBACA,CADA,qBACA,sBAIF,kBAGE,MAIF,QACE,sBAIF,uCAIE,GAIF,aACE,qBACA,IAIF,aACE,uBACA,cACA,UACA,iBACA,SACA,OAIF,aACE,SAIF,eAEE,KAIF,iBACE,OAIF,wBACE,iBACA,OAIF,eAEE,mBACA,QAIF,QACE,UACA,kBACA,uBACA,SACA,OAIF,QACE,aACA,OCnFF,4CAGE,oDACA,sDACA,uDACA,4CACA,qDACA,uDACA,yDACA,8CAGA,qDACA,oDACA,4CACA,qDACA,6CAGA,4DACA,2CACA,oDACA,SAGA,0CAGE,wCACA,6CAGA,gDACA,mDACA,oDACA,oDACA,mDACA,kDACA,iDACA,+DACA,kEACA,8DACA,8DACA,+DACA,+CAGA,iDACA,kDAGA,gDAGA,kDACA,4CAGA,sDACA,mDACA,qDAGA,qDACA,2CAGA,oDACA,sDACA,4CACA,kDACA,cCrEF,aACE,aACA,cACA,kBACA,MCPJ,kCACE,kCACA,YAIF,6BAEE,oCACA,wEACA,cAIF,6BAGE,6BACA,oDACA,OAQF,wcACE,ucACA,aAOF,eACE,gBACA,iCACA,CADA,kBACA,cAIA,YAPF,gBAQI,oFAIF,YAKE,gBAIF,iBACE,wCACA,gBACA,cACA,gBACA,uBACA,gBAIF,oBACE,gBACA,mBACA,gBACA,uBACA,gBAIF,mBACE,gBACA,iBACA,gBACA,uBACA,mBAIF,eACE,gBAIF,YACE,gBACA,uBACA,+BAIF,eAEE,wCACA,gBACA,eACA,uBACA,gBAIF,wBACE,gBAIF,cACE,gEACA,eAIF,+BACE,sBACA,qCAGA,sBAEE,yCAIF,+BAEE,kDAKJ,6BAGE,cACA,cAGA,iDAPF,oBAQI,mBAKJ,uBACE,gBACA,sBACA,yCACA,oBACA,mCACA,CADA,0BACA,sCAGA,YACE,wCACA,yHAKJ,cAME,gBACA,6BACA,gBACA,oBAIF,kBACE,iBAIF,iBACE,aACA,gBACA,sBAGA,aACE,SACA,qCACA,cACA,kBACA,gBACA,mCACA,CADA,0BACA,kBACA,qBACA,gEACA,4BAGA,qDACE,yCAIF,WACE,aACA,+CAIF,oDACE,qDAGA,0CACE,0CCxCN,gBDkDA,kBACE,sBAGA,eACE,kBAMN,oBACE,wBACA,iCACA,gBACA,wBACA,sBACA,6CACA,oBACA,qKAEE,kBAMJ,aACE,sBACA,8CACA,mCACA,CADA,0BACA,kBAIF,oBACE,8DACA,YACA,qBAGA,iBANF,iBAOI,2EAGA,gGEnRJ,kBFuRM,OACA,qBACA,WACA,8BACA,CADA,0BACA,CADA,qBACA,cACA,eACA,oBACA,iCACA,gBACA,4CACA,oBACA,oBACA,oBAON,WACE,iCAIF,qBAEE,qDAGA,sBACE,oBACA,wBAKJ,kBACE,wCACA,4DACA,kCAGA,mBACE,qBACA,6DACA,oBACA,gBAKJ,oBACE,+BAIF,kBAEE,UACA,mDAGA,mBACE,oBACA,qCAIF,2BACE,2CAGA,2BACE,qCAKJ,kBACE,mBACA,yDAGA,mBACE,oBACA,mGAIF,aAEE,2DAIF,eACE,qFAIF,yBAEE,6HAGA,mBACE,oBACA,gBAOR,0BACE,0BAGA,oBACE,oBACA,iCAKJ,cAEE,YACA,yDAGA,UACE,cACA,2DAIF,UACE,eACA,qEAIF,YACE,oBAKJ,yBACE,CADF,sBACE,CADF,iBACE,eACA,cACA,kBACA,wBAGA,aACE,wBAKJ,eACE,oBACA,kBACA,oBAIF,cACE,gCAIF,oBACE,eACA,cACA,iBACA,4CACA,oBACA,mEAEE,kBAEF,cAGA,+BAbF,aAcI,mCAMF,gBACE,iGAQA,YACE,+FAIF,eACE,+FAKJ,eAEE,mHAGA,gBACE,mCAKJ,cACE,uBACA,iCACA,mBACA,mDACA,qCAGA,aACE,mCAKJ,sBACE,mBACA,6DACA,mCAIF,iCACE,yCAGA,iCACE,uDACA,kDAIF,YACE,kCAKJ,iBACE,yCAKJ,cACE,gDAGA,oBACE,YACA,aACA,iBACA,mBACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,qEAIF,6BACE,sDACA,CADA,6CACA,sEAIF,6BACE,uDACA,CADA,8CACA,yBAKJ,kBACE,gBACA,kBACA,oBAIF,oBACE,mBACA,gBACA,cAGA,mBANF,aAOI,gCAIF,aACE,WACA,SACA,gBACA,MGplBN,WACE,kBACA,eAOA,sCFuJE,KEhKJ,gBAaI,uCFmJA,KEhKJ,cAkBI,OAMJ,iBACE,aACA,sBACA,WACA,gBACA,gBAGA,4CACA,cAGA,KAZF,aAaI,2CF6IA,yBEzIF,cAII,WAUN,eACE,kBACA,iBACA,eAIF,YACE,sBACA,YACA,cAGA,cANF,aAOI,WAKJ,WACE,iBAGA,YACE,YACA,kBACA,cAKJ,eACE,mBACA,uBACA,YASF,YACE,UAIF,cACE,WAGA,aACA,oBACA,iCACA,iBACA,4CACA,oBACA,6BACA,UACA,gBAGA,UACE,wBACA,UACA,2EAEE,OAUN,WACE,cCtIF,aACE,2CACA,cAGA,aALF,YAMI,sBAIF,iBACE,gBACA,gCACA,gBACA,wBCXF,oBACE,mBACA,iCACA,gBACA,gCACA,oBACA,iEAEE,iCAKF,gCACE,4CACA,wCACA,2DAIF,+BAEE,2CACA,uCACA,OC3BN,mfACE,eAMF,iBACE,SACA,WACA,UACA,YACA,aACA,2CACA,oBACA,eACA,uBACA,cAGA,cAbF,YAcI,uBAIF,uCACE,yCAIF,+BAEE,sBAKF,aACE,cACA,eACA,cACA,8BACA,4CACA,CADA,mCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,aC9CJ,WACE,gBAMA,2BACA,oBAGA,qBACE,kBACA,wCNmJA,kEM7IE,kBACE,6EAGA,mBACE,kBACA,qEAKJ,mBACE,+EAGA,kBACE,mBACA,6BAON,aACE,aACA,WACA,gCAIF,eACE,qBAMJ,WACE,eACA,kBACA,UACA,cAGA,oBAPF,YAQI,gCAIF,UACE,mBACA,oBACA,mCAGA,oBACE,iCAKJ,yCACE,yBAIF,cACE,mBACA,YCxFN,gGNFE,eMKA,YACA,aACA,aACA,UACA,cACA,kBACA,oBACA,iCACA,gBACA,4CACA,YACA,oBACA,2BACA,UACA,6CAEE,cAIF,WAvBF,YAwBI,uBAIF,aACE,WACA,gCAIF,uBACE,UACA,6EAEE,YCrCN,uBACE,CADF,eACE,MACA,QACA,OACA,UACA,iCACA,4CACA,+DAIE,8CAGA,cAIF,WAlBF,YAmBI,mCAIF,gEAEI,8GAGA,kCAOJ,2BACE,4GAEE,gBASN,YACE,mBACA,gBACA,wBAGA,iBACE,UACA,qBACA,aACA,cACA,mBACA,sBACA,eACA,yBACA,2DAGA,UAEE,4CAIF,YACE,gCAIF,YACE,cACA,0CRmGF,+BQrGA,YAMI,wEAIF,aAEE,aACA,cACA,kBACA,qCRoEJ,qCQ/DA,YAII,8CAIF,YACE,oDAOA,oBACE,wCR8CN,qCQxCA,YAII,wBAMN,iBACE,aACA,eACA,wEAEE,6CAIF,UACE,8BACA,UACA,wEAEE,oBAEF,uDAGA,8BACE,uBAMN,WACE,cACA,mBACA,iBACA,gBACA,mBACA,mEAGA,UACE,+BACA,UACA,wEAEE,oBAEF,6EAGA,6BACE,yFAIF,SACE,wBACA,UACA,wEAEE,uBAEF,gDAKJ,iBACE,WACA,YACA,wBAKJ,YACE,qCRzCA,uBQwCF,aAKI,cACA,kBACA,iBACA,kCAGA,iBACE,oBACA,yCRrDJ,uBQwCF,kBAmBI,kCAGA,mBACE,aC/NR,+BACE,2CACA,cAGA,WALF,YAMI,wBAQF,aACE,cACA,sBAIF,YACE,mBACA,qBACA,yBACA,qCTwIA,qBS5IF,SAQI,wDAIF,UAEE,4BAIF,UACE,0CT2IF,2BS5IA,SAKI,kDAGA,YACE,uCAKJ,WACE,0CAGA,oBACE,4BAMN,WACE,iBACA,0CTiHF,2BSnHA,SAMI,uCAIF,UACE,gBACA,0CAGA,oBACE,uBAOR,iBACE,YACA,8BACA,eACA,gBACA,mBACA,wBAIF,YACE,cACA,2BAIF,iBACE,QACA,OACA,iBACA,eACA,iBACA,WACA,iBAKJ,gDACE,wBAGA,YACE,eACA,8BACA,cACA,mCAIF,sCACE,iFAGA,+BAEE,sBAMN,UACE,kBACA,gBACA,yCACA,iBACA,qCTiBE,qBStBJ,UASI,kCAKF,sCACE,mBAKJ,cACE,sBACA,uDAFF,eAMI,0BAIF,oBACE,aACA,cACA,kBACA,iCAGA,eACE,6BAIF,gBACE,oBACA,kBACA,OCvLN,6bACE,sbACA,0dACA,SAMF,eACE,gBACA,gBAGA,aACE,gBACA,gBACA,gBACA,uBACA,gCAGA,YACE,oCAGA,UACE,YACA,uFAOA,aAEE,aACA,cACA,kBACA,eAOR,QACE,UACA,gBACA,eAIF,eACE,6BAGA,eACE,uCAGA,mBACE,eACA,eAMN,aACE,kBACA,gBACA,uBACA,eACA,uBACA,wBACA,mCAGA,uCACE,qCAIF,+BACE,qCAIF,aACE,yCAIF,+BAEE,2CAIF,YACE,2DAGA,aACE,WACA,YACA,sCACA,CADA,6BACA,8BACA,mDAIF,YACE,iBAMN,YACE,0CVwDA,0CUjDA,iBAEE,MACA,QACA,OACA,UACA,aACA,sBACA,YACA,4CACA,gEAOA,eAEE,gBACA,iCAIF,iBACE,cACA,yBACA,wCACA,gBACA,mBACA,mBACA,sDACA,eACA,+CAGA,iBACE,UACA,WACA,cACA,aACA,cACA,aACA,yDAGA,WACE,aACA,sDAIF,aACE,WACA,YACA,8BACA,4CACA,CADA,mCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,+CAKJ,eACE,4CACA,iEAEE,qCACF,CADE,gCACF,CADE,4BACF,mBACA,4DAGA,YACE,+CAKJ,gCACE,4CACA,0CAIF,iBACE,UACA,WACA,cACA,aACA,cACA,oDAGA,WACE,aACA,gCAMN,MACE,gCAIF,SACE,6DACA,sDAGA,oBACE,gEAGA,mBACE,oBACA,sDAKJ,+BACE,uHAGA,+BAEE,gCAMN,iBACE,aACA,oBACA,8CAGA,iBACE,QACA,YACA,aACA,cACA,mBACA,cACA,iBACA,wDAGA,aACE,WACA,qDAIF,aACE,WACA,YACA,8BACA,4CACA,CADA,mCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,iDASJ,mBACE,mDAQF,eACE,6CAIF,eACE,6BACA,2DAGA,mBACE,qEAGA,oBACE,qBACA,mEAKJ,iBACE,6EAGA,kBACE,qBACA,2EAKJ,mBACE,qFAGA,oBACE,qBACA,mFAKJ,mBACE,6FAGA,oBACE,qBACA,oBAQV,4BACE,yBAIF,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CXlRF,uBW6PF,YA0BI,qBACA,gEACA,mEAGA,eACE,8BAIF,qDACE,2CAIF,WACE,aACA,iDAIF,oDACE,uDAGA,0CACE,oBAQV,gCACE,sBACA,yBAGA,eACE,wCACA,iBACA,mBACA,sDACA,wBACA,qCXpUA,wBW8TF,mBAUI,mCAGA,oBACE,qBACA,0BAMN,QACE,UACA,gBACA,yBAIF,4DACE,qCAGA,eACE,yBAKJ,aACE,aACA,kCACA,wBACA,6DAGA,uDAEE,iDAIF,mBACE,iCAKJ,aACE,oBACA,gCACA,iBACA,UACA,eACA,8CAEE,wBAEF,qCXjYA,gCWuXF,mBAcI,2CAGA,oBACE,mBACA,8EAKJ,+BAEE,wDACA,yDAIF,YACE,qCAIF,WACE,4BAKJ,iBACE,gBACA,gBACA,qCXpaA,2BWiaF,mBAOI,sCAGA,oBACE,mBACA,gEAQF,eACE,gBACA,gBACA,gBACA,yBAMN,iBACE,OACA,aACA,cACA,aACA,wCACA,0CXnbA,wBW6aF,YAUI,iCAIF,oBACE,WACA,YACA,8BACA,gDACA,CADA,uCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,mCAIF,OACE,aACA,0CAGA,oBACE,0BAMN,aACE,gBACA,iBACA,gBACA,2BAIF,mBACE,gBACA,cACA,gBACA,wCACA,iBACA,gBACA,uBACA,4BACA,qBACA,0CXreA,0BW2dF,eAcI,qBACA,gEXjhBA,0BWkgBJ,eAoBI,qBACA,iCAIF,yBACE,6BACA,0BAKJ,aACE,iBACA,kBACA,wBAIF,+BACE,6BACA,aCtrBJ,uBACE,CADF,eACE,WACA,cACA,sBACA,cACA,SACA,iBACA,cAGA,YAVF,YAWI,2CZuKA,qBYhKA,cACE,MACA,cACA,UACA,cACA,cACA,YACA,4CACA,wBACA,yEAEE,gCAIF,cACE,aACA,oEAIF,sGXjBJ,8BWoBM,8EAGA,8BACE,8CAKJ,iBACE,MACA,QACA,SACA,OACA,SACA,8BACA,CADA,yBACA,CADA,qBACA,gBACA,yCZqGJ,YYhKJ,QAkEI,oBAGA,WACE,yBAKJ,YACE,QACA,qCZmFA,uBYrFF,QAMI,+BAGA,WACE,sCAIF,aACE,gDAIF,kBACE,0BAMN,cACE,gBACA,mCAEA,CAFA,0BAEA,qBAKA,gEACA,+BAGA,qDACE,4CAIF,WACE,aACA,kDAIF,oDACE,wDAGA,0CACE,0CZgDJ,YYtCF,cACE,MACA,UACA,QACA,SACA,iCACA,UACA,0DAEE,6CAKF,UACE,YACA,UACA,8CAEE,4CC/JR,GACE,QACE,MAEF,aACE,ED0JI,kCC/JR,GACE,QACE,MAEF,aACE,2CAKJ,GACE,0BACE,UACA,KAEF,SACE,MAEF,wBACE,UACA,EAfA,iCAKJ,GACE,0BACE,UACA,KAEF,SACE,MAEF,wBACE,UACA,aASJ,aACE,iBACA,gBACA,mBACA,mCAEA,CAFA,0BAEA,yBACA,mCAGA,UAEE,kBAIF,oBACE,aACA,cACA,sBACA,sBAGA,gBACE,kBACA,gCAGA,kBACE,oBACA,yCAKJ,iBACE,kBACA,mDAGA,kBACE,oBACA,mBACA,qBACA,wBAMN,oBACE,8BACA,kBACA,gBACA,gBACA,uBACA,sBACA,mBAIF,QACE,UACA,gBACA,gBACA,iBACA,qBACA,YACA,wCAGA,sDACE,CADF,8CACE,kBAKJ,UACE,4BAGA,WACE,uCAIF,sDACE,CADF,8CACE,0BAIF,cACE,YACA,sCAIF,YACE,UC/HN,UACE,cACA,iCACA,4CACA,kCACA,cAGA,SARF,YASI,2CdyKA,SclLJ,YAcI,iCAIF,mBACE,gBAIF,QACE,kBACA,UACA,mBACA,gBACA,gBACA,0BAGA,kBACE,oBACA,gBAKJ,oBACE,cACA,oBACA,mBACA,gBAKF,aACE,iBACA,gBACA,mCAEA,CAFA,0BAEA,WACA,wEAEE,kEAIF,aAGE,UACA,4CAKA,qBACE,4CADF,qBACE,4CADF,qBACE,4CADF,qBACE,4CADF,sBACE,4CADF,sBACE,4CADF,sBACE,4CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,6CADF,sBACE,+CAMJ,yBACE,UACA,6CAEE,OC5DR,+gBAEI,iyNAYF,iBACE,gBACA,gBACA,oCACA,iBACA,wBACA,+CACA,gCACA,oBACA,0EAEE,cAIF,4CAfF,eAgBI,kEAIF,gCACE,iBACA,iIAIF,YACE,6FAIF,kBACE,mFAIF,eACE,2FAIF,YACE,+EAIF,mBACE,mDAKJ,iBACE,2BACA,+BACA,gBACA,qCACA,gCACA,uEAGA,0BACE,+BACA,iCACA,iBACA,mFAIF,eACE,mEAIF,iBACE,WACA,WACA,YACA,yBCyIU,mDDvIV,CCuIU,0CDvIV,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,uFAGA,WACE,aACA,6DAMJ,cACE,gBACA,mBACA,6BACA,sBACA,gBACA,iGAKF,YACE,uDAcJ,oBAHO,+DAQP,oCACE,qBATK,+EAaL,wBAbK,mDAeH,CAfG,0CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,iLAdJ,oBAHO,yMAQP,mCACE,qBATK,yPAaL,wBAbK,uDAeH,CAfG,8CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,6GAdJ,oBAHO,6HAQP,mCACE,qBATK,6JAaL,wBAbK,mDAeH,CAfG,0CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,2KAdJ,oBAHO,mMAQP,mCACE,qBATK,mPAaL,wBAbK,kDAeH,CAfG,yCAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,2KAdJ,oBAHO,mMAQP,kCACE,qBATK,mPAaL,wBAbK,sDAeH,CAfG,6CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,yKAdJ,oBAHO,iMAQP,oCACE,qBATK,iPAaL,wBAbK,uDAeH,CAfG,8CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,yLAdJ,oBAHO,iNAQP,mCACE,qBATK,iQAaL,wBAbK,sDAeH,CAfG,6CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,+KAdJ,oBAHO,uMAQP,mCACE,qBATK,uPAaL,wBAbK,sDAeH,CAfG,6CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,mHAdJ,oBAHO,mIAQP,mCACE,qBATK,mKAaL,wBAbK,qDAeH,CAfG,4CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,qDAdJ,oBAHO,6DAQP,kCACE,qBATK,6EAaL,wBAbK,kDAeH,CAfG,yCAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,6DAdJ,oBAHO,qEAQP,oCACE,qBATK,qFAaL,wBAbK,sDAeH,CAfG,6CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,+GAdJ,oBAHO,+HAQP,qCACE,qBATK,+JAaL,wBAbK,oDAeH,CAfG,2CAeH,8BACA,CADA,qBACA,0BACA,CADA,iBACA,OExKN,6bACE,mCASA,yBACE,mBACA,mBACA,gCAIF,yBACE,oBACA,oBACA,uBAIF,uCACE,iBACA,0BAGA,aACE,0BAIF,sBACE,iCAGA,gCACE,oGAIF,uBAEE,UACA,uCAIF,YACE,+BAMN,oBACE,gCACA,YAEA,2BACA,8BACA,UACA,iEAEE,cAKF,8BAdF,+BAeI,wBACA,UACA,0CAIF,8BACE,qCAIF,+BACE,uCAIF,oBACE,YACA,aACA,8BACA,4CACA,CADA,mCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,qDAME,oBACE,yBCpGR,oBACE,kBACA,0CACA,UACA,qCAEE,cAIF,wBAVF,YAWI,oCAIF,kBACE,oBACA,8FAKJ,SAGE,qCAEE,6FAKJ,+BAGE,qBAOF,wBACE,mEAIF,yBAGE,2FAGA,aACE,mBACA,mBACA,WACA,uBAKJ,yBACE,+BAGA,aACE,oBACA,oBACA,WACA,6CAKJ,yBAEE,6DAGA,aACE,mBACA,mBACA,WACA,4BCpFJ,aACE,0CnB8KA,2BmB/KF,gBAKI,+BAIF,yBACE,CADF,sBACE,CADF,iBACE,2BACA,gBACA,kBACA,2ECbJ,kCAGE,CAHF,0BAGE,wBAIF,4CACE,wBAIF,4CACE,6BAIF,qCACE,qCAGA,aACE,oCAIF,aACE,2BAKJ,aACE,aACA,oBACA,mBACA,cACA,gBACA,wCAGA,eACE,uCAIF,kBACE,OClDN,mbACE,qBASA,aAGE,cACA,iBACA,0CAGA,uBACE,iCAIF,gBACE,gBACA,yCAMA,mBACE,4BAKJ,aACE,WACA,qBAKJ,aAGE,gBACA,gCACA,6BACA,8BACA,eACA,+BAGA,iCACE,yCAIF,YACE,wCACA,4BAIF,iBACE,UACA,YACA,WACA,YACA,8BACA,0CACA,CADA,iCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,uBACA,2BACA,WACA,sCAGA,aACE,WACA,yBACA,6CAKJ,YACE,gECvFJ,oBAGE,eACA,wBACA,4EAGA,aACE,gBACA,kBACA,8BCZJ,sCAEE,eAGF,yCACE,uIAGF,oCASE,4EAGF,qCAKE,yGAGF,oCAOE,0FAGF,qCAME,8BAGF,kCAEE,8CAGF,sCAGE,6DAGF,sCAIE,6DAGF,qCAIE,0FAGF,qCAME,4EAGF,sCAKE,yHAGF,qCAQE,+BAGF,iBAEE,iBACA,oBACA,gBAGF,4CACE,gBAGF,4CACE,iBAIF,aACE,yBACA,yBACA,yCACA,mCAIF,uBACE,CADF,eACE,qBACA,WACA,4BACA,4BACA,4BACA,wCACA,yCACA,iEACA,2BACA,yBACA,CADA,qBACA,CADA,oBACA,CADA,gBACA,iBASJ,iBACE,gBACA,0CAIA,aAEE,UACA,oBAKF,YACE,qBAKF,QACE,0BAKF,oCACE,gBACA,gBACA,yCACA,yBACA,CADA,qBACA,CADA,oBACA,CADA,gBACA,4BAIF,2BACE,iEACA,gCAGA,uCACE,iBACA,uBAKJ,MACE,gBACA,6BAUF,YACE,cACA,oBACA,kCAGA,eACE,0CvBnCF,uBuB2CA,kBACE,6BAGA,gBACE,gBACA,6BAIF,eACE,6BAKJ,kBACE,gBACA,kCAGA,gBACE,gBACA,6DC9OJ,iBAEE,SACA,cACA,gCACA,+BACA,wBAIF,cACE,wCACA,oCAqDE,kBACE,YAlDgB,yCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,8CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,8CAiDlB,kBACE,YAlDgB,qCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,uCAiDlB,kBACE,YAlDgB,4CAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,sCAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,4CAiDlB,kBACE,YAlDgB,sCAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,4CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,8CAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,2CAiDlB,kBACE,YAlDgB,4CAiDlB,kBACE,YAlDgB,yCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,sCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,uCAiDlB,kBACE,YAlDgB,sCAiDlB,kBACE,YAlDgB,oCAiDlB,kBACE,YAlDgB,uCAiDlB,kBACE,YAlDgB,qCAiDlB,kBACE,YAlDgB,uCAiDlB,kBACE,YAlDgB,0CAiDlB,kBACE,YAlDgB,wCAiDlB,kBACE,YAlDgB,6CAiDlB,kBACE,YAlDgB,mCA+DlB,iBACE,YAPgB,yCAMlB,iBACE,YAPgB,qCAMlB,iBACE,YAPgB,6BC5ExB,YACE,SACA,WACA,2DACA,cAGA,4BAPF,aAQI,cACA,0JAKF,QAGE,wKAGA,wBACE,0BACA,yCAKJ,QACE,yBAKJ,iBACE,aACA,eACA,aACA,oBACA,+BAMA,iBACE,QACA,SACA,UACA,6CAGA,+BACE,uCACA,6DAGA,aACE,2CAKJ,kBACE,yDAIF,YACE,wCACA,+BAKJ,SACE,WACA,gCACA,wCACA,gBACA,iBACA,sCACA,eACA,uBACA,qCAGA,+BACE,OC1FR,yWACE,mXAGA,6BAWA,iBACE,qBACA,6CAIA,iBACE,UACA,UACA,uDAGA,UACE,aACA,gDAMN,UACE,UACA,0CAIF,iBACE,UACA,YACA,aACA,cACA,sDACA,2CACA,CADA,kCACA,8BACA,CADA,qBACA,0BACA,CADA,iBACA,WACA,oDAGA,YACE,aACA,kEAKJ,wBV6Ve,oDU3Vb,CV2Va,2CU3Vb,C","file":"assets/stylesheets/main.15aa0b43.min.css","sourcesContent":["html{box-sizing:border-box;text-size-adjust:none}*,*::before,*::after{box-sizing:inherit}body{margin:0}a,button,label,input{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{display:block;box-sizing:content-box;height:.05rem;padding:0;overflow:visible;border:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:separate;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{margin:0;padding:0;font-size:inherit;background:transparent;border:0}input{border:0;outline:none}:root{--md-default-fg-color: hsla(0, 0%, 0%, 0.87);--md-default-fg-color--light: hsla(0, 0%, 0%, 0.54);--md-default-fg-color--lighter: hsla(0, 0%, 0%, 0.32);--md-default-fg-color--lightest: hsla(0, 0%, 0%, 0.07);--md-default-bg-color: hsla(0, 0%, 100%, 1);--md-default-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-default-bg-color--lighter: hsla(0, 0%, 100%, 0.3);--md-default-bg-color--lightest: hsla(0, 0%, 100%, 0.12);--md-primary-fg-color: hsla(231, 48%, 48%, 1);--md-primary-fg-color--light: hsla(231, 44%, 56%, 1);--md-primary-fg-color--dark: hsla(232, 54%, 41%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-accent-fg-color: hsla(231, 99%, 66%, 1);--md-accent-fg-color--transparent: hsla(231, 99%, 66%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}:root>*{--md-code-fg-color: hsla(200, 18%, 26%, 1);--md-code-bg-color: hsla(0, 0%, 96%, 1);--md-code-hl-color: hsla(60, 100%, 50%, 0.5);--md-code-hl-number-color: hsla(0, 67%, 50%, 1);--md-code-hl-special-color: hsla(340, 83%, 47%, 1);--md-code-hl-function-color: hsla(291, 45%, 50%, 1);--md-code-hl-constant-color: hsla(250, 63%, 60%, 1);--md-code-hl-keyword-color: hsla(219, 54%, 51%, 1);--md-code-hl-string-color: hsla(150, 63%, 30%, 1);--md-code-hl-name-color: var(--md-code-fg-color);--md-code-hl-operator-color: var(--md-default-fg-color--light);--md-code-hl-punctuation-color: var(--md-default-fg-color--light);--md-code-hl-comment-color: var(--md-default-fg-color--light);--md-code-hl-generic-color: var(--md-default-fg-color--light);--md-code-hl-variable-color: var(--md-default-fg-color--light);--md-typeset-color: var(--md-default-fg-color);--md-typeset-a-color: var(--md-primary-fg-color);--md-typeset-mark-color: hsla(60, 100%, 50%, 0.5);--md-typeset-del-color: hsla(6, 90%, 60%, 0.15);--md-typeset-ins-color: hsla(150, 90%, 44%, 0.15);--md-typeset-kbd-color: hsla(0, 0%, 98%, 1);--md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1);--md-typeset-kbd-border-color: hsla(0, 0%, 72%, 1);--md-admonition-fg-color: var(--md-default-fg-color);--md-admonition-bg-color: var(--md-default-bg-color);--md-footer-fg-color: hsla(0, 0%, 100%, 1);--md-footer-fg-color--light: hsla(0, 0%, 100%, 0.7);--md-footer-fg-color--lighter: hsla(0, 0%, 100%, 0.3);--md-footer-bg-color: hsla(0, 0%, 0%, 0.87);--md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.32)}.md-icon svg{display:block;width:1.2rem;height:1.2rem;fill:currentColor}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body,input{color:var(--md-typeset-color);font-feature-settings:\"kern\",\"liga\";font-family:-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif}code,pre,kbd{color:var(--md-typeset-color);font-feature-settings:\"kern\";font-family:SFMono-Regular,Consolas,Menlo,monospace}:root{--md-typeset-table--ascending: svg-load(\"@mdi/svg/svg/arrow-down.svg\");--md-typeset-table--descending: svg-load(\"@mdi/svg/svg/arrow-up.svg\")}.md-typeset{font-size:.8rem;line-height:1.6;color-adjust:exact}@media print{.md-typeset{font-size:.68rem}}.md-typeset p,.md-typeset ul,.md-typeset ol,.md-typeset dl,.md-typeset blockquote{margin:1em 0}.md-typeset h1{margin:0 0 1.25em;color:var(--md-default-fg-color--light);font-weight:300;font-size:2em;line-height:1.3;letter-spacing:-0.01em}.md-typeset h2{margin:1.6em 0 .64em;font-weight:300;font-size:1.5625em;line-height:1.4;letter-spacing:-0.01em}.md-typeset h3{margin:1.6em 0 .8em;font-weight:400;font-size:1.25em;line-height:1.5;letter-spacing:-0.01em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{margin:1em 0;font-weight:700;letter-spacing:-0.01em}.md-typeset h5,.md-typeset h6{margin:1.25em 0;color:var(--md-default-fg-color--light);font-weight:700;font-size:.8em;letter-spacing:-0.01em}.md-typeset h5{text-transform:uppercase}.md-typeset hr{margin:1.5em 0;border-bottom:.05rem solid var(--md-default-fg-color--lightest)}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a::before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset code,.md-typeset pre,.md-typeset kbd{color:var(--md-code-fg-color);direction:ltr}@media print{.md-typeset code,.md-typeset pre,.md-typeset kbd{white-space:pre-wrap}}.md-typeset code{padding:0 .2941176471em;font-size:.85em;word-break:break-word;background-color:var(--md-code-bg-color);border-radius:.1rem;box-decoration-break:clone}.md-typeset code:not(.focus-visible){outline:none;-webkit-tap-highlight-color:transparent}.md-typeset h1 code,.md-typeset h2 code,.md-typeset h3 code,.md-typeset h4 code,.md-typeset h5 code,.md-typeset h6 code{margin:initial;padding:initial;background-color:transparent;box-shadow:none}.md-typeset a>code{color:currentColor}.md-typeset pre{position:relative;margin:1em 0;line-height:1.4}.md-typeset pre>code{display:block;margin:0;padding:.7720588235em 1.1764705882em;overflow:auto;word-break:normal;box-shadow:none;box-decoration-break:slice;touch-action:auto;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-typeset pre>code::-webkit-scrollbar{width:.2rem;height:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width: 44.9375em){.md-typeset>pre{margin:1em -0.8rem}.md-typeset>pre code{border-radius:0}}.md-typeset kbd{display:inline-block;padding:0 .6666666667em;color:var(--md-default-fg-color);font-size:.75em;vertical-align:text-top;word-break:break-word;background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -0.1rem .2rem var(--md-typeset-kbd-accent-color) inset}.md-typeset mark{color:inherit;word-break:break-word;background-color:var(--md-typeset-mark-color);box-decoration-break:clone}.md-typeset abbr{text-decoration:none;border-bottom:.05rem dotted var(--md-default-fg-color--light);cursor:help}@media(hover: none){.md-typeset abbr{position:relative}.md-typeset abbr[title]:focus::after,.md-typeset abbr[title]:hover::after{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);position:absolute;left:0;display:inline-block;width:auto;min-width:max-content;max-width:80%;margin-top:2em;padding:.2rem .3rem;color:var(--md-default-bg-color);font-size:.7rem;background-color:var(--md-default-fg-color);border-radius:.1rem;content:attr(title)}}.md-typeset small{opacity:.75}.md-typeset sup,.md-typeset sub{margin-left:.078125em}[dir=rtl] .md-typeset sup,[dir=rtl] .md-typeset sub{margin-right:.078125em;margin-left:initial}.md-typeset blockquote{padding-left:.6rem;color:var(--md-default-fg-color--light);border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{padding-right:.6rem;padding-left:initial;border-right:.2rem solid var(--md-default-fg-color--lighter);border-left:initial}.md-typeset ul{list-style-type:disc}.md-typeset ul,.md-typeset ol{margin-left:.625em;padding:0}[dir=rtl] .md-typeset ul,[dir=rtl] .md-typeset ol{margin-right:.625em;margin-left:initial}.md-typeset ul ol,.md-typeset ol ol{list-style-type:lower-alpha}.md-typeset ul ol ol,.md-typeset ol ol ol{list-style-type:lower-roman}.md-typeset ul li,.md-typeset ol li{margin-bottom:.5em;margin-left:1.25em}[dir=rtl] .md-typeset ul li,[dir=rtl] .md-typeset ol li{margin-right:1.25em;margin-left:initial}.md-typeset ul li p,.md-typeset ul li blockquote,.md-typeset ol li p,.md-typeset ol li blockquote{margin:.5em 0}.md-typeset ul li:last-child,.md-typeset ol li:last-child{margin-bottom:0}.md-typeset ul li ul,.md-typeset ul li ol,.md-typeset ol li ul,.md-typeset ol li ol{margin:.5em 0 .5em .625em}[dir=rtl] .md-typeset ul li ul,[dir=rtl] .md-typeset ul li ol,[dir=rtl] .md-typeset ol li ul,[dir=rtl] .md-typeset ol li ol{margin-right:.625em;margin-left:initial}.md-typeset dd{margin:1em 0 1.5em 1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em;margin-left:initial}.md-typeset img,.md-typeset svg{max-width:100%;height:auto}.md-typeset img[align=left],.md-typeset svg[align=left]{margin:1em;margin-left:0}.md-typeset img[align=right],.md-typeset svg[align=right]{margin:1em;margin-right:0}.md-typeset img[align]:only-child,.md-typeset svg[align]:only-child{margin-top:0}.md-typeset figure{width:fit-content;max-width:100%;margin:0 auto;text-align:center}.md-typeset figure img{display:block}.md-typeset figcaption{max-width:24rem;margin:1em auto 2em;font-style:italic}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){display:inline-block;max-width:100%;overflow:auto;font-size:.64rem;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .05rem rgba(0,0,0,.1);touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) th>*:first-child,.md-typeset table:not([class]) td>*:first-child{margin-top:0}.md-typeset table:not([class]) th>*:last-child,.md-typeset table:not([class]) td>*:last-child{margin-bottom:0}.md-typeset table:not([class]) th:not([align]),.md-typeset table:not([class]) td:not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) th:not([align]),[dir=rtl] .md-typeset table:not([class]) td:not([align]){text-align:right}.md-typeset table:not([class]) th{min-width:5rem;padding:.9375em 1.25em;color:var(--md-default-bg-color);vertical-align:top;background-color:var(--md-default-fg-color--light)}.md-typeset table:not([class]) th a{color:inherit}.md-typeset table:not([class]) td{padding:.9375em 1.25em;vertical-align:top;border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-typeset table:not([class]) tr{transition:background-color 125ms}.md-typeset table:not([class]) tr:hover{background-color:rgba(0,0,0,.035);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) tr:first-child td{border-top:0}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}.md-typeset table th[role=columnheader]::after{display:inline-block;width:1.2em;height:1.2em;margin-left:.5em;vertical-align:sub;mask-repeat:no-repeat;mask-size:contain;content:\"\"}.md-typeset table th[role=columnheader][aria-sort=ascending]::after{background-color:currentColor;mask-image:var(--md-typeset-table--ascending)}.md-typeset table th[role=columnheader][aria-sort=descending]::after{background-color:currentColor;mask-image:var(--md-typeset-table--descending)}.md-typeset__scrollwrap{margin:1em -0.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;width:100%;margin:0;overflow:hidden}html{height:100%;overflow-x:hidden;font-size:125%}@media screen and (min-width: 100em){html{font-size:137.5%}}@media screen and (min-width: 125em){html{font-size:150%}}body{position:relative;display:flex;flex-direction:column;width:100%;min-height:100%;font-size:.5rem;background-color:var(--md-default-bg-color)}@media print{body{display:block}}@media screen and (max-width: 59.9375em){body[data-md-state=lock]{position:fixed}}.md-grid{max-width:61rem;margin-right:auto;margin-left:auto}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.md-toggle{display:none}.md-skip{position:fixed;z-index:-1;margin:.5rem;padding:.3rem .5rem;color:var(--md-default-bg-color);font-size:.64rem;background-color:var(--md-default-fg-color);border-radius:.1rem;transform:translateY(0.4rem);opacity:0}.md-skip:focus{z-index:10;transform:translateY(0);opacity:1;transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),opacity 175ms 75ms}@page{margin:25mm}.md-announce{overflow:auto;background-color:var(--md-footer-bg-color)}@media print{.md-announce{display:none}}.md-announce__inner{margin:.6rem auto;padding:0 .8rem;color:var(--md-footer-fg-color);font-size:.7rem}.md-typeset .md-button{display:inline-block;padding:.625em 2em;color:var(--md-primary-fg-color);font-weight:700;border:.1rem solid currentColor;border-radius:.1rem;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color)}.md-typeset .md-button:focus,.md-typeset .md-button:hover{color:var(--md-accent-bg-color);background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color)}:root{--md-clipboard-icon: svg-load(\"@mdi/svg/svg/content-copy.svg\")}.md-clipboard{position:absolute;top:.5em;right:.5em;z-index:1;width:1.5em;height:1.5em;color:var(--md-default-fg-color--lightest);border-radius:.1rem;cursor:pointer;transition:color 250ms}@media print{.md-clipboard{display:none}}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:focus,.md-clipboard:hover{color:var(--md-accent-fg-color)}.md-clipboard::after{display:block;width:1.125em;height:1.125em;margin:0 auto;background-color:currentColor;mask-image:var(--md-clipboard-icon);mask-repeat:no-repeat;mask-size:contain;content:\"\"}.md-content{flex-grow:1;overflow:hidden;scroll-padding-top:51.2rem}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width: 76.25em){.md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem;margin-left:.8rem}.md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-right:.8rem;margin-left:1.2rem}}.md-content__inner::before{display:block;height:.4rem;content:\"\"}.md-content__inner>:last-child{margin-bottom:0}.md-content__button{float:right;margin:.4rem 0;margin-left:.4rem;padding:0}@media print{.md-content__button{display:none}}[dir=rtl] .md-content__button{float:left;margin-right:.4rem;margin-left:initial}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}.md-dialog{box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2);position:fixed;right:.8rem;bottom:.8rem;left:initial;z-index:2;display:block;min-width:11.1rem;padding:.4rem .6rem;color:var(--md-default-bg-color);font-size:.7rem;background-color:var(--md-default-fg-color);border:none;border-radius:.1rem;transform:translateY(100%);opacity:0;transition:transform 0ms 400ms,opacity 400ms}@media print{.md-dialog{display:none}}[dir=rtl] .md-dialog{right:initial;left:.8rem}.md-dialog[data-md-state=open]{transform:translateY(0);opacity:1;transition:transform 400ms cubic-bezier(0.075, 0.85, 0.175, 1),opacity 400ms}.md-header{position:sticky;top:0;right:0;left:0;z-index:2;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem rgba(0,0,0,0),0 .2rem .4rem rgba(0,0,0,0);transition:color 250ms,background-color 250ms}@media print{.md-header{display:none}}.md-header[data-md-state=shadow]{box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2);transition:transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1),color 250ms,background-color 250ms,box-shadow 250ms}.md-header[data-md-state=hidden]{transform:translateY(-100%);transition:transform 250ms cubic-bezier(0.8, 0, 0.6, 1),color 250ms,background-color 250ms,box-shadow 250ms}.md-header-nav{display:flex;align-items:center;padding:0 .2rem}.md-header-nav__button{position:relative;z-index:1;display:inline-block;margin:.2rem;padding:.4rem;color:currentColor;vertical-align:middle;cursor:pointer;transition:opacity 250ms}.md-header-nav__button:focus,.md-header-nav__button:hover{opacity:.7}.md-header-nav__button:not(.focus-visible){outline:none}.md-header-nav__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width: 76.1875em){.md-header-nav__button.md-logo{display:none}}.md-header-nav__button.md-logo img,.md-header-nav__button.md-logo svg{display:block;width:1.2rem;height:1.2rem;fill:currentColor}@media screen and (min-width: 60em){.md-header-nav__button[for=__search]{display:none}}.no-js .md-header-nav__button[for=__search]{display:none}[dir=rtl] .md-header-nav__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width: 76.25em){.md-header-nav__button[for=__drawer]{display:none}}.md-header-nav__topic{position:absolute;display:flex;max-width:100%;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms}.md-header-nav__topic+.md-header-nav__topic{z-index:-1;transform:translateX(1.25rem);opacity:0;transition:transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),opacity 150ms;pointer-events:none}[dir=rtl] .md-header-nav__topic+.md-header-nav__topic{transform:translateX(-1.25rem)}.md-header-nav__title{flex-grow:1;height:2.4rem;margin-right:.4rem;margin-left:1rem;font-size:.9rem;line-height:2.4rem}.md-header-nav__title[data-md-state=active] .md-header-nav__topic{z-index:-1;transform:translateX(-1.25rem);opacity:0;transition:transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),opacity 150ms;pointer-events:none}[dir=rtl] .md-header-nav__title[data-md-state=active] .md-header-nav__topic{transform:translateX(1.25rem)}.md-header-nav__title[data-md-state=active] .md-header-nav__topic+.md-header-nav__topic{z-index:0;transform:translateX(0);opacity:1;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms;pointer-events:initial}.md-header-nav__title>.md-header-nav__ellipsis{position:relative;width:100%;height:100%}.md-header-nav__source{display:none}@media screen and (min-width: 60em){.md-header-nav__source{display:block;width:11.7rem;max-width:11.7rem;margin-left:1rem}[dir=rtl] .md-header-nav__source{margin-right:1rem;margin-left:initial}}@media screen and (min-width: 76.25em){.md-header-nav__source{margin-left:1.4rem}[dir=rtl] .md-header-nav__source{margin-right:1.4rem}}.md-footer{color:var(--md-footer-fg-color);background-color:var(--md-footer-bg-color)}@media print{.md-footer{display:none}}.md-footer-nav__inner{padding:.2rem;overflow:auto}.md-footer-nav__link{display:flex;padding-top:1.4rem;padding-bottom:.4rem;transition:opacity 250ms}@media screen and (min-width: 45em){.md-footer-nav__link{width:50%}}.md-footer-nav__link:focus,.md-footer-nav__link:hover{opacity:.7}.md-footer-nav__link--prev{float:left}@media screen and (max-width: 44.9375em){.md-footer-nav__link--prev{width:25%}.md-footer-nav__link--prev .md-footer-nav__title{display:none}}[dir=rtl] .md-footer-nav__link--prev{float:right}[dir=rtl] .md-footer-nav__link--prev svg{transform:scaleX(-1)}.md-footer-nav__link--next{float:right;text-align:right}@media screen and (max-width: 44.9375em){.md-footer-nav__link--next{width:75%}}[dir=rtl] .md-footer-nav__link--next{float:left;text-align:left}[dir=rtl] .md-footer-nav__link--next svg{transform:scaleX(-1)}.md-footer-nav__title{position:relative;flex-grow:1;max-width:calc(100% - 2.4rem);padding:0 1rem;font-size:.9rem;line-height:2.4rem}.md-footer-nav__button{margin:.2rem;padding:.4rem}.md-footer-nav__direction{position:absolute;right:0;left:0;margin-top:-1rem;padding:0 1rem;font-size:.64rem;opacity:.7}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:focus,html .md-footer-meta.md-typeset a:hover{color:var(--md-footer-fg-color)}.md-footer-copyright{width:100%;margin:auto .6rem;padding:.4rem 0;color:var(--md-footer-fg-color--lighter);font-size:.64rem}@media screen and (min-width: 45em){.md-footer-copyright{width:auto}}.md-footer-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-footer-social{margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width: 45em){.md-footer-social{padding:.6rem 0}}.md-footer-social__link{display:inline-block;width:1.6rem;height:1.6rem;text-align:center}.md-footer-social__link::before{line-height:1.9}.md-footer-social__link svg{max-height:.8rem;vertical-align:-25%;fill:currentColor}:root{--md-nav-icon--prev: svg-load(\"@mdi/svg/svg/arrow-left.svg\");--md-nav-icon--next: svg-load(\"@mdi/svg/svg/chevron-right.svg\");--md-toc-icon: svg-load(\"@mdi/svg/svg/table-of-contents.svg\")}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{display:block;padding:0 .6rem;overflow:hidden;font-weight:700;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{width:auto;height:100%}.md-nav__title .md-nav__button.md-logo img,.md-nav__title .md-nav__button.md-logo svg{display:block;width:2.4rem;height:2.4rem;fill:currentColor}.md-nav__list{margin:0;padding:0;list-style:none}.md-nav__item{padding:0 .6rem}.md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-right:.6rem;padding-left:0}.md-nav__link{display:block;margin-top:.625em;overflow:hidden;text-overflow:ellipsis;cursor:pointer;transition:color 125ms;scroll-snap-align:start}.md-nav__link[data-md-state=blur]{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active{color:var(--md-typeset-a-color)}.md-nav__item--nested>.md-nav__link{color:inherit}.md-nav__link:focus,.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon::after{display:block;width:100%;height:100%;mask-image:var(--md-toc-icon);background-color:currentColor}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__source{display:none}@media screen and (max-width: 76.1875em){.md-nav--primary,.md-nav--primary .md-nav{position:absolute;top:0;right:0;left:0;z-index:1;display:flex;flex-direction:column;height:100%;background-color:var(--md-default-bg-color)}.md-nav--primary .md-nav__title,.md-nav--primary .md-nav__item{font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{position:relative;height:5.6rem;padding:3rem .8rem .2rem;color:var(--md-default-fg-color--light);font-weight:400;line-height:2.4rem;white-space:nowrap;background-color:var(--md-default-fg-color--lightest);cursor:pointer}.md-nav--primary .md-nav__title .md-nav__icon{position:absolute;top:.4rem;left:.4rem;display:block;width:1.2rem;height:1.2rem;margin:.2rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem;left:initial}.md-nav--primary .md-nav__title .md-nav__icon::after{display:block;width:100%;height:100%;background-color:currentColor;mask-image:var(--md-nav-icon--prev);mask-repeat:no-repeat;mask-size:contain;content:\"\"}.md-nav--primary .md-nav__title~.md-nav__list{overflow-y:auto;background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color)}.md-nav--primary .md-nav__title .md-logo{position:absolute;top:.2rem;left:.2rem;display:block;margin:.2rem;padding:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-logo{right:.2rem;left:initial}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{padding:0;border-top:.05rem solid var(--md-default-fg-color--lightest)}.md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:2.4rem}[dir=rtl] .md-nav--primary .md-nav__item--nested>.md-nav__link{padding-right:.8rem;padding-left:2.4rem}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:focus,.md-nav--primary .md-nav__item--active>.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{position:relative;margin-top:0;padding:.6rem .8rem}.md-nav--primary .md-nav__link .md-nav__icon{position:absolute;top:50%;right:.6rem;width:1.2rem;height:1.2rem;margin-top:-0.6rem;color:inherit;font-size:1.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{right:initial;left:.6rem}.md-nav--primary .md-nav__link .md-nav__icon::after{display:block;width:100%;height:100%;background-color:currentColor;mask-image:var(--md-nav-icon--next);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-nav--primary .md-nav__icon::after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav__link{position:static}.md-nav--primary .md-nav--secondary .md-nav{position:static;background-color:transparent}.md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem;padding-left:initial}.md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem;padding-left:initial}.md-nav--secondary{background-color:transparent}.md-nav__toggle~.md-nav{display:flex;transform:translateX(100%);opacity:0;transition:transform 250ms cubic-bezier(0.8, 0, 0.6, 1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{transform:translateX(0);opacity:1;transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{backface-visibility:hidden}}@media screen and (max-width: 59.9375em){.md-nav--primary .md-nav__link[for=__toc]{display:block;padding-right:2.4rem}[dir=rtl] .md-nav--primary .md-nav__link[for=__toc]{padding-right:.8rem;padding-left:2.4rem}.md-nav--primary .md-nav__link[for=__toc] .md-icon::after{content:\"\"}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{display:block;padding:0 .2rem;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color--dark)}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-nav--integrated .md-nav__link[for=__toc]{display:block;padding-right:2.4rem;scroll-snap-align:initial}[dir=rtl] .md-nav--integrated .md-nav__link[for=__toc]{padding-right:.8rem;padding-left:2.4rem}.md-nav--integrated .md-nav__link[for=__toc] .md-icon::after{content:\"\"}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width: 60em){.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}}@media screen and (min-width: 76.25em){.md-nav{transition:max-height 250ms cubic-bezier(0.86, 0, 0.07, 1)}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon{display:none}.md-nav__toggle~.md-nav{display:none}.md-nav__toggle:checked~.md-nav,.md-nav__toggle:indeterminate~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{display:none}.md-nav__item--section>.md-nav{display:block}.md-nav__item--section>.md-nav>.md-nav__title{display:block;padding:0;pointer-events:none;scroll-snap-align:start}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{float:right;width:.9rem;height:.9rem;transition:transform 250ms}[dir=rtl] .md-nav__icon{float:left;transform:rotate(180deg)}.md-nav__icon::after{display:inline-block;width:100%;height:100%;vertical-align:-0.1rem;background-color:currentColor;mask-image:var(--md-nav-icon--next);mask-repeat:no-repeat;mask-size:contain;content:\"\"}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon,.md-nav__item--nested .md-nav__toggle:indeterminate~.md-nav__link .md-nav__icon{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item--nested,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block;padding:0}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav>.md-nav__title{display:block;padding:0 .6rem;pointer-events:none;scroll-snap-align:start}.md-nav--lifted>.md-nav__list>.md-nav__item>.md-nav__item{padding-right:.6rem}.md-nav--lifted .md-nav[data-md-level=\"1\"]{display:block}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:block;margin-bottom:1.25em;border-left:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav>.md-nav__title{display:none}}:root{--md-search-result-icon: svg-load(\"@mdi/svg/svg/file-search-outline.svg\")}.md-search{position:relative}@media screen and (min-width: 60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{z-index:1;opacity:0}@media screen and (max-width: 59.9375em){.md-search__overlay{position:absolute;top:.2rem;left:-2.2rem;width:2rem;height:2rem;overflow:hidden;background-color:var(--md-default-bg-color);border-radius:1rem;transform-origin:center;transition:transform 300ms 100ms,opacity 200ms 200ms;pointer-events:none}[dir=rtl] .md-search__overlay{right:-2.2rem;left:initial}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform 400ms,opacity 100ms}}@media screen and (min-width: 60em){.md-search__overlay{position:fixed;top:0;left:0;width:0;height:0;background-color:rgba(0,0,0,.54);cursor:pointer;transition:width 0ms 250ms,height 0ms 250ms,opacity 250ms}[dir=rtl] .md-search__overlay{right:0;left:initial}[data-md-toggle=search]:checked~.md-header .md-search__overlay{width:100%;height:100%;opacity:1;transition:width 0ms,height 0ms,opacity 250ms}}@media screen and (max-width: 29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width: 30em)and (max-width: 44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width: 45em)and (max-width: 59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{backface-visibility:hidden}@media screen and (max-width: 59.9375em){.md-search__inner{position:fixed;top:0;left:100%;z-index:2;width:100%;height:100%;transform:translateX(5%);opacity:0;transition:right 0ms 300ms,left 0ms 300ms,transform 150ms 150ms cubic-bezier(0.4, 0, 0.2, 1),opacity 150ms 150ms}[data-md-toggle=search]:checked~.md-header .md-search__inner{left:0;transform:translateX(0);opacity:1;transition:right 0ms 0ms,left 0ms 0ms,transform 150ms 150ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms 150ms}[dir=rtl] [data-md-toggle=search]:checked~.md-header .md-search__inner{right:0;left:initial}html [dir=rtl] .md-search__inner{right:100%;left:initial;transform:translateX(-5%)}}@media screen and (min-width: 60em){.md-search__inner{position:relative;float:right;width:11.7rem;padding:.1rem 0;transition:width 250ms cubic-bezier(0.1, 0.7, 0.1, 1)}[dir=rtl] .md-search__inner{float:left}}@media screen and (min-width: 60em)and (max-width: 76.1875em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width: 76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{position:relative}@media screen and (min-width: 60em){.md-search__form{border-radius:.1rem}}.md-search__input{position:relative;z-index:2;padding:0 2.2rem 0 3.6rem;text-overflow:ellipsis;background-color:var(--md-default-bg-color);transition:color 250ms,background-color 250ms}[dir=rtl] .md-search__input{padding:0 3.6rem 0 2.2rem}.md-search__input::placeholder{transition:color 250ms}.md-search__input~.md-search__icon,.md-search__input::placeholder{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width: 59.9375em){.md-search__input{width:100%;height:2.4rem;font-size:.9rem}}@media screen and (min-width: 60em){.md-search__input{width:100%;height:1.8rem;padding-left:2.2rem;color:inherit;font-size:.8rem;background-color:rgba(0,0,0,.26);border-radius:.1rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input:hover{background-color:rgba(255,255,255,.12)}[data-md-toggle=search]:checked~.md-header .md-search__input{color:var(--md-default-fg-color);text-overflow:clip;background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon,[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:var(--md-default-fg-color--light)}}.md-search__icon{position:absolute;z-index:2;width:1.2rem;height:1.2rem;cursor:pointer;transition:color 250ms,opacity 250ms}.md-search__icon:hover{opacity:.7}.md-search__icon[for=__search]{top:.3rem;left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem;left:initial}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width: 59.9375em){.md-search__icon[for=__search]{top:.6rem;left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem;left:initial}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width: 60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}.md-search__icon[type=reset]{top:.3rem;right:.5rem;transform:scale(0.75);opacity:0;transition:transform 150ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 150ms;pointer-events:none}[dir=rtl] .md-search__icon[type=reset]{right:initial;left:.5rem}@media screen and (max-width: 59.9375em){.md-search__icon[type=reset]{top:.6rem;right:.8rem}[dir=rtl] .md-search__icon[type=reset]{right:initial;left:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]{transform:scale(1);opacity:1;pointer-events:initial}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__icon[type=reset]:hover{opacity:.7}.md-search__output{position:absolute;z-index:1;width:100%;overflow:hidden;border-radius:0 0 .1rem .1rem}@media screen and (max-width: 59.9375em){.md-search__output{top:2.4rem;bottom:0}}@media screen and (min-width: 60em){.md-search__output{top:1.9rem;opacity:0;transition:opacity 400ms}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12),0 3px 5px -1px rgba(0,0,0,.4);opacity:1}}.md-search__scrollwrap{height:100%;overflow-y:auto;background-color:var(--md-default-bg-color);backface-visibility:hidden;scroll-snap-type:y mandatory;touch-action:pan-y}@media(max-resolution: 1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width: 76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width: 60em){.md-search__scrollwrap{max-height:0;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-search__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{padding:0 .8rem;color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;background-color:var(--md-default-fg-color--lightest);scroll-snap-align:start}@media screen and (min-width: 60em){.md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem;padding-left:initial}}.md-search-result__list{margin:0;padding:0;list-style:none}.md-search-result__item{box-shadow:0 -0.05rem 0 var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;transition:background-color 250ms;scroll-snap-align:start}.md-search-result__link:focus,.md-search-result__link:hover{background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more summary{display:block;padding:.75em .8rem;color:var(--md-typeset-a-color);font-size:.64rem;outline:0;cursor:pointer;transition:color 250ms,background-color 250ms;scroll-snap-align:start}@media screen and (min-width: 60em){.md-search-result__more summary{padding-left:2.2rem}[dir=rtl] .md-search-result__more summary{padding-right:2.2rem;padding-left:.8rem}}.md-search-result__more summary:focus,.md-search-result__more summary:hover{color:var(--md-accent-fg-color);background-color:var(--md-accent-fg-color--transparent)}.md-search-result__more summary::-webkit-details-marker{display:none}.md-search-result__more summary~*>*{opacity:.65}.md-search-result__article{position:relative;padding:0 .8rem;overflow:hidden}@media screen and (min-width: 60em){.md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem;padding-left:.8rem}}.md-search-result__article--document .md-search-result__title{margin:.55rem 0;font-weight:400;font-size:.8rem;line-height:1.4}.md-search-result__icon{position:absolute;left:0;width:1.2rem;height:1.2rem;margin:.5rem;color:var(--md-default-fg-color--light)}@media screen and (max-width: 59.9375em){.md-search-result__icon{display:none}}.md-search-result__icon::after{display:inline-block;width:100%;height:100%;background-color:currentColor;mask-image:var(--md-search-result-icon);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-search-result__icon{right:0;left:initial}[dir=rtl] .md-search-result__icon::after{transform:scaleX(-1)}.md-search-result__title{margin:.5em 0;font-weight:700;font-size:.64rem;line-height:1.6}.md-search-result__teaser{display:-webkit-box;max-height:2rem;margin:.5em 0;overflow:hidden;color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.6;text-overflow:ellipsis;-webkit-box-orient:vertical;-webkit-line-clamp:2}@media screen and (max-width: 44.9375em){.md-search-result__teaser{max-height:3rem;-webkit-line-clamp:3}}@media screen and (min-width: 60em)and (max-width: 76.1875em){.md-search-result__teaser{max-height:3rem;-webkit-line-clamp:3}}.md-search-result__teaser mark{text-decoration:underline;background-color:transparent}.md-search-result__terms{margin:.5em 0;font-size:.64rem;font-style:italic}.md-search-result mark{color:var(--md-accent-fg-color);background-color:transparent}.md-sidebar{position:sticky;top:2.4rem;flex-shrink:0;align-self:flex-start;width:12.1rem;height:0;padding:1.2rem 0}@media print{.md-sidebar{display:none}}@media screen and (max-width: 76.1875em){.md-sidebar--primary{position:fixed;top:0;left:-12.1rem;z-index:3;display:block;width:12.1rem;height:100%;background-color:var(--md-default-bg-color);transform:translateX(0);transition:transform 250ms cubic-bezier(0.4, 0, 0.2, 1),box-shadow 250ms}[dir=rtl] .md-sidebar--primary{right:-12.1rem;left:initial}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12),0 5px 5px -3px rgba(0,0,0,.4);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{position:absolute;top:0;right:0;bottom:0;left:0;margin:0;scroll-snap-type:none;overflow:hidden}}@media screen and (min-width: 76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width: 60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{margin:0 .2rem;overflow-y:auto;backface-visibility:hidden;scrollbar-width:thin;scrollbar-color:var(--md-default-fg-color--lighter) transparent}.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) transparent}.md-sidebar__scrollwrap::-webkit-scrollbar{width:.2rem;height:.2rem}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@media screen and (max-width: 76.1875em){.md-overlay{position:fixed;top:0;z-index:3;width:0;height:0;background-color:rgba(0,0,0,.54);opacity:0;transition:width 0ms 250ms,height 0ms 250ms,opacity 250ms}[data-md-toggle=drawer]:checked~.md-overlay{width:100%;height:100%;opacity:1;transition:width 0ms,height 0ms,opacity 250ms}}@keyframes md-source__facts--done{0%{height:0}100%{height:.65rem}}@keyframes md-source__fact--done{0%{transform:translateY(100%);opacity:0}50%{opacity:0}100%{transform:translateY(0%);opacity:1}}.md-source{display:block;font-size:.65rem;line-height:1.2;white-space:nowrap;backface-visibility:hidden;transition:opacity 250ms}.md-source:focus,.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;width:2.4rem;height:2.4rem;vertical-align:middle}.md-source__icon svg{margin-top:.6rem;margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem;margin-left:initial}.md-source__icon+.md-source__repository{margin-left:-2rem;padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem;margin-left:initial;padding-right:2rem;padding-left:initial}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);margin-left:.6rem;overflow:hidden;font-weight:700;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{margin:0;padding:0;overflow:hidden;font-weight:700;font-size:.55rem;list-style-type:none;opacity:.75}[data-md-state=done] .md-source__facts{animation:md-source__facts--done 250ms ease-in}.md-source__fact{float:left}[dir=rtl] .md-source__fact{float:right}[data-md-state=done] .md-source__fact{animation:md-source__fact--done 400ms ease-out}.md-source__fact::before{margin:0 .1rem;content:\"·\"}.md-source__fact:first-child::before{display:none}.md-tabs{width:100%;overflow:auto;color:var(--md-primary-bg-color);background-color:var(--md-primary-fg-color);transition:background-color 250ms}@media print{.md-tabs{display:none}}@media screen and (max-width: 76.1875em){.md-tabs{display:none}}.md-tabs[data-md-state=hidden]{pointer-events:none}.md-tabs__list{margin:0;margin-left:.2rem;padding:0;white-space:nowrap;list-style:none;contain:content}[dir=rtl] .md-tabs__list{margin-right:.2rem;margin-left:initial}.md-tabs__item{display:inline-block;height:2.4rem;padding-right:.6rem;padding-left:.6rem}.md-tabs__link{display:block;margin-top:.8rem;font-size:.7rem;backface-visibility:hidden;opacity:.7;transition:transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),opacity 250ms}.md-tabs__link--active,.md-tabs__link:focus,.md-tabs__link:hover{color:inherit;opacity:1}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:100ms}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:120ms}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:140ms}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:160ms}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:180ms}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:200ms}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:220ms}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:240ms}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:260ms}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:280ms}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:300ms}.md-tabs[data-md-state=hidden] .md-tabs__link{transform:translateY(50%);opacity:0;transition:transform 0ms 100ms,opacity 100ms}:root{--md-admonition-icon--note: svg-load( \"@mdi/svg/svg/pencil.svg\" );--md-admonition-icon--abstract: svg-load( \"@mdi/svg/svg/text-subject.svg\" );--md-admonition-icon--info: svg-load( \"@mdi/svg/svg/information.svg\" );--md-admonition-icon--tip: svg-load( \"@mdi/svg/svg/fire.svg\" );--md-admonition-icon--success: svg-load( \"@mdi/svg/svg/check-circle.svg\" );--md-admonition-icon--question: svg-load( \"@mdi/svg/svg/help-circle.svg\" );--md-admonition-icon--warning: svg-load( \"@mdi/svg/svg/alert.svg\" );--md-admonition-icon--failure: svg-load( \"@mdi/svg/svg/close-circle.svg\" );--md-admonition-icon--danger: svg-load( \"@mdi/svg/svg/flash-circle.svg\" );--md-admonition-icon--bug: svg-load( \"@mdi/svg/svg/bug.svg\" );--md-admonition-icon--example: svg-load( \"@mdi/svg/svg/format-list-numbered.svg\" );--md-admonition-icon--quote: svg-load( \"@mdi/svg/svg/format-quote-close.svg\" )}.md-typeset .admonition,.md-typeset details{margin:1.5625em 0;padding:0 .6rem;overflow:hidden;color:var(--md-admonition-fg-color);font-size:.64rem;page-break-inside:avoid;background-color:var(--md-admonition-bg-color);border-left:.2rem solid #448aff;border-radius:.1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 .025rem .05rem rgba(0,0,0,.05)}@media print{.md-typeset .admonition,.md-typeset details{box-shadow:none}}[dir=rtl] .md-typeset .admonition,[dir=rtl] .md-typeset details{border-right:.2rem solid #448aff;border-left:none}.md-typeset .admonition .admonition,.md-typeset details .admonition,.md-typeset .admonition details,.md-typeset details details{margin:1em 0}.md-typeset .admonition .md-typeset__scrollwrap,.md-typeset details .md-typeset__scrollwrap{margin:1em -0.6rem}.md-typeset .admonition .md-typeset__table,.md-typeset details .md-typeset__table{padding:0 .6rem}.md-typeset .admonition>.tabbed-set:only-child,.md-typeset details>.tabbed-set:only-child{margin-top:0}html .md-typeset .admonition>:last-child,html .md-typeset details>:last-child{margin-bottom:.6rem}.md-typeset .admonition-title,.md-typeset summary{position:relative;margin:0 -0.6rem 0 -0.8rem;padding:.4rem .6rem .4rem 2rem;font-weight:700;background-color:rgba(68,138,255,.1);border-left:.2rem solid #448aff}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{margin:0 -0.8rem 0 -0.6rem;padding:.4rem 2rem .4rem .6rem;border-right:.2rem solid #448aff;border-left:none}html .md-typeset .admonition-title:last-child,html .md-typeset summary:last-child{margin-bottom:0}.md-typeset .admonition-title::before,.md-typeset summary::before{position:absolute;left:.6rem;width:1rem;height:1rem;background-color:#448aff;mask-image:var(--md-admonition-icon--note);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-typeset .admonition-title::before,[dir=rtl] .md-typeset summary::before{right:.6rem;left:initial}.md-typeset .admonition-title code,.md-typeset summary code{margin:initial;padding:initial;color:currentColor;background-color:transparent;border-radius:initial;box-shadow:none}.md-typeset .admonition-title+.tabbed-set:last-child,.md-typeset summary+.tabbed-set:last-child{margin-top:0}.md-typeset .admonition.note,.md-typeset details.note{border-color:#448aff}.md-typeset .note>.admonition-title,.md-typeset .note>summary{background-color:rgba(68,138,255,.1);border-color:#448aff}.md-typeset .note>.admonition-title::before,.md-typeset .note>summary::before{background-color:#448aff;mask-image:var(--md-admonition-icon--note);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.abstract,.md-typeset details.abstract,.md-typeset .admonition.tldr,.md-typeset details.tldr,.md-typeset .admonition.summary,.md-typeset details.summary{border-color:#00b0ff}.md-typeset .abstract>.admonition-title,.md-typeset .abstract>summary,.md-typeset .tldr>.admonition-title,.md-typeset .tldr>summary,.md-typeset .summary>.admonition-title,.md-typeset .summary>summary{background-color:rgba(0,176,255,.1);border-color:#00b0ff}.md-typeset .abstract>.admonition-title::before,.md-typeset .abstract>summary::before,.md-typeset .tldr>.admonition-title::before,.md-typeset .tldr>summary::before,.md-typeset .summary>.admonition-title::before,.md-typeset .summary>summary::before{background-color:#00b0ff;mask-image:var(--md-admonition-icon--abstract);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.info,.md-typeset details.info,.md-typeset .admonition.todo,.md-typeset details.todo{border-color:#00b8d4}.md-typeset .info>.admonition-title,.md-typeset .info>summary,.md-typeset .todo>.admonition-title,.md-typeset .todo>summary{background-color:rgba(0,184,212,.1);border-color:#00b8d4}.md-typeset .info>.admonition-title::before,.md-typeset .info>summary::before,.md-typeset .todo>.admonition-title::before,.md-typeset .todo>summary::before{background-color:#00b8d4;mask-image:var(--md-admonition-icon--info);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.tip,.md-typeset details.tip,.md-typeset .admonition.important,.md-typeset details.important,.md-typeset .admonition.hint,.md-typeset details.hint{border-color:#00bfa5}.md-typeset .tip>.admonition-title,.md-typeset .tip>summary,.md-typeset .important>.admonition-title,.md-typeset .important>summary,.md-typeset .hint>.admonition-title,.md-typeset .hint>summary{background-color:rgba(0,191,165,.1);border-color:#00bfa5}.md-typeset .tip>.admonition-title::before,.md-typeset .tip>summary::before,.md-typeset .important>.admonition-title::before,.md-typeset .important>summary::before,.md-typeset .hint>.admonition-title::before,.md-typeset .hint>summary::before{background-color:#00bfa5;mask-image:var(--md-admonition-icon--tip);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.success,.md-typeset details.success,.md-typeset .admonition.done,.md-typeset details.done,.md-typeset .admonition.check,.md-typeset details.check{border-color:#00c853}.md-typeset .success>.admonition-title,.md-typeset .success>summary,.md-typeset .done>.admonition-title,.md-typeset .done>summary,.md-typeset .check>.admonition-title,.md-typeset .check>summary{background-color:rgba(0,200,83,.1);border-color:#00c853}.md-typeset .success>.admonition-title::before,.md-typeset .success>summary::before,.md-typeset .done>.admonition-title::before,.md-typeset .done>summary::before,.md-typeset .check>.admonition-title::before,.md-typeset .check>summary::before{background-color:#00c853;mask-image:var(--md-admonition-icon--success);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.question,.md-typeset details.question,.md-typeset .admonition.faq,.md-typeset details.faq,.md-typeset .admonition.help,.md-typeset details.help{border-color:#64dd17}.md-typeset .question>.admonition-title,.md-typeset .question>summary,.md-typeset .faq>.admonition-title,.md-typeset .faq>summary,.md-typeset .help>.admonition-title,.md-typeset .help>summary{background-color:rgba(100,221,23,.1);border-color:#64dd17}.md-typeset .question>.admonition-title::before,.md-typeset .question>summary::before,.md-typeset .faq>.admonition-title::before,.md-typeset .faq>summary::before,.md-typeset .help>.admonition-title::before,.md-typeset .help>summary::before{background-color:#64dd17;mask-image:var(--md-admonition-icon--question);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.warning,.md-typeset details.warning,.md-typeset .admonition.attention,.md-typeset details.attention,.md-typeset .admonition.caution,.md-typeset details.caution{border-color:#ff9100}.md-typeset .warning>.admonition-title,.md-typeset .warning>summary,.md-typeset .attention>.admonition-title,.md-typeset .attention>summary,.md-typeset .caution>.admonition-title,.md-typeset .caution>summary{background-color:rgba(255,145,0,.1);border-color:#ff9100}.md-typeset .warning>.admonition-title::before,.md-typeset .warning>summary::before,.md-typeset .attention>.admonition-title::before,.md-typeset .attention>summary::before,.md-typeset .caution>.admonition-title::before,.md-typeset .caution>summary::before{background-color:#ff9100;mask-image:var(--md-admonition-icon--warning);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.failure,.md-typeset details.failure,.md-typeset .admonition.missing,.md-typeset details.missing,.md-typeset .admonition.fail,.md-typeset details.fail{border-color:#ff5252}.md-typeset .failure>.admonition-title,.md-typeset .failure>summary,.md-typeset .missing>.admonition-title,.md-typeset .missing>summary,.md-typeset .fail>.admonition-title,.md-typeset .fail>summary{background-color:rgba(255,82,82,.1);border-color:#ff5252}.md-typeset .failure>.admonition-title::before,.md-typeset .failure>summary::before,.md-typeset .missing>.admonition-title::before,.md-typeset .missing>summary::before,.md-typeset .fail>.admonition-title::before,.md-typeset .fail>summary::before{background-color:#ff5252;mask-image:var(--md-admonition-icon--failure);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.danger,.md-typeset details.danger,.md-typeset .admonition.error,.md-typeset details.error{border-color:#ff1744}.md-typeset .danger>.admonition-title,.md-typeset .danger>summary,.md-typeset .error>.admonition-title,.md-typeset .error>summary{background-color:rgba(255,23,68,.1);border-color:#ff1744}.md-typeset .danger>.admonition-title::before,.md-typeset .danger>summary::before,.md-typeset .error>.admonition-title::before,.md-typeset .error>summary::before{background-color:#ff1744;mask-image:var(--md-admonition-icon--danger);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.bug,.md-typeset details.bug{border-color:#f50057}.md-typeset .bug>.admonition-title,.md-typeset .bug>summary{background-color:rgba(245,0,87,.1);border-color:#f50057}.md-typeset .bug>.admonition-title::before,.md-typeset .bug>summary::before{background-color:#f50057;mask-image:var(--md-admonition-icon--bug);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.example,.md-typeset details.example{border-color:#651fff}.md-typeset .example>.admonition-title,.md-typeset .example>summary{background-color:rgba(101,31,255,.1);border-color:#651fff}.md-typeset .example>.admonition-title::before,.md-typeset .example>summary::before{background-color:#651fff;mask-image:var(--md-admonition-icon--example);mask-repeat:no-repeat;mask-size:contain}.md-typeset .admonition.quote,.md-typeset details.quote,.md-typeset .admonition.cite,.md-typeset details.cite{border-color:#9e9e9e}.md-typeset .quote>.admonition-title,.md-typeset .quote>summary,.md-typeset .cite>.admonition-title,.md-typeset .cite>summary{background-color:rgba(158,158,158,.1);border-color:#9e9e9e}.md-typeset .quote>.admonition-title::before,.md-typeset .quote>summary::before,.md-typeset .cite>.admonition-title::before,.md-typeset .cite>summary::before{background-color:#9e9e9e;mask-image:var(--md-admonition-icon--quote);mask-repeat:no-repeat;mask-size:contain}:root{--md-footnotes-icon: svg-load(\"@mdi/svg/svg/keyboard-return.svg\")}.md-typeset [id^=\"fnref:\"]:target{scroll-margin-top:initial;margin-top:-3.4rem;padding-top:3.4rem}.md-typeset [id^=\"fn:\"]:target{scroll-margin-top:initial;margin-top:-3.45rem;padding-top:3.45rem}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}.md-typeset .footnote ol{margin-left:0}.md-typeset .footnote li{transition:color 125ms}.md-typeset .footnote li:target{color:var(--md-default-fg-color)}.md-typeset .footnote li:hover .footnote-backref,.md-typeset .footnote li:target .footnote-backref{transform:translateX(0);opacity:1}.md-typeset .footnote li>:first-child{margin-top:0}.md-typeset .footnote-backref{display:inline-block;color:var(--md-typeset-a-color);font-size:0;vertical-align:text-bottom;transform:translateX(0.25rem);opacity:0;transition:color 250ms,transform 250ms 250ms,opacity 125ms 250ms}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);transform:translateX(0);opacity:1}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-0.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref::before{display:inline-block;width:.8rem;height:.8rem;background-color:currentColor;mask-image:var(--md-footnotes-icon);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-typeset .footnote-backref::before svg{transform:scaleX(-1)}.md-typeset .headerlink{display:inline-block;margin-left:.5rem;color:var(--md-default-fg-color--lighter);opacity:0;transition:color 250ms,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem;margin-left:initial}.md-typeset :hover>.headerlink,.md-typeset :target>.headerlink,.md-typeset .headerlink:focus{opacity:1;transition:color 250ms,opacity 125ms}.md-typeset :target>.headerlink,.md-typeset .headerlink:focus,.md-typeset .headerlink:hover{color:var(--md-accent-fg-color)}.md-typeset :target{scroll-margin-top:3.6rem}.md-typeset h1:target,.md-typeset h2:target,.md-typeset h3:target{scroll-margin-top:initial}.md-typeset h1:target::before,.md-typeset h2:target::before,.md-typeset h3:target::before{display:block;margin-top:-3.4rem;padding-top:3.4rem;content:\"\"}.md-typeset h4:target{scroll-margin-top:initial}.md-typeset h4:target::before{display:block;margin-top:-3.45rem;padding-top:3.45rem;content:\"\"}.md-typeset h5:target,.md-typeset h6:target{scroll-margin-top:initial}.md-typeset h5:target::before,.md-typeset h6:target::before{display:block;margin-top:-3.6rem;padding-top:3.6rem;content:\"\"}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width: 44.9375em){.md-typeset div.arithmatex{margin:0 -0.8rem}}.md-typeset div.arithmatex>*{width:min-content;margin:1em auto !important;padding:0 .8rem;touch-action:auto}.md-typeset del.critic,.md-typeset ins.critic,.md-typeset .critic.comment{box-decoration-break:clone}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment::before{content:\"/* \"}.md-typeset .critic.comment::after{content:\" */\"}.md-typeset .critic.block{display:block;margin:1em 0;padding-right:.8rem;padding-left:.8rem;overflow:auto;box-shadow:none}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon: svg-load(\"@mdi/svg/svg/chevron-right.svg\")}.md-typeset details{display:block;padding-top:0;overflow:visible}.md-typeset details[open]>summary::after{transform:rotate(90deg)}.md-typeset details:not([open]){padding-bottom:0;box-shadow:none}.md-typeset details:not([open])>summary{border-radius:.1rem}.md-typeset details::after{display:table;content:\"\"}.md-typeset summary{display:block;min-height:1rem;padding:.4rem 1.8rem .4rem 2rem;border-top-left-radius:.1rem;border-top-right-radius:.1rem;cursor:pointer}[dir=rtl] .md-typeset summary{padding:.4rem 2.2rem .4rem 1.8rem}.md-typeset summary:not(.focus-visible){outline:none;-webkit-tap-highlight-color:transparent}.md-typeset summary::after{position:absolute;top:.4rem;right:.4rem;width:1rem;height:1rem;background-color:currentColor;mask-image:var(--md-details-icon);mask-repeat:no-repeat;mask-size:contain;transform:rotate(0deg);transition:transform 250ms;content:\"\"}[dir=rtl] .md-typeset summary::after{right:initial;left:.4rem;transform:rotate(180deg)}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset .emojione,.md-typeset .twemoji,.md-typeset .gemoji{display:inline-block;height:1.125em;vertical-align:text-top}.md-typeset .emojione svg,.md-typeset .twemoji svg,.md-typeset .gemoji svg{width:1.125em;max-height:100%;fill:currentColor}.highlight .o,.highlight .ow{color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight .cpf,.highlight .l,.highlight .s,.highlight .sb,.highlight .sc,.highlight .s2,.highlight .si,.highlight .s1,.highlight .ss{color:var(--md-code-hl-string-color)}.highlight .cp,.highlight .se,.highlight .sh,.highlight .sr,.highlight .sx{color:var(--md-code-hl-special-color)}.highlight .m,.highlight .mb,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .il,.highlight .mo{color:var(--md-code-hl-number-color)}.highlight .k,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:var(--md-code-hl-keyword-color)}.highlight .kc,.highlight .n{color:var(--md-code-hl-name-color)}.highlight .no,.highlight .nb,.highlight .bp{color:var(--md-code-hl-constant-color)}.highlight .nc,.highlight .ne,.highlight .nf,.highlight .nn{color:var(--md-code-hl-function-color)}.highlight .nd,.highlight .ni,.highlight .nl,.highlight .nt{color:var(--md-code-hl-keyword-color)}.highlight .c,.highlight .cm,.highlight .c1,.highlight .ch,.highlight .cs,.highlight .sd{color:var(--md-code-hl-comment-color)}.highlight .na,.highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi{color:var(--md-code-hl-variable-color)}.highlight .ge,.highlight .gr,.highlight .gh,.highlight .go,.highlight .gp,.highlight .gs,.highlight .gu,.highlight .gt{color:var(--md-code-hl-generic-color)}.highlight .gd,.highlight .gi{margin:0 -0.125em;padding:0 .125em;border-radius:.1rem}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em;background-color:var(--md-code-hl-color)}.highlight [data-linenos]::before{position:sticky;left:-1.1764705882em;float:left;margin-right:1.1764705882em;margin-left:-1.1764705882em;padding-left:1.1764705882em;color:var(--md-default-fg-color--light);background-color:var(--md-code-bg-color);box-shadow:-0.05rem 0 var(--md-default-fg-color--lightest) inset;content:attr(data-linenos);user-select:none}.highlighttable{display:flow-root;overflow:hidden}.highlighttable tbody,.highlighttable td{display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable .linenos{padding:.7720588235em 1.1764705882em;padding-right:0;font-size:.85em;background-color:var(--md-code-bg-color);user-select:none}.highlighttable .linenodiv{padding-right:.5882352941em;box-shadow:-0.05rem 0 var(--md-default-fg-color--lightest) inset}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .code{flex:1;overflow:hidden}.md-typeset .highlighttable{margin:1em 0;direction:ltr;border-radius:.1rem}.md-typeset .highlighttable code{border-radius:0}@media screen and (max-width: 44.9375em){.md-typeset>.highlight{margin:1em -0.8rem}.md-typeset>.highlight .hll{margin:0 -0.8rem;padding:0 .8rem}.md-typeset>.highlight code{border-radius:0}.md-typeset>.highlighttable{margin:1em -0.8rem;border-radius:0}.md-typeset>.highlighttable .hll{margin:0 -0.8rem;padding:0 .8rem}}.md-typeset .keys kbd::before,.md-typeset .keys kbd::after{position:relative;margin:0;color:inherit;-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial}.md-typeset .keys span{padding:0 .2em;color:var(--md-default-fg-color--light)}.md-typeset .keys .key-alt::before{padding-right:.4em;content:\"⎇\"}.md-typeset .keys .key-left-alt::before{padding-right:.4em;content:\"⎇\"}.md-typeset .keys .key-right-alt::before{padding-right:.4em;content:\"⎇\"}.md-typeset .keys .key-command::before{padding-right:.4em;content:\"⌘\"}.md-typeset .keys .key-left-command::before{padding-right:.4em;content:\"⌘\"}.md-typeset .keys .key-right-command::before{padding-right:.4em;content:\"⌘\"}.md-typeset .keys .key-control::before{padding-right:.4em;content:\"⌃\"}.md-typeset .keys .key-left-control::before{padding-right:.4em;content:\"⌃\"}.md-typeset .keys .key-right-control::before{padding-right:.4em;content:\"⌃\"}.md-typeset .keys .key-meta::before{padding-right:.4em;content:\"◆\"}.md-typeset .keys .key-left-meta::before{padding-right:.4em;content:\"◆\"}.md-typeset .keys .key-right-meta::before{padding-right:.4em;content:\"◆\"}.md-typeset .keys .key-option::before{padding-right:.4em;content:\"⌥\"}.md-typeset .keys .key-left-option::before{padding-right:.4em;content:\"⌥\"}.md-typeset .keys .key-right-option::before{padding-right:.4em;content:\"⌥\"}.md-typeset .keys .key-shift::before{padding-right:.4em;content:\"⇧\"}.md-typeset .keys .key-left-shift::before{padding-right:.4em;content:\"⇧\"}.md-typeset .keys .key-right-shift::before{padding-right:.4em;content:\"⇧\"}.md-typeset .keys .key-super::before{padding-right:.4em;content:\"❖\"}.md-typeset .keys .key-left-super::before{padding-right:.4em;content:\"❖\"}.md-typeset .keys .key-right-super::before{padding-right:.4em;content:\"❖\"}.md-typeset .keys .key-windows::before{padding-right:.4em;content:\"⊞\"}.md-typeset .keys .key-left-windows::before{padding-right:.4em;content:\"⊞\"}.md-typeset .keys .key-right-windows::before{padding-right:.4em;content:\"⊞\"}.md-typeset .keys .key-arrow-down::before{padding-right:.4em;content:\"↓\"}.md-typeset .keys .key-arrow-left::before{padding-right:.4em;content:\"←\"}.md-typeset .keys .key-arrow-right::before{padding-right:.4em;content:\"→\"}.md-typeset .keys .key-arrow-up::before{padding-right:.4em;content:\"↑\"}.md-typeset .keys .key-backspace::before{padding-right:.4em;content:\"⌫\"}.md-typeset .keys .key-backtab::before{padding-right:.4em;content:\"⇤\"}.md-typeset .keys .key-caps-lock::before{padding-right:.4em;content:\"⇪\"}.md-typeset .keys .key-clear::before{padding-right:.4em;content:\"⌧\"}.md-typeset .keys .key-context-menu::before{padding-right:.4em;content:\"☰\"}.md-typeset .keys .key-delete::before{padding-right:.4em;content:\"⌦\"}.md-typeset .keys .key-eject::before{padding-right:.4em;content:\"⏏\"}.md-typeset .keys .key-end::before{padding-right:.4em;content:\"⤓\"}.md-typeset .keys .key-escape::before{padding-right:.4em;content:\"⎋\"}.md-typeset .keys .key-home::before{padding-right:.4em;content:\"⤒\"}.md-typeset .keys .key-insert::before{padding-right:.4em;content:\"⎀\"}.md-typeset .keys .key-page-down::before{padding-right:.4em;content:\"⇟\"}.md-typeset .keys .key-page-up::before{padding-right:.4em;content:\"⇞\"}.md-typeset .keys .key-print-screen::before{padding-right:.4em;content:\"⎙\"}.md-typeset .keys .key-tab::after{padding-left:.4em;content:\"⇥\"}.md-typeset .keys .key-num-enter::after{padding-left:.4em;content:\"⌤\"}.md-typeset .keys .key-enter::after{padding-left:.4em;content:\"⏎\"}.md-typeset .tabbed-content{display:none;order:99;width:100%;box-shadow:0 -0.05rem var(--md-default-fg-color--lightest)}@media print{.md-typeset .tabbed-content{display:block;order:initial}}.md-typeset .tabbed-content>pre:only-child,.md-typeset .tabbed-content>.highlight:only-child pre,.md-typeset .tabbed-content>.highlighttable:only-child{margin:0}.md-typeset .tabbed-content>pre:only-child>code,.md-typeset .tabbed-content>.highlight:only-child pre>code,.md-typeset .tabbed-content>.highlighttable:only-child>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-content>.tabbed-set{margin:0}.md-typeset .tabbed-set{position:relative;display:flex;flex-wrap:wrap;margin:1em 0;border-radius:.1rem}.md-typeset .tabbed-set>input{position:absolute;width:0;height:0;opacity:0}.md-typeset .tabbed-set>input:checked+label{color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color)}.md-typeset .tabbed-set>input:checked+label+.tabbed-content{display:block}.md-typeset .tabbed-set>input:focus+label{outline-style:auto}.md-typeset .tabbed-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.md-typeset .tabbed-set>label{z-index:1;width:auto;padding:.9375em 1.25em .78125em;color:var(--md-default-fg-color--light);font-weight:700;font-size:.64rem;border-bottom:.1rem solid transparent;cursor:pointer;transition:color 250ms}.md-typeset .tabbed-set>label:hover{color:var(--md-accent-fg-color)}:root{--md-tasklist-icon: svg-load( \"@primer/octicons/build/svg/check-circle-fill-24.svg\" );--md-tasklist-icon--checked: svg-load( \"@primer/octicons/build/svg/check-circle-fill-24.svg\" )}.md-typeset .task-list-item{position:relative;list-style-type:none}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em;left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em;left:initial}.md-typeset .task-list-control [type=checkbox]{z-index:-1;opacity:0}.md-typeset .task-list-indicator::before{position:absolute;top:.15em;left:-1.5em;width:1.25em;height:1.25em;background-color:var(--md-default-fg-color--lightest);mask-image:var(--md-tasklist-icon);mask-repeat:no-repeat;mask-size:contain;content:\"\"}[dir=rtl] .md-typeset .task-list-indicator::before{right:-1.5em;left:initial}.md-typeset [type=checkbox]:checked+.task-list-indicator::before{background-color:#00e676;mask-image:var(--md-tasklist-icon--checked)}","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Enforce correct box model and prevent adjustments of font size after\n// orientation changes in IE and iOS\nhtml {\n box-sizing: border-box;\n text-size-adjust: none;\n}\n\n// All elements shall inherit the document default\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n// Remove margin in all browsers\nbody {\n margin: 0;\n}\n\n// Reset tap outlines on iOS and Android\na,\nbutton,\nlabel,\ninput {\n -webkit-tap-highlight-color: transparent;\n}\n\n// Reset link styles\na {\n color: inherit;\n text-decoration: none;\n}\n\n// Normalize horizontal separator styles\nhr {\n display: block;\n box-sizing: content-box;\n height: px2rem(1px);\n padding: 0;\n overflow: visible;\n border: 0;\n}\n\n// Normalize font-size in all browsers\nsmall {\n font-size: 80%;\n}\n\n// Prevent subscript and superscript from affecting line-height\nsub,\nsup {\n line-height: 1em;\n}\n\n// Remove border on image\nimg {\n border-style: none;\n}\n\n// Reset table styles\ntable {\n border-collapse: separate;\n border-spacing: 0;\n}\n\n// Reset table cell styles\ntd,\nth {\n font-weight: 400;\n vertical-align: top;\n}\n\n// Reset button styles\nbutton {\n margin: 0;\n padding: 0;\n font-size: inherit;\n background: transparent;\n border: 0;\n}\n\n// Reset input styles\ninput {\n border: 0;\n outline: none;\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Color definitions\n:root {\n\n // Default color shades\n --md-default-fg-color: hsla(0, 0%, 0%, 0.87);\n --md-default-fg-color--light: hsla(0, 0%, 0%, 0.54);\n --md-default-fg-color--lighter: hsla(0, 0%, 0%, 0.32);\n --md-default-fg-color--lightest: hsla(0, 0%, 0%, 0.07);\n --md-default-bg-color: hsla(0, 0%, 100%, 1);\n --md-default-bg-color--light: hsla(0, 0%, 100%, 0.7);\n --md-default-bg-color--lighter: hsla(0, 0%, 100%, 0.3);\n --md-default-bg-color--lightest: hsla(0, 0%, 100%, 0.12);\n\n // Primary color shades\n --md-primary-fg-color: hsla(#{hex2hsl($clr-indigo-500)}, 1);\n --md-primary-fg-color--light: hsla(#{hex2hsl($clr-indigo-400)}, 1);\n --md-primary-fg-color--dark: hsla(#{hex2hsl($clr-indigo-700)}, 1);\n --md-primary-bg-color: hsla(0, 0%, 100%, 1);\n --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);\n\n // Accent color shades\n --md-accent-fg-color: hsla(#{hex2hsl($clr-indigo-a200)}, 1);\n --md-accent-fg-color--transparent: hsla(#{hex2hsl($clr-indigo-a200)}, 0.1);\n --md-accent-bg-color: hsla(0, 0%, 100%, 1);\n --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7);\n\n // Light theme (default)\n > * {\n\n // Code color shades\n --md-code-fg-color: hsla(200, 18%, 26%, 1);\n --md-code-bg-color: hsla(0, 0%, 96%, 1);\n\n // Code highlighting color shades\n --md-code-hl-color: hsla(#{hex2hsl($clr-yellow-a200)}, 0.5);\n --md-code-hl-number-color: hsla(0, 67%, 50%, 1);\n --md-code-hl-special-color: hsla(340, 83%, 47%, 1);\n --md-code-hl-function-color: hsla(291, 45%, 50%, 1);\n --md-code-hl-constant-color: hsla(250, 63%, 60%, 1);\n --md-code-hl-keyword-color: hsla(219, 54%, 51%, 1);\n --md-code-hl-string-color: hsla(150, 63%, 30%, 1);\n --md-code-hl-name-color: var(--md-code-fg-color);\n --md-code-hl-operator-color: var(--md-default-fg-color--light);\n --md-code-hl-punctuation-color: var(--md-default-fg-color--light);\n --md-code-hl-comment-color: var(--md-default-fg-color--light);\n --md-code-hl-generic-color: var(--md-default-fg-color--light);\n --md-code-hl-variable-color: var(--md-default-fg-color--light);\n\n // Typeset color shades\n --md-typeset-color: var(--md-default-fg-color);\n --md-typeset-a-color: var(--md-primary-fg-color);\n\n // Typeset `mark` color shades\n --md-typeset-mark-color: hsla(#{hex2hsl($clr-yellow-a200)}, 0.5);\n\n // Typeset `del` and `ins` color shades\n --md-typeset-del-color: hsla(6, 90%, 60%, 0.15);\n --md-typeset-ins-color: hsla(150, 90%, 44%, 0.15);\n\n // Typeset `kbd` color shades\n --md-typeset-kbd-color: hsla(0, 0%, 98%, 1);\n --md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1);\n --md-typeset-kbd-border-color: hsla(0, 0%, 72%, 1);\n\n // Admonition color shades\n --md-admonition-fg-color: var(--md-default-fg-color);\n --md-admonition-bg-color: var(--md-default-bg-color);\n\n // Footer color shades\n --md-footer-fg-color: hsla(0, 0%, 100%, 1);\n --md-footer-fg-color--light: hsla(0, 0%, 100%, 0.7);\n --md-footer-fg-color--lighter: hsla(0, 0%, 100%, 0.3);\n --md-footer-bg-color: hsla(0, 0%, 0%, 0.87);\n --md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.32);\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon\n.md-icon {\n\n // SVG defaults\n svg {\n display: block;\n width: px2rem(24px);\n height: px2rem(24px);\n fill: currentColor;\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules: font definitions\n// ----------------------------------------------------------------------------\n\n// Enable font-smoothing in Webkit and FF\nbody {\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Define default fonts\nbody,\ninput {\n color: var(--md-typeset-color);\n font-feature-settings: \"kern\", \"liga\";\n font-family: -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;\n}\n\n// Define proportionally spaced fonts\ncode,\npre,\nkbd {\n color: var(--md-typeset-color);\n font-feature-settings: \"kern\";\n font-family: SFMono-Regular, Consolas, Menlo, monospace;\n}\n\n// ----------------------------------------------------------------------------\n// Rules: typesetted content\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-typeset-table--ascending: svg-load(\"@mdi/svg/svg/arrow-down.svg\");\n --md-typeset-table--descending: svg-load(\"@mdi/svg/svg/arrow-up.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Content that is typeset - if possible, all margins, paddings and font sizes\n// should be set in ems, so nested blocks (e.g. admonitions) render correctly.\n.md-typeset {\n font-size: px2rem(16px);\n line-height: 1.6;\n color-adjust: exact;\n\n // [print]: We'll use a smaller `font-size` for printing, so code examples\n // don't break too early, and `16px` looks too big anyway.\n @media print {\n font-size: px2rem(13.6px);\n }\n\n // Default spacing\n p,\n ul,\n ol,\n dl,\n blockquote {\n margin: 1em 0;\n }\n\n // Headline on level 1\n h1 {\n margin: 0 0 px2em(40px, 32px);\n color: var(--md-default-fg-color--light);\n font-weight: 300;\n font-size: px2em(32px);\n line-height: 1.3;\n letter-spacing: -0.01em;\n }\n\n // Headline on level 2\n h2 {\n margin: px2em(40px, 25px) 0 px2em(16px, 25px);\n font-weight: 300;\n font-size: px2em(25px);\n line-height: 1.4;\n letter-spacing: -0.01em;\n }\n\n // Headline on level 3\n h3 {\n margin: px2em(32px, 20px) 0 px2em(16px, 20px);\n font-weight: 400;\n font-size: px2em(20px);\n line-height: 1.5;\n letter-spacing: -0.01em;\n }\n\n // Headline on level 3 following level 2\n h2 + h3 {\n margin-top: px2em(16px, 20px);\n }\n\n // Headline on level 4\n h4 {\n margin: px2em(16px) 0;\n font-weight: 700;\n letter-spacing: -0.01em;\n }\n\n // Headline on level 5-6\n h5,\n h6 {\n margin: px2em(16px, 12.8px) 0;\n color: var(--md-default-fg-color--light);\n font-weight: 700;\n font-size: px2em(12.8px);\n letter-spacing: -0.01em;\n }\n\n // Headline on level 5\n h5 {\n text-transform: uppercase;\n }\n\n // Horizontal separator\n hr {\n margin: 1.5em 0;\n border-bottom: px2rem(1px) solid var(--md-default-fg-color--lightest);\n }\n\n // Text link\n a {\n color: var(--md-typeset-a-color);\n word-break: break-word;\n\n // Also enable color transition on pseudo elements\n &,\n &::before {\n transition: color 125ms;\n }\n\n // Text link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n }\n }\n\n // Code blocks\n code,\n pre,\n kbd {\n color: var(--md-code-fg-color);\n direction: ltr;\n\n // [print]: Wrap text and hide scollbars\n @media print {\n white-space: pre-wrap;\n }\n }\n\n // Inline code blocks\n code {\n padding: 0 px2em(4px, 13.6px);\n font-size: px2em(13.6px);\n word-break: break-word;\n background-color: var(--md-code-bg-color);\n border-radius: px2rem(2px);\n box-decoration-break: clone;\n\n // Hide outline for pointer devices\n &:not(.focus-visible) {\n outline: none;\n -webkit-tap-highlight-color: transparent;\n }\n }\n\n // Code block in headline\n h1 code,\n h2 code,\n h3 code,\n h4 code,\n h5 code,\n h6 code {\n margin: initial;\n padding: initial;\n background-color: transparent;\n box-shadow: none;\n }\n\n // Ensure link color in code blocks\n a > code {\n color: currentColor;\n }\n\n // Unformatted content\n pre {\n position: relative;\n margin: 1em 0;\n line-height: 1.4;\n\n // Code block\n > code {\n display: block;\n margin: 0;\n padding: px2em(10.5px, 13.6px) px2em(16px, 13.6px);\n overflow: auto;\n word-break: normal;\n box-shadow: none;\n box-decoration-break: slice;\n touch-action: auto;\n scrollbar-width: thin;\n scrollbar-color: var(--md-default-fg-color--lighter) transparent;\n\n // Code block on hover\n &:hover {\n scrollbar-color: var(--md-accent-fg-color) transparent;\n }\n\n // Webkit scrollbar\n &::-webkit-scrollbar {\n width: px2rem(4px);\n height: px2rem(4px);\n }\n\n // Webkit scrollbar thumb\n &::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n\n // Webkit scrollbar thumb on hover\n &:hover {\n background-color: var(--md-accent-fg-color);\n }\n }\n }\n }\n\n // [mobile -]: Align with body copy\n @include break-to-device(mobile) {\n\n // Unformatted text\n > pre {\n margin: 1em px2rem(-16px);\n\n // Code block\n code {\n border-radius: 0;\n }\n }\n }\n\n // Keyboard key\n kbd {\n display: inline-block;\n padding: 0 px2em(8px, 12px);\n color: var(--md-default-fg-color);\n font-size: px2em(12px);\n vertical-align: text-top;\n word-break: break-word;\n background-color: var(--md-typeset-kbd-color);\n border-radius: px2rem(2px);\n box-shadow:\n 0 px2rem(2px) 0 px2rem(1px) var(--md-typeset-kbd-border-color),\n 0 px2rem(2px) 0 var(--md-typeset-kbd-border-color),\n 0 px2rem(-2px) px2rem(4px) var(--md-typeset-kbd-accent-color) inset;\n }\n\n // Text highlighting marker\n mark {\n color: inherit;\n word-break: break-word;\n background-color: var(--md-typeset-mark-color);\n box-decoration-break: clone;\n }\n\n // Abbreviation\n abbr {\n text-decoration: none;\n border-bottom: px2rem(1px) dotted var(--md-default-fg-color--light);\n cursor: help;\n\n // Show tooltip for touch devices\n @media (hover: none) {\n position: relative;\n\n // Tooltip\n &[title]:focus::after,\n &[title]:hover::after {\n @include z-depth(2);\n\n position: absolute;\n left: 0;\n display: inline-block;\n width: auto;\n min-width: max-content;\n max-width: 80%;\n margin-top: 2em;\n padding: px2rem(4px) px2rem(6px);\n color: var(--md-default-bg-color);\n font-size: px2rem(14px);\n background-color: var(--md-default-fg-color);\n border-radius: px2rem(2px);\n content: attr(title);\n }\n }\n\n }\n\n // Small text\n small {\n opacity: 0.75;\n }\n\n // Superscript and subscript\n sup,\n sub {\n margin-left: px2em(1px, 12.8px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(1px, 12.8px);\n margin-left: initial;\n }\n }\n\n // Blockquotes, possibly nested\n blockquote {\n padding-left: px2rem(12px);\n color: var(--md-default-fg-color--light);\n border-left: px2rem(4px) solid var(--md-default-fg-color--lighter);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(12px);\n padding-left: initial;\n border-right: px2rem(4px) solid var(--md-default-fg-color--lighter);\n border-left: initial;\n }\n }\n\n // Unordered list\n ul {\n list-style-type: disc;\n }\n\n // Unordered and ordered list\n ul,\n ol {\n margin-left: px2em(10px);\n padding: 0;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(10px);\n margin-left: initial;\n }\n\n // Nested ordered list\n ol {\n list-style-type: lower-alpha;\n\n // Triply nested ordered list\n ol {\n list-style-type: lower-roman;\n }\n }\n\n // List element\n li {\n margin-bottom: 0.5em;\n margin-left: px2em(20px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(20px);\n margin-left: initial;\n }\n\n // Adjust spacing\n p,\n blockquote {\n margin: 0.5em 0;\n }\n\n // Adjust spacing on last child\n &:last-child {\n margin-bottom: 0;\n }\n\n // Nested list\n ul,\n ol {\n margin: 0.5em 0 0.5em px2em(10px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(10px);\n margin-left: initial;\n }\n }\n }\n }\n\n // Definition list\n dd {\n margin: 1em 0 1.5em px2em(30px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2em(30px);\n margin-left: initial;\n }\n }\n\n // Image or icon\n img,\n svg {\n max-width: 100%;\n height: auto;\n\n // Adjust spacing when left-aligned\n &[align=\"left\"] {\n margin: 1em;\n margin-left: 0;\n }\n\n // Adjust spacing when right-aligned\n &[align=\"right\"] {\n margin: 1em;\n margin-right: 0;\n }\n\n // Adjust spacing when sole children\n &[align]:only-child {\n margin-top: 0;\n }\n }\n\n // Figure\n figure {\n width: fit-content;\n max-width: 100%;\n margin: 0 auto;\n text-align: center;\n\n // Figure images\n img {\n display: block;\n }\n }\n\n // Figure caption\n figcaption {\n max-width: px2rem(480px);\n margin: 1em auto 2em;\n font-style: italic;\n }\n\n // Limit width to container\n iframe {\n max-width: 100%;\n }\n\n // Data table\n table:not([class]) {\n display: inline-block;\n max-width: 100%;\n overflow: auto;\n font-size: px2rem(12.8px);\n background-color: var(--md-default-bg-color);\n border-radius: px2rem(2px);\n box-shadow:\n 0 px2rem(4px) px2rem(10px) hsla(0, 0%, 0%, 0.05),\n 0 0 px2rem(1px) hsla(0, 0%, 0%, 0.1);\n touch-action: auto;\n\n // [print]: Reset display mode so table header wraps when printing\n @media print {\n display: table;\n }\n\n // Due to margin collapse because of the necessary inline-block hack, we\n // cannot increase the bottom margin on the table, so we just increase the\n // top margin on the following element\n & + * {\n margin-top: 1.5em;\n }\n\n // Elements in table heading and cell\n th > *,\n td > * {\n\n // Adjust spacing on first child\n &:first-child {\n margin-top: 0;\n }\n\n // Adjust spacing on last child\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Table heading and cell\n th:not([align]),\n td:not([align]) {\n text-align: left;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n text-align: right;\n }\n }\n\n // Table heading\n th {\n min-width: px2rem(100px);\n padding: px2em(12px, 12.8px) px2em(16px, 12.8px);\n color: var(--md-default-bg-color);\n vertical-align: top;\n background-color: var(--md-default-fg-color--light);\n\n // Links in table headings\n a {\n color: inherit;\n }\n }\n\n // Table cell\n td {\n padding: px2em(12px, 12.8px) px2em(16px, 12.8px);\n vertical-align: top;\n border-top: px2rem(1px) solid var(--md-default-fg-color--lightest);\n }\n\n // Table row\n tr {\n transition: background-color 125ms;\n\n // Table row on hover\n &:hover {\n background-color: rgba(0, 0, 0, 0.035);\n box-shadow: 0 px2rem(1px) 0 var(--md-default-bg-color) inset;\n }\n\n // Hide border on first table row\n &:first-child td {\n border-top: 0;\n }\n }\n\n // Text link in table\n a {\n word-break: normal;\n }\n }\n\n // Sortable table\n table th[role=\"columnheader\"] {\n cursor: pointer;\n\n // Sort icon\n &::after {\n display: inline-block;\n width: 1.2em;\n height: 1.2em;\n margin-left: 0.5em;\n vertical-align: sub;\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n\n // Sort ascending\n &[aria-sort=\"ascending\"]::after {\n background-color: currentColor;\n mask-image: var(--md-typeset-table--ascending);\n }\n\n // Sort descending\n &[aria-sort=\"descending\"]::after {\n background-color: currentColor;\n mask-image: var(--md-typeset-table--descending);\n }\n }\n\n // Data table scroll wrapper\n &__scrollwrap {\n margin: 1em px2rem(-16px);\n overflow-x: auto;\n touch-action: auto;\n }\n\n // Data table wrapper\n &__table {\n display: inline-block;\n margin-bottom: 0.5em;\n padding: 0 px2rem(16px);\n\n // [print]: Reset display mode so table header wraps when printing\n @media print {\n display: block;\n }\n\n // Data table\n html & table {\n display: table;\n width: 100%;\n margin: 0;\n overflow: hidden;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Variables\n// ----------------------------------------------------------------------------\n\n///\n/// Device-specific breakpoints\n///\n/// @example\n/// $break-devices: (\n/// mobile: (\n/// portrait: 220px 479px,\n/// landscape: 480px 719px\n/// ),\n/// tablet: (\n/// portrait: 720px 959px,\n/// landscape: 960px 1219px\n/// ),\n/// screen: (\n/// small: 1220px 1599px,\n/// medium: 1600px 1999px,\n/// large: 2000px\n/// )\n/// );\n///\n$break-devices: () !default;\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n///\n/// Choose minimum and maximum device widths\n///\n@function break-select-min-max($devices) {\n $min: 1000000;\n $max: 0;\n @each $key, $value in $devices {\n @while type-of($value) == map {\n $value: break-select-min-max($value);\n }\n @if type-of($value) == list {\n @each $number in $value {\n @if type-of($number) == number {\n $min: min($number, $min);\n @if $max != null {\n $max: max($number, $max);\n }\n } @else {\n @error \"Invalid number: #{$number}\";\n }\n }\n } @else if type-of($value) == number {\n $min: min($value, $min);\n $max: null;\n } @else {\n @error \"Invalid value: #{$value}\";\n }\n }\n @return $min, $max;\n}\n\n///\n/// Select minimum and maximum widths for a device breakpoint\n///\n@function break-select-device($device) {\n $current: $break-devices;\n @for $n from 1 through length($device) {\n @if type-of($current) == map {\n $current: map-get($current, nth($device, $n));\n } @else {\n @error \"Invalid device map: #{$devices}\";\n }\n }\n @if type-of($current) == list or type-of($current) == number {\n $current: (default: $current);\n }\n @return break-select-min-max($current);\n}\n\n// ----------------------------------------------------------------------------\n// Mixins\n// ----------------------------------------------------------------------------\n\n///\n/// A minimum-maximum media query breakpoint\n///\n@mixin break-at($breakpoint) {\n @if type-of($breakpoint) == number {\n @media screen and (min-width: $breakpoint) {\n @content;\n }\n } @else if type-of($breakpoint) == list {\n $min: nth($breakpoint, 1);\n $max: nth($breakpoint, 2);\n @if type-of($min) == number and type-of($max) == number {\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// An orientation media query breakpoint\n///\n@mixin break-at-orientation($breakpoint) {\n @if type-of($breakpoint) == string {\n @media screen and (orientation: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A maximum-aspect-ratio media query breakpoint\n///\n@mixin break-at-ratio($breakpoint) {\n @if type-of($breakpoint) == number {\n @media screen and (max-aspect-ratio: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A minimum-maximum media query device breakpoint\n///\n@mixin break-at-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n @if nth($breakpoint, 2) != null {\n $min: nth($breakpoint, 1);\n $max: nth($breakpoint, 2);\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A minimum media query device breakpoint\n///\n@mixin break-from-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n $min: nth($breakpoint, 1);\n @media screen and (min-width: $min) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A maximum media query device breakpoint\n///\n@mixin break-to-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n $max: nth($breakpoint, 2);\n @media screen and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n","//\n// Name: Material Shadows\n// Description: Mixins for Material Design Shadows.\n// Version: 3.0.1\n//\n// Author: Denis Malinochkin\n// Git: https://github.com/mrmlnc/material-shadows\n//\n// twitter: @mrmlnc\n//\n// ------------------------------------\n\n\n// Mixins\n// ------------------------------------\n\n@mixin z-depth-transition() {\n transition: box-shadow .28s cubic-bezier(.4, 0, .2, 1);\n}\n\n@mixin z-depth-focus() {\n box-shadow: 0 0 8px rgba(0, 0, 0, .18), 0 8px 16px rgba(0, 0, 0, .36);\n}\n\n@mixin z-depth-2dp() {\n box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14),\n 0 1px 5px 0 rgba(0, 0, 0, .12),\n 0 3px 1px -2px rgba(0, 0, 0, .2);\n}\n\n@mixin z-depth-3dp() {\n box-shadow: 0 3px 4px 0 rgba(0, 0, 0, .14),\n 0 1px 8px 0 rgba(0, 0, 0, .12),\n 0 3px 3px -2px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-4dp() {\n box-shadow: 0 4px 5px 0 rgba(0, 0, 0, .14),\n 0 1px 10px 0 rgba(0, 0, 0, .12),\n 0 2px 4px -1px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-6dp() {\n box-shadow: 0 6px 10px 0 rgba(0, 0, 0, .14),\n 0 1px 18px 0 rgba(0, 0, 0, .12),\n 0 3px 5px -1px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-8dp() {\n box-shadow: 0 8px 10px 1px rgba(0, 0, 0, .14),\n 0 3px 14px 2px rgba(0, 0, 0, .12),\n 0 5px 5px -3px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-16dp() {\n box-shadow: 0 16px 24px 2px rgba(0, 0, 0, .14),\n 0 6px 30px 5px rgba(0, 0, 0, .12),\n 0 8px 10px -5px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth-24dp() {\n box-shadow: 0 9px 46px 8px rgba(0, 0, 0, .14),\n 0 24px 38px 3px rgba(0, 0, 0, .12),\n 0 11px 15px -7px rgba(0, 0, 0, .4);\n}\n\n@mixin z-depth($dp: 2) {\n @if $dp == 2 {\n @include z-depth-2dp();\n } @else if $dp == 3 {\n @include z-depth-3dp();\n } @else if $dp == 4 {\n @include z-depth-4dp();\n } @else if $dp == 6 {\n @include z-depth-6dp();\n } @else if $dp == 8 {\n @include z-depth-8dp();\n } @else if $dp == 16 {\n @include z-depth-16dp();\n } @else if $dp == 24 {\n @include z-depth-24dp();\n }\n}\n\n\n// Class generator\n// ------------------------------------\n\n@mixin z-depth-classes($transition: false, $focus: false) {\n @if $transition == true {\n &-transition {\n @include z-depth-transition();\n }\n }\n\n @if $focus == true {\n &-focus {\n @include z-depth-focus();\n }\n }\n\n // The available values for the shadow depth\n @each $depth in 2, 3, 4, 6, 8, 16, 24 {\n &-#{$depth}dp {\n @include z-depth($depth);\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules: base grid and containers\n// ----------------------------------------------------------------------------\n\n// Stretch container to viewport and set base `font-size`\nhtml {\n height: 100%;\n overflow-x: hidden;\n // Hack: normally, we would set the base `font-size` to `62.5%`, so we can\n // base all calculations on `10px`, but Chromium and Chrome define a minimal\n // `font-size` of `12px` if the system language is set to Chinese. For this\n // reason we just double the `font-size` and set it to `20px`.\n //\n // See https://github.com/squidfunk/mkdocs-material/issues/911\n font-size: 125%;\n\n // [screen medium +]: Set base `font-size` to `11px`\n @include break-from-device(screen medium) {\n font-size: 137.50%;\n }\n\n // [screen large +]: Set base `font-size` to `12px`\n @include break-from-device(screen large) {\n font-size: 150%;\n }\n}\n\n// Stretch body to container - flexbox is used, so the footer will always be\n// aligned to the bottom of the viewport\nbody {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n min-height: 100%;\n // Hack: reset `font-size` to `10px`, so the spacing for all inline elements\n // is correct again. Otherwise the spacing would be based on `20px`.\n font-size: px2rem(10px);\n background-color: var(--md-default-bg-color);\n\n // [print]: Omit flexbox layout due to a Firefox bug (https://mzl.la/39DgR3m)\n @media print {\n display: block;\n }\n\n // Body in locked state\n &[data-md-state=\"lock\"] {\n\n // [tablet portrait -]: Omit scroll bubbling\n @include break-to-device(tablet portrait) {\n position: fixed;\n }\n }\n}\n\n// ----------------------------------------------------------------------------\n\n// Grid container - this class is applied to wrapper elements within the\n// header, content area and footer, and makes sure that their width is limited\n// to `1220px`, and they are rendered centered if the screen is larger.\n.md-grid {\n max-width: px2rem(1220px);\n margin-right: auto;\n margin-left: auto;\n}\n\n// Main container\n.md-container {\n display: flex;\n flex-direction: column;\n flex-grow: 1;\n\n // [print]: Omit flexbox layout due to a Firefox bug (https://mzl.la/39DgR3m)\n @media print {\n display: block;\n }\n}\n\n// Main area - stretch to remaining space of container\n.md-main {\n flex-grow: 1;\n\n // Main area wrapper\n &__inner {\n display: flex;\n height: 100%;\n margin-top: px2rem(24px + 6px);\n }\n}\n\n// Add ellipsis in case of overflowing text\n.md-ellipsis {\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n// ----------------------------------------------------------------------------\n// Rules: navigational elements\n// ----------------------------------------------------------------------------\n\n// Toggle - this class is applied to the checkbox elements, which are used to\n// implement the CSS-only drawer and navigation, as well as the search\n.md-toggle {\n display: none;\n}\n\n// Skip link\n.md-skip {\n position: fixed;\n // Hack: if we don't set the negative `z-index`, the skip link will force the\n // creation of new layers when code blocks are near the header on scrolling\n z-index: -1;\n margin: px2rem(10px);\n padding: px2rem(6px) px2rem(10px);\n color: var(--md-default-bg-color);\n font-size: px2rem(12.8px);\n background-color: var(--md-default-fg-color);\n border-radius: px2rem(2px);\n transform: translateY(px2rem(8px));\n opacity: 0;\n\n // Show skip link on focus\n &:focus {\n z-index: 10;\n transform: translateY(0);\n opacity: 1;\n transition:\n transform 250ms cubic-bezier(0.4, 0, 0.2, 1),\n opacity 175ms 75ms;\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: print styles\n// ----------------------------------------------------------------------------\n\n// Add margins to page\n@page {\n margin: 25mm;\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Announcement bar\n.md-announce {\n overflow: auto;\n background-color: var(--md-footer-bg-color);\n\n // [print]: Hide announcement bar\n @media print {\n display: none;\n }\n\n // Announcement wrapper\n &__inner {\n margin: px2rem(12px) auto;\n padding: 0 px2rem(16px);\n color: var(--md-footer-fg-color);\n font-size: px2rem(14px);\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Button\n .md-button {\n display: inline-block;\n padding: px2em(10px) px2em(32px);\n color: var(--md-primary-fg-color);\n font-weight: 700;\n border: px2rem(2px) solid currentColor;\n border-radius: px2rem(2px);\n transition:\n color 125ms,\n background-color 125ms,\n border-color 125ms;\n\n // Primary button\n &--primary {\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color);\n border-color: var(--md-primary-fg-color);\n }\n\n // Button on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-bg-color);\n background-color: var(--md-accent-fg-color);\n border-color: var(--md-accent-fg-color);\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-clipboard-icon: svg-load(\"@mdi/svg/svg/content-copy.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Button to copy to clipboard\n.md-clipboard {\n position: absolute;\n top: px2em(8px);\n right: px2em(8px);\n z-index: 1;\n width: px2em(24px);\n height: px2em(24px);\n color: var(--md-default-fg-color--lightest);\n border-radius: px2rem(2px);\n cursor: pointer;\n transition: color 250ms;\n\n // [print]: Hide button\n @media print {\n display: none;\n }\n\n // Darken color on code block hover\n :hover > & {\n color: var(--md-default-fg-color--light);\n }\n\n // Button on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n }\n\n // Button icon - the width and height are defined in `em`, so the size is\n // automatically adjusted for nested code blocks (e.g. in admonitions)\n &::after {\n display: block;\n width: px2em(18px);\n height: px2em(18px);\n margin: 0 auto;\n background-color: currentColor;\n mask-image: var(--md-clipboard-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Content area\n.md-content {\n flex-grow: 1;\n // Hack: we must use `overflow: hidden`, so the content area is capped by\n // the dimensions of its parent. Otherwise, long code blocks might lead to\n // a wider content area which will break everything. This, however, induces\n // margin collapse, which will break scroll margins. Adding a large enough\n // scroll padding seems to do the trick, at least in Chrome and Firefox.\n overflow: hidden;\n scroll-padding-top: px2rem(1024px);\n\n // Content wrapper\n &__inner {\n margin: 0 px2rem(16px) px2rem(24px);\n padding-top: px2rem(12px);\n\n // [screen +]: Adjust spacing between content area and sidebars\n @include break-from-device(screen) {\n\n // Sidebar with navigation is visible\n .md-sidebar--primary:not([hidden]) ~ .md-content > & {\n margin-left: px2rem(24px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(24px);\n margin-left: px2rem(16px);\n }\n }\n\n // Sidebar with table of contents is visible\n .md-sidebar--secondary:not([hidden]) ~ .md-content > & {\n margin-right: px2rem(24px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(16px);\n margin-left: px2rem(24px);\n }\n }\n }\n\n // Hack: add pseudo element for spacing, as the overflow of the content\n // container may not be hidden due to an imminent offset error on targets\n &::before {\n display: block;\n height: px2rem(8px);\n content: \"\";\n }\n\n // Adjust spacing on last child\n > :last-child {\n margin-bottom: 0;\n }\n }\n\n // Button inside of the content area - these buttons are meant for actions on\n // a document-level, i.e. linking to related source code files, printing etc.\n &__button {\n float: right;\n margin: px2rem(8px) 0;\n margin-left: px2rem(8px);\n padding: 0;\n\n // [print]: Hide buttons\n @media print {\n display: none;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: left;\n margin-right: px2rem(8px);\n margin-left: initial;\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n\n // Adjust default link color for icons\n .md-typeset & {\n color: var(--md-default-fg-color--lighter);\n }\n\n // Align with body copy located next to icon\n svg {\n display: inline;\n vertical-align: top;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Dialog\n.md-dialog {\n @include z-depth(2);\n\n position: fixed;\n right: px2rem(16px);\n bottom: px2rem(16px);\n left: initial;\n z-index: 2;\n display: block;\n min-width: px2rem(222px);\n padding: px2rem(8px) px2rem(12px);\n color: var(--md-default-bg-color);\n font-size: px2rem(14px);\n background-color: var(--md-default-fg-color);\n border: none;\n border-radius: px2rem(2px);\n transform: translateY(100%);\n opacity: 0;\n transition:\n transform 0ms 400ms,\n opacity 400ms;\n\n // [print]: Hide dialog\n @media print {\n display: none;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(16px);\n }\n\n // Dialog in open state\n &[data-md-state=\"open\"] {\n transform: translateY(0);\n opacity: 1;\n transition:\n transform 400ms cubic-bezier(0.075, 0.85, 0.175, 1),\n opacity 400ms;\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Header - by default, the header will be sticky and stay always on top of the\n// viewport. If this behavior is not desired, just set `position: static`.\n.md-header {\n position: sticky;\n top: 0;\n right: 0;\n left: 0;\n z-index: 2;\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color);\n // Hack: reduce jitter by adding a transparent box shadow of the same size\n // so the size of the layer doesn't change during animation\n box-shadow:\n 0 0 px2rem(4px) rgba(0, 0, 0, 0),\n 0 px2rem(4px) px2rem(8px) rgba(0, 0, 0, 0);\n transition:\n color 250ms,\n background-color 250ms;\n\n // [print]: Hide header\n @media print {\n display: none;\n }\n\n // Header in shadow state, i.e. shadow is visible\n &[data-md-state=\"shadow\"] {\n box-shadow:\n 0 0 px2rem(4px) rgba(0, 0, 0, 0.1),\n 0 px2rem(4px) px2rem(8px) rgba(0, 0, 0, 0.2);\n transition:\n transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1),\n color 250ms,\n background-color 250ms,\n box-shadow 250ms;\n }\n\n // Header in hidden state, i.e. moved out of sight\n &[data-md-state=\"hidden\"] {\n transform: translateY(-100%);\n transition:\n transform 250ms cubic-bezier(0.8, 0, 0.6, 1),\n color 250ms,\n background-color 250ms,\n box-shadow 250ms;\n }\n}\n\n// Header navigation - if the header exceeds the default height of `48px`, i.e.\n// by adding a bigger logo, the items are agned at the center\n.md-header-nav {\n display: flex;\n align-items: center;\n padding: 0 px2rem(4px);\n\n // Header navigation button\n &__button {\n position: relative;\n z-index: 1;\n display: inline-block;\n margin: px2rem(4px);\n padding: px2rem(8px);\n color: currentColor;\n vertical-align: middle;\n cursor: pointer;\n transition: opacity 250ms;\n\n // Button on focus/hover\n &:focus,\n &:hover {\n opacity: 0.7;\n }\n\n // Hide outline for pointer devices\n &:not(.focus-visible) {\n outline: none;\n }\n\n // Button with logo, pointing to `config.site_url`\n &.md-logo {\n margin: px2rem(4px);\n padding: px2rem(8px);\n\n // [tablet -]: Hide button\n @include break-to-device(tablet) {\n display: none;\n }\n\n // Image or icon\n img,\n svg {\n display: block;\n width: px2rem(24px);\n height: px2rem(24px);\n fill: currentColor;\n }\n }\n\n // Button for search\n &[for=\"__search\"] {\n\n // [tablet landscape +]: Hide button\n @include break-from-device(tablet landscape) {\n display: none;\n }\n\n // [no-js]: Hide button\n .no-js & {\n display: none\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n }\n\n // Button for drawer\n &[for=\"__drawer\"] {\n\n // [screen +]: Hide button\n @include break-from-device(screen) {\n display: none;\n }\n }\n }\n\n // Header navigation topic\n &__topic {\n position: absolute;\n display: flex;\n max-width: 100%;\n transition:\n transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 150ms;\n\n // Second header topic - title of the current page\n & + & {\n z-index: -1;\n transform: translateX(px2rem(25px));\n opacity: 0;\n transition:\n transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),\n opacity 150ms;\n pointer-events: none;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(px2rem(-25px));\n }\n }\n }\n\n // Header navigation title\n &__title {\n flex-grow: 1;\n height: px2rem(48px);\n margin-right: px2rem(8px);\n margin-left: px2rem(20px);\n font-size: px2rem(18px);\n line-height: px2rem(48px);\n\n // Header title in active state, i.e. page title is visible\n &[data-md-state=\"active\"] .md-header-nav__topic {\n z-index: -1;\n transform: translateX(px2rem(-25px));\n opacity: 0;\n transition:\n transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1),\n opacity 150ms;\n pointer-events: none;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(px2rem(25px));\n }\n\n // Second header topic - title of the current page\n & + .md-header-nav__topic {\n z-index: 0;\n transform: translateX(0);\n opacity: 1;\n transition:\n transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 150ms;\n pointer-events: initial;\n }\n }\n\n // Add ellipsis in case of overflowing text\n > .md-header-nav__ellipsis {\n position: relative;\n width: 100%;\n height: 100%;\n }\n }\n\n // Repository information container\n &__source {\n display: none;\n\n // [tablet landscape +]: Show repository information\n @include break-from-device(tablet landscape) {\n display: block;\n width: px2rem(234px);\n max-width: px2rem(234px);\n margin-left: px2rem(20px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(20px);\n margin-left: initial;\n }\n }\n\n // [screen +]: Adjust spacing of search bar\n @include break-from-device(screen) {\n margin-left: px2rem(28px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(28px);\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Footer\n.md-footer {\n color: var(--md-footer-fg-color);\n background-color: var(--md-footer-bg-color);\n\n // [print]: Hide footer\n @media print {\n display: none;\n }\n}\n\n// Footer navigation\n.md-footer-nav {\n\n // Footer navigation wrapper\n &__inner {\n padding: px2rem(4px);\n overflow: auto;\n }\n\n // Footer link to previous and next page\n &__link {\n display: flex;\n padding-top: px2rem(28px);\n padding-bottom: px2rem(8px);\n transition: opacity 250ms;\n\n // [tablet +]: Adjust width to 50/50\n @include break-from-device(tablet) {\n width: 50%;\n }\n\n // Footer link on focus/hover\n &:focus,\n &:hover {\n opacity: 0.7;\n }\n\n // Footer link to previous page\n &--prev {\n float: left;\n\n // [mobile -]: Adjust width to 25/75 and hide title\n @include break-to-device(mobile) {\n width: 25%;\n\n // Hide footer navigation title\n .md-footer-nav__title {\n display: none;\n }\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: right;\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n }\n\n // Footer link to next page\n &--next {\n float: right;\n text-align: right;\n\n // [mobile -]: Adjust width to 25/75\n @include break-to-device(mobile) {\n width: 75%;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: left;\n text-align: left;\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n }\n }\n\n // Footer navigation title\n &__title {\n position: relative;\n flex-grow: 1;\n max-width: calc(100% - #{px2rem(48px)});\n padding: 0 px2rem(20px);\n font-size: px2rem(18px);\n line-height: px2rem(48px);\n }\n\n // Footer navigation link button\n &__button {\n margin: px2rem(4px);\n padding: px2rem(8px);\n }\n\n // Footer navigation link direction (i.e. prev and next)\n &__direction {\n position: absolute;\n right: 0;\n left: 0;\n margin-top: px2rem(-20px);\n padding: 0 px2rem(20px);\n font-size: px2rem(12.8px);\n opacity: 0.7;\n }\n}\n\n// Footer metadata\n.md-footer-meta {\n background-color: var(--md-footer-bg-color--dark);\n\n // Footer metadata wrapper\n &__inner {\n display: flex;\n flex-wrap: wrap;\n justify-content: space-between;\n padding: px2rem(4px);\n }\n\n // Lighten color for non-hovered text links\n html &.md-typeset a {\n color: var(--md-footer-fg-color--light);\n\n // Text link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-footer-fg-color);\n }\n }\n}\n\n// Footer copyright metadata\n.md-footer-copyright {\n width: 100%;\n margin: auto px2rem(12px);\n padding: px2rem(8px) 0;\n color: var(--md-footer-fg-color--lighter);\n font-size: px2rem(12.8px);\n\n // [tablet portrait +]: Show copyright and social links in one line\n @include break-from-device(tablet portrait) {\n width: auto;\n }\n\n // Footer copyright highlight - this is the upper part of the copyright and\n // theme information, which will include a darker color than the theme link\n &__highlight {\n color: var(--md-footer-fg-color--light);\n }\n}\n\n// Footer social metadata\n.md-footer-social {\n margin: 0 px2rem(8px);\n padding: px2rem(4px) 0 px2rem(12px);\n\n // [tablet portrait +]: Show copyright and social links in one line\n @include break-from-device(tablet portrait) {\n padding: px2rem(12px) 0;\n }\n\n // Footer social link\n &__link {\n display: inline-block;\n width: px2rem(32px);\n height: px2rem(32px);\n text-align: center;\n\n // Adjust line-height to match height for correct alignment\n &::before {\n line-height: 1.9;\n }\n\n // Fill icon with current color\n svg {\n max-height: px2rem(16px);\n vertical-align: -25%;\n fill: currentColor;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-nav-icon--prev: svg-load(\"@mdi/svg/svg/arrow-left.svg\");\n --md-nav-icon--next: svg-load(\"@mdi/svg/svg/chevron-right.svg\");\n --md-toc-icon: svg-load(\"@mdi/svg/svg/table-of-contents.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Navigation\n.md-nav {\n font-size: px2rem(14px);\n line-height: 1.3;\n\n // Navigation title\n &__title {\n display: block;\n padding: 0 px2rem(12px);\n overflow: hidden;\n font-weight: 700;\n text-overflow: ellipsis;\n\n // Navigaton button\n .md-nav__button {\n display: none;\n\n // Stretch images based on height, as it's the smaller dimension\n img {\n width: auto;\n height: 100%;\n }\n\n // Button with logo, pointing to `config.site_url`\n &.md-logo {\n\n // Image or icon\n img,\n svg {\n display: block;\n width: px2rem(48px);\n height: px2rem(48px);\n fill: currentColor;\n }\n }\n }\n }\n\n // Navigation list\n &__list {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n // Navigation item\n &__item {\n padding: 0 px2rem(12px);\n\n // Navigation item on level 2\n & & {\n padding-right: 0;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(12px);\n padding-left: 0;\n }\n }\n }\n\n // Navigation link\n &__link {\n display: block;\n margin-top: 0.625em;\n overflow: hidden;\n text-overflow: ellipsis;\n cursor: pointer;\n transition: color 125ms;\n scroll-snap-align: start;\n\n // Link in blurred state\n &[data-md-state=\"blur\"] {\n color: var(--md-default-fg-color--light);\n }\n\n // Active link\n .md-nav__item &--active {\n color: var(--md-typeset-a-color);\n }\n\n // Navigation link in nested list\n .md-nav__item--nested > & {\n color: inherit;\n }\n\n // Navigation link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n }\n\n // Navigation link to table of contents\n .md-nav--primary &[for=\"__toc\"] {\n display: none;\n\n // Table of contents icon\n .md-icon::after {\n display: block;\n width: 100%;\n height: 100%;\n mask-image: var(--md-toc-icon);\n background-color: currentColor;\n }\n\n // Hide table of contents\n & ~ .md-nav {\n display: none;\n }\n }\n }\n\n // Repository information container\n &__source {\n display: none;\n }\n\n // [tablet -]: Layered navigation\n @include break-to-device(tablet) {\n\n // Primary and nested navigation\n &--primary,\n &--primary & {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n display: flex;\n flex-direction: column;\n height: 100%;\n background-color: var(--md-default-bg-color);\n }\n\n // Primary navigation\n &--primary {\n\n // Navigation title and item\n .md-nav__title,\n .md-nav__item {\n font-size: px2rem(16px);\n line-height: 1.5;\n }\n\n // Navigation title\n .md-nav__title {\n position: relative;\n height: px2rem(112px);\n padding: px2rem(60px) px2rem(16px) px2rem(4px);\n color: var(--md-default-fg-color--light);\n font-weight: 400;\n line-height: px2rem(48px);\n white-space: nowrap;\n background-color: var(--md-default-fg-color--lightest);\n cursor: pointer;\n\n // Navigation icon\n .md-nav__icon {\n position: absolute;\n top: px2rem(8px);\n left: px2rem(8px);\n display: block;\n width: px2rem(24px);\n height: px2rem(24px);\n margin: px2rem(4px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(8px);\n left: initial;\n }\n\n // Navigation icon in link to previous level\n &::after {\n display: block;\n width: 100%;\n height: 100%;\n background-color: currentColor;\n mask-image: var(--md-nav-icon--prev);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n }\n\n // Navigation list\n ~ .md-nav__list {\n overflow-y: auto;\n background-color: var(--md-default-bg-color);\n box-shadow:\n 0 px2rem(1px) 0 var(--md-default-fg-color--lightest) inset;\n scroll-snap-type: y mandatory;\n touch-action: pan-y;\n\n // Omit border on first child\n > :first-child {\n border-top: 0;\n }\n }\n\n // Top-level navigation title\n &[for=\"__drawer\"] {\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color);\n }\n\n // Button with logo, pointing to `config.site_url`\n .md-logo {\n position: absolute;\n top: px2rem(4px);\n left: px2rem(4px);\n display: block;\n margin: px2rem(4px);\n padding: px2rem(8px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(4px);\n left: initial;\n }\n }\n }\n\n // Navigation list\n .md-nav__list {\n flex: 1;\n }\n\n // Navigation item\n .md-nav__item {\n padding: 0;\n border-top: px2rem(1px) solid var(--md-default-fg-color--lightest);\n\n // Navigation link in nested navigation\n &--nested > .md-nav__link {\n padding-right: px2rem(48px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(16px);\n padding-left: px2rem(48px);\n }\n }\n\n // Navigation link in active navigation\n &--active > .md-nav__link {\n color: var(--md-typeset-a-color);\n\n // Navigation link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n }\n }\n }\n\n // Navigation link\n .md-nav__link {\n position: relative;\n margin-top: 0;\n padding: px2rem(12px) px2rem(16px);\n\n // Navigation icon\n .md-nav__icon {\n position: absolute;\n top: 50%;\n right: px2rem(12px);\n width: px2rem(24px);\n height: px2rem(24px);\n margin-top: px2rem(-12px);\n color: inherit;\n font-size: px2rem(24px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(12px);\n }\n\n // Navigation icon in link to next level\n &::after {\n display: block;\n width: 100%;\n height: 100%;\n background-color: currentColor;\n mask-image: var(--md-nav-icon--next);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n }\n }\n\n // Flip icon vertically\n .md-nav__icon {\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] &::after {\n transform: scale(-1);\n }\n }\n\n // Table of contents contained in primary navigation\n .md-nav--secondary {\n\n // Navigation link - omit unnecessary layering\n .md-nav__link {\n position: static;\n }\n\n // Navigation on level 2-6\n .md-nav {\n position: static;\n background-color: transparent;\n\n // Navigation link on level 3\n .md-nav__link {\n padding-left: px2rem(28px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(28px);\n padding-left: initial;\n }\n }\n\n // Navigation link on level 4\n .md-nav .md-nav__link {\n padding-left: px2rem(40px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(40px);\n padding-left: initial;\n }\n }\n\n // Navigation link on level 5\n .md-nav .md-nav .md-nav__link {\n padding-left: px2rem(52px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(52px);\n padding-left: initial;\n }\n }\n\n // Navigation link on level 6\n .md-nav .md-nav .md-nav .md-nav__link {\n padding-left: px2rem(64px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(64px);\n padding-left: initial;\n }\n }\n }\n }\n }\n\n // Table of contents\n &--secondary {\n background-color: transparent;\n }\n\n // Toggle for nested navigation\n &__toggle ~ & {\n display: flex;\n transform: translateX(100%);\n opacity: 0;\n transition:\n transform 250ms cubic-bezier(0.8, 0, 0.6, 1),\n opacity 125ms 50ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(-100%);\n }\n }\n\n // Show nested navigation when toggle is active\n &__toggle:checked ~ & {\n transform: translateX(0);\n opacity: 1;\n transition:\n transform 250ms cubic-bezier(0.4, 0, 0.2, 1),\n opacity 125ms 125ms;\n\n // Navigation list\n > .md-nav__list {\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n }\n }\n }\n\n // [tablet portrait -]: Layered navigation with table of contents\n @include break-to-device(tablet portrait) {\n\n // Show link to table of contents\n &--primary &__link[for=\"__toc\"] {\n display: block;\n padding-right: px2rem(48px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(16px);\n padding-left: px2rem(48px);\n }\n\n // Show table of contents icon\n .md-icon::after {\n content: \"\";\n }\n\n // Hide navigation link to current page\n + .md-nav__link {\n display: none;\n }\n\n // Show table of contents\n & ~ .md-nav {\n display: flex;\n }\n }\n\n // Repository information container\n &__source {\n display: block;\n padding: 0 px2rem(4px);\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color--dark);\n }\n }\n\n // [tablet landscape]: Layered navigation with table of contents\n @include break-at-device(tablet landscape) {\n\n // Show link to integrated table of contents\n &--integrated &__link[for=\"__toc\"] {\n display: block;\n padding-right: px2rem(48px);\n scroll-snap-align: initial;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(16px);\n padding-left: px2rem(48px);\n }\n\n // Show table of contents icon\n .md-icon::after {\n content: \"\";\n }\n\n // Hide navigation link to current page\n + .md-nav__link {\n display: none;\n }\n\n // Show table of contents\n & ~ .md-nav {\n display: flex;\n }\n }\n }\n\n // [tablet landscape +]: Tree-like table of contents\n @include break-from-device(tablet landscape) {\n\n // Navigation title\n &--secondary &__title {\n\n // Adjust snapping behavior\n &[for=\"__toc\"] {\n scroll-snap-align: start;\n }\n\n // Hide navigation icon\n .md-nav__icon {\n display: none;\n }\n }\n }\n\n // [screen +]: Tree-like navigation\n @include break-from-device(screen) {\n transition: max-height 250ms cubic-bezier(0.86, 0, 0.07, 1);\n\n // Navigation title\n &--primary &__title {\n\n // Adjust snapping behavior\n &[for=\"__drawer\"] {\n scroll-snap-align: start;\n }\n\n // Hide navigation icon\n .md-nav__icon {\n display: none;\n }\n }\n\n // Hide toggle for nested navigation\n &__toggle ~ & {\n display: none;\n }\n\n // Show nested navigation when toggle is active or indeterminate\n &__toggle:checked ~ &,\n &__toggle:indeterminate ~ & {\n display: block;\n }\n\n // Hide navigation title in nested navigation\n &__item--nested > & > &__title {\n display: none;\n }\n\n // Navigation section\n &__item--section {\n display: block;\n margin: 1.25em 0;\n\n // Adjust spacing on last child\n &:last-child {\n margin-bottom: 0;\n }\n\n // Hide navigation link, as sections are always expanded\n > .md-nav__link {\n display: none;\n }\n\n // Navigation\n > .md-nav {\n display: block;\n\n // Navigation title\n > .md-nav__title {\n display: block;\n padding: 0;\n pointer-events: none;\n scroll-snap-align: start;\n }\n\n // Adjust spacing on next level item\n > .md-nav__list > .md-nav__item {\n padding: 0;\n }\n }\n }\n\n // Navigation icon\n &__icon {\n float: right;\n width: px2rem(18px);\n height: px2rem(18px);\n transition: transform 250ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: left;\n transform: rotate(180deg);\n }\n\n // Navigation icon content\n &::after {\n display: inline-block;\n width: 100%;\n height: 100%;\n vertical-align: px2rem(-2px);\n background-color: currentColor;\n mask-image: var(--md-nav-icon--next);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n\n // Navigation icon - rotate icon when toggle is active or indeterminate\n .md-nav__item--nested .md-nav__toggle:checked ~ .md-nav__link &,\n .md-nav__item--nested .md-nav__toggle:indeterminate ~ .md-nav__link & {\n transform: rotate(90deg);\n }\n }\n\n // Modifier for when navigation tabs are rendered\n &--lifted {\n\n // Hide nested items on level 1 and site title\n > .md-nav__list > .md-nav__item--nested,\n > .md-nav__title {\n display: none;\n }\n\n // Hide level 1 items\n > .md-nav__list > .md-nav__item {\n display: none;\n\n // Active parent navigation item\n &--active {\n display: block;\n padding: 0;\n\n // Hide nested links\n > .md-nav__link {\n display: none;\n }\n\n // Show title and adjust spacing\n > .md-nav > .md-nav__title {\n display: block;\n padding: 0 px2rem(12px);\n pointer-events: none;\n scroll-snap-align: start;\n }\n }\n\n // Adjust spacing for navigation item on level 2\n > .md-nav__item {\n padding-right: px2rem(12px);\n }\n }\n\n // Hack: Always show active navigation tab on breakpoint screen, despite\n // of checkbox being checked or not. Fixes #1655.\n .md-nav[data-md-level=\"1\"] {\n display: block;\n }\n }\n\n // Modifier for when table of contents is rendered in primary navigation\n &--integrated &__link[for=\"__toc\"] ~ .md-nav {\n display: block;\n margin-bottom: 1.25em;\n border-left: px2rem(1px) solid var(--md-primary-fg-color);\n\n // Hide navigation title\n > .md-nav__title {\n display: none;\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-search-result-icon: svg-load(\"@mdi/svg/svg/file-search-outline.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Search\n.md-search {\n position: relative;\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n padding: px2rem(4px) 0;\n }\n\n // [no-js]: Hide search\n .no-js & {\n display: none;\n }\n\n // Search overlay\n &__overlay {\n z-index: 1;\n opacity: 0;\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n position: absolute;\n top: px2rem(4px);\n left: px2rem(-44px);\n width: px2rem(40px);\n height: px2rem(40px);\n overflow: hidden;\n background-color: var(--md-default-bg-color);\n border-radius: px2rem(20px);\n transform-origin: center;\n transition:\n transform 300ms 100ms,\n opacity 200ms 200ms;\n pointer-events: none;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(-44px);\n left: initial;\n }\n\n // Show overlay when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n opacity: 1;\n transition:\n transform 400ms,\n opacity 100ms;\n }\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n background-color: hsla(0, 0%, 0%, 0.54);\n cursor: pointer;\n transition:\n width 0ms 250ms,\n height 0ms 250ms,\n opacity 250ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: 0;\n left: initial;\n }\n\n // Show overlay when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n width: 100%;\n height: 100%;\n opacity: 1;\n transition:\n width 0ms,\n height 0ms,\n opacity 250ms;\n }\n }\n\n // Adjust appearance when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n\n // [mobile portrait -]: Scale up 45 times\n @include break-to-device(mobile portrait) {\n transform: scale(45);\n }\n\n // [mobile landscape]: Scale up 60 times\n @include break-at-device(mobile landscape) {\n transform: scale(60);\n }\n\n // [tablet portrait]: Scale up 75 times\n @include break-at-device(tablet portrait) {\n transform: scale(75);\n }\n }\n }\n\n // Search wrapper\n &__inner {\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n position: fixed;\n top: 0;\n left: 100%;\n z-index: 2;\n width: 100%;\n height: 100%;\n transform: translateX(5%);\n opacity: 0;\n transition:\n right 0ms 300ms,\n left 0ms 300ms,\n transform 150ms 150ms cubic-bezier(0.4, 0, 0.2, 1),\n opacity 150ms 150ms;\n\n // Adjust appearance when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n left: 0;\n transform: translateX(0);\n opacity: 1;\n transition:\n right 0ms 0ms,\n left 0ms 0ms,\n transform 150ms 150ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 150ms 150ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: 0;\n left: initial;\n }\n }\n\n // Adjust for right-to-left languages\n html [dir=\"rtl\"] & {\n right: 100%;\n left: initial;\n transform: translateX(-5%);\n }\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n position: relative;\n float: right;\n width: px2rem(234px);\n padding: px2rem(2px) 0;\n transition: width 250ms cubic-bezier(0.1, 0.7, 0.1, 1);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: left;\n }\n }\n\n // Adjust appearance when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n\n // [tablet landscape]: Omit overlaying header title\n @include break-at-device(tablet landscape) {\n width: px2rem(468px);\n }\n\n // [screen +]: Match width of content area\n @include break-from-device(screen) {\n width: px2rem(688px);\n }\n }\n }\n\n // Search form\n &__form {\n position: relative;\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n border-radius: px2rem(2px);\n }\n }\n\n // Search input\n &__input {\n position: relative;\n z-index: 2;\n padding: 0 px2rem(44px) 0 px2rem(72px);\n text-overflow: ellipsis;\n background-color: var(--md-default-bg-color);\n transition:\n color 250ms,\n background-color 250ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding: 0 px2rem(72px) 0 px2rem(44px);\n }\n\n // Search placeholder\n &::placeholder {\n transition: color 250ms;\n }\n\n // Search icon and placeholder\n ~ .md-search__icon,\n &::placeholder {\n color: var(--md-default-fg-color--light);\n }\n\n // Remove the \"x\" rendered by Internet Explorer\n &::-ms-clear {\n display: none;\n }\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n width: 100%;\n height: px2rem(48px);\n font-size: px2rem(18px);\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n width: 100%;\n height: px2rem(36px);\n padding-left: px2rem(44px);\n color: inherit;\n font-size: px2rem(16px);\n background-color: hsla(0, 0%, 0%, 0.26);\n border-radius: px2rem(2px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(44px);\n }\n\n // Search icon\n + .md-search__icon {\n color: var(--md-primary-bg-color);\n }\n\n // Search placeholder\n &::placeholder {\n color: var(--md-primary-bg-color--light);\n }\n\n // Search input on hover\n &:hover {\n background-color: hsla(0, 0%, 100%, 0.12);\n }\n\n // Adjust appearance when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n color: var(--md-default-fg-color);\n text-overflow: clip;\n background-color: var(--md-default-bg-color);\n border-radius: px2rem(2px) px2rem(2px) 0 0;\n\n // Search icon and placeholder\n + .md-search__icon,\n &::placeholder {\n color: var(--md-default-fg-color--light);\n }\n }\n }\n }\n\n // Search icon\n &__icon {\n position: absolute;\n z-index: 2;\n width: px2rem(24px);\n height: px2rem(24px);\n cursor: pointer;\n transition:\n color 250ms,\n opacity 250ms;\n\n // Search icon on hover\n &:hover {\n opacity: 0.7;\n }\n\n // Search focus button\n &[for=\"__search\"] {\n top: px2rem(6px);\n left: px2rem(10px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(10px);\n left: initial;\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1);\n }\n }\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n top: px2rem(12px);\n left: px2rem(16px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(16px);\n left: initial;\n }\n\n // Hide the magnifying glass\n svg:first-child {\n display: none;\n }\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n pointer-events: none;\n\n // Hide the back arrow\n svg:last-child {\n display: none;\n }\n }\n }\n\n // Search reset button\n &[type=\"reset\"] {\n top: px2rem(6px);\n right: px2rem(10px);\n transform: scale(0.75);\n opacity: 0;\n transition:\n transform 150ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 150ms;\n pointer-events: none;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(10px);\n }\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n top: px2rem(12px);\n right: px2rem(16px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(16px);\n }\n }\n\n // Show reset button when search is active and input non-empty\n [data-md-toggle=\"search\"]:checked ~ .md-header\n .md-search__input:valid ~ & {\n transform: scale(1);\n opacity: 1;\n pointer-events: initial;\n\n // Search focus icon\n &:hover {\n opacity: 0.7;\n }\n }\n }\n }\n\n // Search output\n &__output {\n position: absolute;\n z-index: 1;\n width: 100%;\n overflow: hidden;\n border-radius: 0 0 px2rem(2px) px2rem(2px);\n\n // [tablet portrait -]: Search modal\n @include break-to-device(tablet portrait) {\n top: px2rem(48px);\n bottom: 0;\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n top: px2rem(38px);\n opacity: 0;\n transition: opacity 400ms;\n\n // Show output when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n @include z-depth(6);\n\n opacity: 1;\n }\n }\n }\n\n // Search scroll wrapper\n &__scrollwrap {\n height: 100%;\n overflow-y: auto;\n background-color: var(--md-default-bg-color);\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n scroll-snap-type: y mandatory;\n touch-action: pan-y;\n\n // Mitigiate excessive repaints on non-retina devices\n @media (max-resolution: 1dppx) {\n transform: translateZ(0);\n }\n\n // [tablet landscape]: Set fixed width to omit unnecessary reflow\n @include break-at-device(tablet landscape) {\n width: px2rem(468px);\n }\n\n // [screen +]: Set fixed width to omit unnecessary reflow\n @include break-from-device(screen) {\n width: px2rem(688px);\n }\n\n // [tablet landscape +]: Limit height to viewport\n @include break-from-device(tablet landscape) {\n max-height: 0;\n scrollbar-width: thin;\n scrollbar-color: var(--md-default-fg-color--lighter) transparent;\n\n // Show scroll wrapper when search is active\n [data-md-toggle=\"search\"]:checked ~ .md-header & {\n max-height: 75vh;\n }\n\n // Search scroll wrapper on hover\n &:hover {\n scrollbar-color: var(--md-accent-fg-color) transparent;\n }\n\n // Webkit scrollbar\n &::-webkit-scrollbar {\n width: px2rem(4px);\n height: px2rem(4px);\n }\n\n // Webkit scrollbar thumb\n &::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n\n // Webkit scrollbar thumb on hover\n &:hover {\n background-color: var(--md-accent-fg-color);\n }\n }\n }\n }\n}\n\n// Search result\n.md-search-result {\n color: var(--md-default-fg-color);\n word-break: break-word;\n\n // Search result metadata\n &__meta {\n padding: 0 px2rem(16px);\n color: var(--md-default-fg-color--light);\n font-size: px2rem(12.8px);\n line-height: px2rem(36px);\n background-color: var(--md-default-fg-color--lightest);\n scroll-snap-align: start;\n\n // [tablet landscape +]: Adjust spacing\n @include break-from-device(tablet landscape) {\n padding-left: px2rem(44px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(44px);\n padding-left: initial;\n }\n }\n }\n\n // Search result list\n &__list {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n // Search result item\n &__item {\n box-shadow: 0 px2rem(-1px) 0 var(--md-default-fg-color--lightest);\n\n // Omit border on first child\n &:first-child {\n box-shadow: none;\n }\n }\n\n // Search result link\n &__link {\n display: block;\n outline: none;\n transition: background-color 250ms;\n scroll-snap-align: start;\n\n // Search result link on focus/hover\n &:focus,\n &:hover {\n background-color: var(--md-accent-fg-color--transparent);\n }\n\n // Adjust spacing on last child of last link\n &:last-child p:last-child {\n margin-bottom: px2rem(12px);\n }\n }\n\n // Search result more link\n &__more summary {\n display: block;\n padding: px2em(12px) px2rem(16px);\n color: var(--md-typeset-a-color);\n font-size: px2rem(12.8px);\n outline: 0;\n cursor: pointer;\n transition:\n color 250ms,\n background-color 250ms;\n scroll-snap-align: start;\n\n // [tablet landscape +]: Adjust spacing\n @include break-from-device(tablet landscape) {\n padding-left: px2rem(44px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(44px);\n padding-left: px2rem(16px);\n }\n }\n\n // Search result more link on focus/hover\n &:focus,\n &:hover {\n color: var(--md-accent-fg-color);\n background-color: var(--md-accent-fg-color--transparent);\n }\n\n // Hide native details marker\n &::-webkit-details-marker {\n display: none;\n }\n\n // Adjust transparency of less relevant results\n & ~ * > * {\n opacity: 0.65;\n }\n }\n\n // Search result article\n &__article {\n position: relative;\n padding: 0 px2rem(16px);\n overflow: hidden;\n\n // [tablet landscape +]: Adjust spacing\n @include break-from-device(tablet landscape) {\n padding-left: px2rem(44px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding-right: px2rem(44px);\n padding-left: px2rem(16px);\n }\n }\n\n // Search result article document\n &--document {\n\n // Search result title\n .md-search-result__title {\n margin: px2rem(11px) 0;\n font-weight: 400;\n font-size: px2rem(16px);\n line-height: 1.4;\n }\n }\n }\n\n // Search result icon\n &__icon {\n position: absolute;\n left: 0;\n width: px2rem(24px);\n height: px2rem(24px);\n margin: px2rem(10px);\n color: var(--md-default-fg-color--light);\n\n // [tablet portrait -]: Hide icon\n @include break-to-device(tablet portrait) {\n display: none;\n }\n\n // Search result icon content\n &::after {\n display: inline-block;\n width: 100%;\n height: 100%;\n background-color: currentColor;\n mask-image: var(--md-search-result-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: 0;\n left: initial;\n\n // Flip icon vertically\n &::after {\n transform: scaleX(-1);\n }\n }\n }\n\n // Search result title\n &__title {\n margin: 0.5em 0;\n font-weight: 700;\n font-size: px2rem(12.8px);\n line-height: 1.6;\n }\n\n // Search result teaser\n &__teaser {\n display: -webkit-box;\n max-height: px2rem(40px);\n margin: 0.5em 0;\n overflow: hidden;\n color: var(--md-default-fg-color--light);\n font-size: px2rem(12.8px);\n line-height: 1.6;\n text-overflow: ellipsis;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n\n // [mobile -]: Adjust number of lines\n @include break-to-device(mobile) {\n max-height: px2rem(60px);\n -webkit-line-clamp: 3;\n }\n\n // [tablet landscape]: Adjust number of lines\n @include break-at-device(tablet landscape) {\n max-height: px2rem(60px);\n -webkit-line-clamp: 3;\n }\n\n // Search term highlighting\n mark {\n text-decoration: underline;\n background-color: transparent;\n }\n }\n\n // Search result terms\n &__terms {\n margin: 0.5em 0;\n font-size: px2rem(12.8px);\n font-style: italic;\n }\n\n // Search term highlighting\n mark {\n color: var(--md-accent-fg-color);\n background-color: transparent;\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Sidebar\n.md-sidebar {\n position: sticky;\n top: px2rem(48px);\n flex-shrink: 0;\n align-self: flex-start;\n width: px2rem(242px);\n height: 0;\n padding: px2rem(24px) 0;\n\n // [print]: Hide sidebar\n @media print {\n display: none;\n }\n\n // [tablet -]: Show navigation as drawer\n @include break-to-device(tablet) {\n\n // Primary sidebar with navigation\n &--primary {\n position: fixed;\n top: 0;\n left: px2rem(-242px);\n z-index: 3;\n display: block;\n width: px2rem(242px);\n height: 100%;\n background-color: var(--md-default-bg-color);\n transform: translateX(0);\n transition:\n transform 250ms cubic-bezier(0.4, 0, 0.2, 1),\n box-shadow 250ms;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(-242px);\n left: initial;\n }\n\n // Show sidebar when drawer is active\n [data-md-toggle=\"drawer\"]:checked ~ .md-container & {\n @include z-depth(8);\n\n transform: translateX(px2rem(242px));\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(px2rem(-242px));\n }\n }\n\n // Stretch scroll wrapper for primary sidebar\n .md-sidebar__scrollwrap {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n margin: 0;\n scroll-snap-type: none;\n overflow: hidden;\n }\n }\n }\n\n // [screen +]: Show navigation as sidebar\n @include break-from-device(screen) {\n height: 0;\n\n // [no-js]: Switch to native sticky behavior\n .no-js & {\n height: auto;\n }\n }\n\n // Secondary sidebar with table of contents\n &--secondary {\n display: none;\n order: 2;\n\n // [tablet landscape +]: Show table of contents as sidebar\n @include break-from-device(tablet landscape) {\n height: 0;\n\n // [no-js]: Switch to native sticky behavior\n .no-js & {\n height: auto;\n }\n\n // Sidebar is visible\n &:not([hidden]) {\n display: block;\n }\n\n // Ensure smooth scrolling on iOS\n .md-sidebar__scrollwrap {\n touch-action: pan-y;\n }\n }\n }\n\n // Sidebar scroll wrapper\n &__scrollwrap {\n margin: 0 px2rem(4px);\n overflow-y: auto;\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n // Hack: Chrome 81+ exhibits a strange bug, where it scrolls the container\n // to the bottom if `scroll-snap-type` is set on the initial render. For\n // this reason, we disable scroll snapping until this is resolved (#1667).\n // scroll-snap-type: y mandatory;\n scrollbar-width: thin;\n scrollbar-color: var(--md-default-fg-color--lighter) transparent;\n\n // Sidebar scroll wrapper on hover\n &:hover {\n scrollbar-color: var(--md-accent-fg-color) transparent;\n }\n\n // Webkit scrollbar\n &::-webkit-scrollbar {\n width: px2rem(4px);\n height: px2rem(4px);\n }\n\n // Webkit scrollbar thumb\n &::-webkit-scrollbar-thumb {\n background-color: var(--md-default-fg-color--lighter);\n\n // Webkit scrollbar thumb on hover\n &:hover {\n background-color: var(--md-accent-fg-color);\n }\n }\n }\n}\n\n// [tablet -]: Show overlay on active drawer\n@include break-to-device(tablet) {\n\n // Sidebar overlay\n .md-overlay {\n position: fixed;\n top: 0;\n z-index: 3;\n width: 0;\n height: 0;\n background-color: hsla(0, 0%, 0%, 0.54);\n opacity: 0;\n transition:\n width 0ms 250ms,\n height 0ms 250ms,\n opacity 250ms;\n\n // Show overlay when drawer is active\n [data-md-toggle=\"drawer\"]:checked ~ & {\n width: 100%;\n height: 100%;\n opacity: 1;\n transition:\n width 0ms,\n height 0ms,\n opacity 250ms;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Keyframes\n// ----------------------------------------------------------------------------\n\n// Show source facts\n@keyframes md-source__facts--done {\n 0% {\n height: 0;\n }\n 100% {\n height: px2rem(13px);\n }\n}\n\n// Show source fact\n@keyframes md-source__fact--done {\n 0% {\n transform: translateY(100%);\n opacity: 0;\n }\n 50% {\n opacity: 0;\n }\n 100% {\n transform: translateY(0%);\n opacity: 1;\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Repository information\n.md-source {\n display: block;\n font-size: px2rem(13px);\n line-height: 1.2;\n white-space: nowrap;\n // Hack: promote to own layer to reduce jitter\n backface-visibility: hidden;\n transition: opacity 250ms;\n\n // Repository information on focus/hover\n &:focus,\n &:hover {\n opacity: 0.7;\n }\n\n // Repository icon\n &__icon {\n display: inline-block;\n width: px2rem(48px);\n height: px2rem(48px);\n vertical-align: middle;\n\n // Align with margin only (as opposed to normal button alignment)\n svg {\n margin-top: px2rem(12px);\n margin-left: px2rem(12px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(12px);\n margin-left: initial;\n }\n }\n\n // Adjust spacing if icon is present\n + .md-source__repository {\n margin-left: px2rem(-40px);\n padding-left: px2rem(40px);\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(-40px);\n margin-left: initial;\n padding-right: px2rem(40px);\n padding-left: initial;\n }\n }\n }\n\n // Repository name\n &__repository {\n display: inline-block;\n max-width: calc(100% - #{px2rem(24px)});\n margin-left: px2rem(12px);\n overflow: hidden;\n font-weight: 700;\n text-overflow: ellipsis;\n vertical-align: middle;\n }\n\n // Repository facts\n &__facts {\n margin: 0;\n padding: 0;\n overflow: hidden;\n font-weight: 700;\n font-size: px2rem(11px);\n list-style-type: none;\n opacity: 0.75;\n\n // Show after the data was loaded\n [data-md-state=\"done\"] & {\n animation: md-source__facts--done 250ms ease-in;\n }\n }\n\n // Repository fact\n &__fact {\n float: left;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n float: right;\n }\n\n // Show after the data was loaded\n [data-md-state=\"done\"] & {\n animation: md-source__fact--done 400ms ease-out;\n }\n\n // Middle dot before fact\n &::before {\n margin: 0 px2rem(2px);\n content: \"\\00B7\";\n }\n\n // Remove middle dot on first fact\n &:first-child::before {\n display: none;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Navigation tabs\n.md-tabs {\n width: 100%;\n overflow: auto;\n color: var(--md-primary-bg-color);\n background-color: var(--md-primary-fg-color);\n transition: background-color 250ms;\n\n // [print]: Hide tabs\n @media print {\n display: none;\n }\n\n // [tablet -]: Hide tabs\n @include break-to-device(tablet) {\n display: none;\n }\n\n // Tabs in hidden state, i.e. when scrolling down\n &[data-md-state=\"hidden\"] {\n pointer-events: none;\n }\n\n // Navigation tabs list\n &__list {\n margin: 0;\n margin-left: px2rem(4px);\n padding: 0;\n white-space: nowrap;\n list-style: none;\n contain: content;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(4px);\n margin-left: initial;\n }\n }\n\n // Navigation tabs item\n &__item {\n display: inline-block;\n height: px2rem(48px);\n padding-right: px2rem(12px);\n padding-left: px2rem(12px);\n }\n\n // Navigation tabs link - could be defined as block elements and aligned via\n // line height, but this would imply more repaints when scrolling\n &__link {\n display: block;\n margin-top: px2rem(16px);\n font-size: px2rem(14px);\n // Hack: save a repaint when tabs are appearing on scrolling up\n backface-visibility: hidden;\n opacity: 0.7;\n transition:\n transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1),\n opacity 250ms;\n\n // Active link and link on focus/hover\n &--active,\n &:focus,\n &:hover {\n color: inherit;\n opacity: 1;\n }\n\n // Delay transitions by a small amount\n @for $i from 2 through 16 {\n .md-tabs__item:nth-child(#{$i}) & {\n transition-delay: 20ms * ($i - 1);\n }\n }\n\n // Hide tabs upon scrolling - disable transition to minimizes repaints\n // while scrolling down, while scrolling up seems to be okay\n .md-tabs[data-md-state=\"hidden\"] & {\n transform: translateY(50%);\n opacity: 0;\n transition:\n transform 0ms 100ms,\n opacity 100ms;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Variables\n// ----------------------------------------------------------------------------\n\n/// Admonition flavours\n$admonitions: (\n note: pencil $clr-blue-a200,\n abstract summary tldr: text-subject $clr-light-blue-a400,\n info todo: information $clr-cyan-a700,\n tip hint important: fire $clr-teal-a700,\n success check done: check-circle $clr-green-a700,\n question help faq: help-circle $clr-light-green-a700,\n warning caution attention: alert $clr-orange-a400,\n failure fail missing: close-circle $clr-red-a200,\n danger error: flash-circle $clr-red-a400,\n bug: bug $clr-pink-a400,\n example: format-list-numbered $clr-deep-purple-a400,\n quote cite: format-quote-close $clr-grey\n) !default;\n\n// ----------------------------------------------------------------------------\n// Rules: layout\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n @each $names, $props in $admonitions {\n --md-admonition-icon--#{nth($names, 1)}: svg-load(\n \"@mdi/svg/svg/#{nth($props, 1)}.svg\"\n );\n }\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Admonition\n .admonition {\n margin: px2em(20px, 12.8px) 0;\n padding: 0 px2rem(12px);\n overflow: hidden;\n color: var(--md-admonition-fg-color);\n font-size: px2rem(12.8px);\n page-break-inside: avoid;\n background-color: var(--md-admonition-bg-color);\n border-left: px2rem(4px) solid $clr-blue-a200;\n border-radius: px2rem(2px);\n box-shadow:\n 0 px2rem(4px) px2rem(10px) hsla(0, 0%, 0%, 0.05),\n 0 px2rem(0.5px) px2rem(1px) hsla(0, 0%, 0%, 0.05);\n\n // [print]: Omit shadow as it may lead to rendering errors\n @media print {\n box-shadow: none;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n border-right: px2rem(4px) solid $clr-blue-a200;\n border-left: none;\n }\n\n // Adjust spacing for nested admonitions\n .admonition {\n margin: 1em 0;\n }\n\n // Adjust spacing for contained table wrappers\n .md-typeset__scrollwrap {\n margin: 1em px2rem(-12px);\n }\n\n // Adjust spacing for contained tables\n .md-typeset__table {\n padding: 0 px2rem(12px);\n }\n\n // Adjust spacing for single-child tabbed block container\n > .tabbed-set:only-child {\n margin-top: 0;\n }\n\n // Adjust spacing on last child\n html & > :last-child {\n margin-bottom: px2rem(12px);\n }\n }\n\n // Admonition title\n .admonition-title {\n position: relative;\n margin: 0 px2rem(-12px) 0 px2rem(-16px);\n padding: px2rem(8px) px2rem(12px) px2rem(8px) px2rem(40px);\n font-weight: 700;\n background-color: transparentize($clr-blue-a200, 0.9);\n border-left: px2rem(4px) solid $clr-blue-a200;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin: 0 px2rem(-16px) 0 px2rem(-12px);\n padding: px2rem(8px) px2rem(40px) px2rem(8px) px2rem(12px);\n border-right: px2rem(4px) solid $clr-blue-a200;\n border-left: none;\n }\n\n // Adjust spacing for title-only admonitions\n html &:last-child {\n margin-bottom: 0;\n }\n\n // Admonition icon\n &::before {\n position: absolute;\n left: px2rem(12px);\n width: px2rem(20px);\n height: px2rem(20px);\n background-color: $clr-blue-a200;\n mask-image: var(--md-admonition-icon--note);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2rem(12px);\n left: initial;\n }\n }\n\n // Omit background on inline code blocks, as they don't go well with the\n // pastelly tones applied to admonition titles\n code {\n margin: initial;\n padding: initial;\n color: currentColor;\n background-color: transparent;\n border-radius: initial;\n box-shadow: none;\n }\n\n // Adjust spacing on last tabbed block container child - if the tabbed\n // block container is the sole child, it looks better to omit the margin\n + .tabbed-set:last-child {\n margin-top: 0;\n }\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: flavours\n// ----------------------------------------------------------------------------\n\n@each $names, $props in $admonitions {\n $name: nth($names, 1);\n $tint: nth($props, 2);\n\n // Admonition flavour\n .md-typeset .admonition.#{$name} {\n border-color: $tint;\n }\n\n // Admonition flavour title\n .md-typeset .#{$name} > .admonition-title {\n background-color: transparentize($tint, 0.9);\n border-color: $tint;\n\n // Admonition icon\n &::before {\n background-color: $tint;\n mask-image: var(--md-admonition-icon--#{$name});\n mask-repeat: no-repeat;\n mask-size: contain;\n }\n }\n\n // Define synonyms for flavours\n @if length($names) > 1 {\n @for $n from 2 through length($names) {\n .#{nth($names, $n)} {\n @extend .#{$name};\n }\n }\n }\n}\n","// ==========================================================================\n//\n// Name: UI Color Palette\n// Description: The color palette of material design.\n// Version: 2.3.1\n//\n// Author: Denis Malinochkin\n// Git: https://github.com/mrmlnc/material-color\n//\n// twitter: @mrmlnc\n//\n// ==========================================================================\n\n\n//\n// List of base colors\n//\n\n// $clr-red\n// $clr-pink\n// $clr-purple\n// $clr-deep-purple\n// $clr-indigo\n// $clr-blue\n// $clr-light-blue\n// $clr-cyan\n// $clr-teal\n// $clr-green\n// $clr-light-green\n// $clr-lime\n// $clr-yellow\n// $clr-amber\n// $clr-orange\n// $clr-deep-orange\n// $clr-brown\n// $clr-grey\n// $clr-blue-grey\n// $clr-black\n// $clr-white\n\n\n//\n// Red\n//\n\n$clr-red-list: (\n \"base\": #f44336,\n \"50\": #ffebee,\n \"100\": #ffcdd2,\n \"200\": #ef9a9a,\n \"300\": #e57373,\n \"400\": #ef5350,\n \"500\": #f44336,\n \"600\": #e53935,\n \"700\": #d32f2f,\n \"800\": #c62828,\n \"900\": #b71c1c,\n \"a100\": #ff8a80,\n \"a200\": #ff5252,\n \"a400\": #ff1744,\n \"a700\": #d50000\n);\n\n$clr-red: map-get($clr-red-list, \"base\");\n\n$clr-red-50: map-get($clr-red-list, \"50\");\n$clr-red-100: map-get($clr-red-list, \"100\");\n$clr-red-200: map-get($clr-red-list, \"200\");\n$clr-red-300: map-get($clr-red-list, \"300\");\n$clr-red-400: map-get($clr-red-list, \"400\");\n$clr-red-500: map-get($clr-red-list, \"500\");\n$clr-red-600: map-get($clr-red-list, \"600\");\n$clr-red-700: map-get($clr-red-list, \"700\");\n$clr-red-800: map-get($clr-red-list, \"800\");\n$clr-red-900: map-get($clr-red-list, \"900\");\n$clr-red-a100: map-get($clr-red-list, \"a100\");\n$clr-red-a200: map-get($clr-red-list, \"a200\");\n$clr-red-a400: map-get($clr-red-list, \"a400\");\n$clr-red-a700: map-get($clr-red-list, \"a700\");\n\n\n//\n// Pink\n//\n\n$clr-pink-list: (\n \"base\": #e91e63,\n \"50\": #fce4ec,\n \"100\": #f8bbd0,\n \"200\": #f48fb1,\n \"300\": #f06292,\n \"400\": #ec407a,\n \"500\": #e91e63,\n \"600\": #d81b60,\n \"700\": #c2185b,\n \"800\": #ad1457,\n \"900\": #880e4f,\n \"a100\": #ff80ab,\n \"a200\": #ff4081,\n \"a400\": #f50057,\n \"a700\": #c51162\n);\n\n$clr-pink: map-get($clr-pink-list, \"base\");\n\n$clr-pink-50: map-get($clr-pink-list, \"50\");\n$clr-pink-100: map-get($clr-pink-list, \"100\");\n$clr-pink-200: map-get($clr-pink-list, \"200\");\n$clr-pink-300: map-get($clr-pink-list, \"300\");\n$clr-pink-400: map-get($clr-pink-list, \"400\");\n$clr-pink-500: map-get($clr-pink-list, \"500\");\n$clr-pink-600: map-get($clr-pink-list, \"600\");\n$clr-pink-700: map-get($clr-pink-list, \"700\");\n$clr-pink-800: map-get($clr-pink-list, \"800\");\n$clr-pink-900: map-get($clr-pink-list, \"900\");\n$clr-pink-a100: map-get($clr-pink-list, \"a100\");\n$clr-pink-a200: map-get($clr-pink-list, \"a200\");\n$clr-pink-a400: map-get($clr-pink-list, \"a400\");\n$clr-pink-a700: map-get($clr-pink-list, \"a700\");\n\n\n//\n// Purple\n//\n\n$clr-purple-list: (\n \"base\": #9c27b0,\n \"50\": #f3e5f5,\n \"100\": #e1bee7,\n \"200\": #ce93d8,\n \"300\": #ba68c8,\n \"400\": #ab47bc,\n \"500\": #9c27b0,\n \"600\": #8e24aa,\n \"700\": #7b1fa2,\n \"800\": #6a1b9a,\n \"900\": #4a148c,\n \"a100\": #ea80fc,\n \"a200\": #e040fb,\n \"a400\": #d500f9,\n \"a700\": #aa00ff\n);\n\n$clr-purple: map-get($clr-purple-list, \"base\");\n\n$clr-purple-50: map-get($clr-purple-list, \"50\");\n$clr-purple-100: map-get($clr-purple-list, \"100\");\n$clr-purple-200: map-get($clr-purple-list, \"200\");\n$clr-purple-300: map-get($clr-purple-list, \"300\");\n$clr-purple-400: map-get($clr-purple-list, \"400\");\n$clr-purple-500: map-get($clr-purple-list, \"500\");\n$clr-purple-600: map-get($clr-purple-list, \"600\");\n$clr-purple-700: map-get($clr-purple-list, \"700\");\n$clr-purple-800: map-get($clr-purple-list, \"800\");\n$clr-purple-900: map-get($clr-purple-list, \"900\");\n$clr-purple-a100: map-get($clr-purple-list, \"a100\");\n$clr-purple-a200: map-get($clr-purple-list, \"a200\");\n$clr-purple-a400: map-get($clr-purple-list, \"a400\");\n$clr-purple-a700: map-get($clr-purple-list, \"a700\");\n\n\n//\n// Deep purple\n//\n\n$clr-deep-purple-list: (\n \"base\": #673ab7,\n \"50\": #ede7f6,\n \"100\": #d1c4e9,\n \"200\": #b39ddb,\n \"300\": #9575cd,\n \"400\": #7e57c2,\n \"500\": #673ab7,\n \"600\": #5e35b1,\n \"700\": #512da8,\n \"800\": #4527a0,\n \"900\": #311b92,\n \"a100\": #b388ff,\n \"a200\": #7c4dff,\n \"a400\": #651fff,\n \"a700\": #6200ea\n);\n\n$clr-deep-purple: map-get($clr-deep-purple-list, \"base\");\n\n$clr-deep-purple-50: map-get($clr-deep-purple-list, \"50\");\n$clr-deep-purple-100: map-get($clr-deep-purple-list, \"100\");\n$clr-deep-purple-200: map-get($clr-deep-purple-list, \"200\");\n$clr-deep-purple-300: map-get($clr-deep-purple-list, \"300\");\n$clr-deep-purple-400: map-get($clr-deep-purple-list, \"400\");\n$clr-deep-purple-500: map-get($clr-deep-purple-list, \"500\");\n$clr-deep-purple-600: map-get($clr-deep-purple-list, \"600\");\n$clr-deep-purple-700: map-get($clr-deep-purple-list, \"700\");\n$clr-deep-purple-800: map-get($clr-deep-purple-list, \"800\");\n$clr-deep-purple-900: map-get($clr-deep-purple-list, \"900\");\n$clr-deep-purple-a100: map-get($clr-deep-purple-list, \"a100\");\n$clr-deep-purple-a200: map-get($clr-deep-purple-list, \"a200\");\n$clr-deep-purple-a400: map-get($clr-deep-purple-list, \"a400\");\n$clr-deep-purple-a700: map-get($clr-deep-purple-list, \"a700\");\n\n\n//\n// Indigo\n//\n\n$clr-indigo-list: (\n \"base\": #3f51b5,\n \"50\": #e8eaf6,\n \"100\": #c5cae9,\n \"200\": #9fa8da,\n \"300\": #7986cb,\n \"400\": #5c6bc0,\n \"500\": #3f51b5,\n \"600\": #3949ab,\n \"700\": #303f9f,\n \"800\": #283593,\n \"900\": #1a237e,\n \"a100\": #8c9eff,\n \"a200\": #536dfe,\n \"a400\": #3d5afe,\n \"a700\": #304ffe\n);\n\n$clr-indigo: map-get($clr-indigo-list, \"base\");\n\n$clr-indigo-50: map-get($clr-indigo-list, \"50\");\n$clr-indigo-100: map-get($clr-indigo-list, \"100\");\n$clr-indigo-200: map-get($clr-indigo-list, \"200\");\n$clr-indigo-300: map-get($clr-indigo-list, \"300\");\n$clr-indigo-400: map-get($clr-indigo-list, \"400\");\n$clr-indigo-500: map-get($clr-indigo-list, \"500\");\n$clr-indigo-600: map-get($clr-indigo-list, \"600\");\n$clr-indigo-700: map-get($clr-indigo-list, \"700\");\n$clr-indigo-800: map-get($clr-indigo-list, \"800\");\n$clr-indigo-900: map-get($clr-indigo-list, \"900\");\n$clr-indigo-a100: map-get($clr-indigo-list, \"a100\");\n$clr-indigo-a200: map-get($clr-indigo-list, \"a200\");\n$clr-indigo-a400: map-get($clr-indigo-list, \"a400\");\n$clr-indigo-a700: map-get($clr-indigo-list, \"a700\");\n\n\n//\n// Blue\n//\n\n$clr-blue-list: (\n \"base\": #2196f3,\n \"50\": #e3f2fd,\n \"100\": #bbdefb,\n \"200\": #90caf9,\n \"300\": #64b5f6,\n \"400\": #42a5f5,\n \"500\": #2196f3,\n \"600\": #1e88e5,\n \"700\": #1976d2,\n \"800\": #1565c0,\n \"900\": #0d47a1,\n \"a100\": #82b1ff,\n \"a200\": #448aff,\n \"a400\": #2979ff,\n \"a700\": #2962ff\n);\n\n$clr-blue: map-get($clr-blue-list, \"base\");\n\n$clr-blue-50: map-get($clr-blue-list, \"50\");\n$clr-blue-100: map-get($clr-blue-list, \"100\");\n$clr-blue-200: map-get($clr-blue-list, \"200\");\n$clr-blue-300: map-get($clr-blue-list, \"300\");\n$clr-blue-400: map-get($clr-blue-list, \"400\");\n$clr-blue-500: map-get($clr-blue-list, \"500\");\n$clr-blue-600: map-get($clr-blue-list, \"600\");\n$clr-blue-700: map-get($clr-blue-list, \"700\");\n$clr-blue-800: map-get($clr-blue-list, \"800\");\n$clr-blue-900: map-get($clr-blue-list, \"900\");\n$clr-blue-a100: map-get($clr-blue-list, \"a100\");\n$clr-blue-a200: map-get($clr-blue-list, \"a200\");\n$clr-blue-a400: map-get($clr-blue-list, \"a400\");\n$clr-blue-a700: map-get($clr-blue-list, \"a700\");\n\n\n//\n// Light Blue\n//\n\n$clr-light-blue-list: (\n \"base\": #03a9f4,\n \"50\": #e1f5fe,\n \"100\": #b3e5fc,\n \"200\": #81d4fa,\n \"300\": #4fc3f7,\n \"400\": #29b6f6,\n \"500\": #03a9f4,\n \"600\": #039be5,\n \"700\": #0288d1,\n \"800\": #0277bd,\n \"900\": #01579b,\n \"a100\": #80d8ff,\n \"a200\": #40c4ff,\n \"a400\": #00b0ff,\n \"a700\": #0091ea\n);\n\n$clr-light-blue: map-get($clr-light-blue-list, \"base\");\n\n$clr-light-blue-50: map-get($clr-light-blue-list, \"50\");\n$clr-light-blue-100: map-get($clr-light-blue-list, \"100\");\n$clr-light-blue-200: map-get($clr-light-blue-list, \"200\");\n$clr-light-blue-300: map-get($clr-light-blue-list, \"300\");\n$clr-light-blue-400: map-get($clr-light-blue-list, \"400\");\n$clr-light-blue-500: map-get($clr-light-blue-list, \"500\");\n$clr-light-blue-600: map-get($clr-light-blue-list, \"600\");\n$clr-light-blue-700: map-get($clr-light-blue-list, \"700\");\n$clr-light-blue-800: map-get($clr-light-blue-list, \"800\");\n$clr-light-blue-900: map-get($clr-light-blue-list, \"900\");\n$clr-light-blue-a100: map-get($clr-light-blue-list, \"a100\");\n$clr-light-blue-a200: map-get($clr-light-blue-list, \"a200\");\n$clr-light-blue-a400: map-get($clr-light-blue-list, \"a400\");\n$clr-light-blue-a700: map-get($clr-light-blue-list, \"a700\");\n\n\n//\n// Cyan\n//\n\n$clr-cyan-list: (\n \"base\": #00bcd4,\n \"50\": #e0f7fa,\n \"100\": #b2ebf2,\n \"200\": #80deea,\n \"300\": #4dd0e1,\n \"400\": #26c6da,\n \"500\": #00bcd4,\n \"600\": #00acc1,\n \"700\": #0097a7,\n \"800\": #00838f,\n \"900\": #006064,\n \"a100\": #84ffff,\n \"a200\": #18ffff,\n \"a400\": #00e5ff,\n \"a700\": #00b8d4\n);\n\n$clr-cyan: map-get($clr-cyan-list, \"base\");\n\n$clr-cyan-50: map-get($clr-cyan-list, \"50\");\n$clr-cyan-100: map-get($clr-cyan-list, \"100\");\n$clr-cyan-200: map-get($clr-cyan-list, \"200\");\n$clr-cyan-300: map-get($clr-cyan-list, \"300\");\n$clr-cyan-400: map-get($clr-cyan-list, \"400\");\n$clr-cyan-500: map-get($clr-cyan-list, \"500\");\n$clr-cyan-600: map-get($clr-cyan-list, \"600\");\n$clr-cyan-700: map-get($clr-cyan-list, \"700\");\n$clr-cyan-800: map-get($clr-cyan-list, \"800\");\n$clr-cyan-900: map-get($clr-cyan-list, \"900\");\n$clr-cyan-a100: map-get($clr-cyan-list, \"a100\");\n$clr-cyan-a200: map-get($clr-cyan-list, \"a200\");\n$clr-cyan-a400: map-get($clr-cyan-list, \"a400\");\n$clr-cyan-a700: map-get($clr-cyan-list, \"a700\");\n\n\n//\n// Teal\n//\n\n$clr-teal-list: (\n \"base\": #009688,\n \"50\": #e0f2f1,\n \"100\": #b2dfdb,\n \"200\": #80cbc4,\n \"300\": #4db6ac,\n \"400\": #26a69a,\n \"500\": #009688,\n \"600\": #00897b,\n \"700\": #00796b,\n \"800\": #00695c,\n \"900\": #004d40,\n \"a100\": #a7ffeb,\n \"a200\": #64ffda,\n \"a400\": #1de9b6,\n \"a700\": #00bfa5\n);\n\n$clr-teal: map-get($clr-teal-list, \"base\");\n\n$clr-teal-50: map-get($clr-teal-list, \"50\");\n$clr-teal-100: map-get($clr-teal-list, \"100\");\n$clr-teal-200: map-get($clr-teal-list, \"200\");\n$clr-teal-300: map-get($clr-teal-list, \"300\");\n$clr-teal-400: map-get($clr-teal-list, \"400\");\n$clr-teal-500: map-get($clr-teal-list, \"500\");\n$clr-teal-600: map-get($clr-teal-list, \"600\");\n$clr-teal-700: map-get($clr-teal-list, \"700\");\n$clr-teal-800: map-get($clr-teal-list, \"800\");\n$clr-teal-900: map-get($clr-teal-list, \"900\");\n$clr-teal-a100: map-get($clr-teal-list, \"a100\");\n$clr-teal-a200: map-get($clr-teal-list, \"a200\");\n$clr-teal-a400: map-get($clr-teal-list, \"a400\");\n$clr-teal-a700: map-get($clr-teal-list, \"a700\");\n\n\n//\n// Green\n//\n\n$clr-green-list: (\n \"base\": #4caf50,\n \"50\": #e8f5e9,\n \"100\": #c8e6c9,\n \"200\": #a5d6a7,\n \"300\": #81c784,\n \"400\": #66bb6a,\n \"500\": #4caf50,\n \"600\": #43a047,\n \"700\": #388e3c,\n \"800\": #2e7d32,\n \"900\": #1b5e20,\n \"a100\": #b9f6ca,\n \"a200\": #69f0ae,\n \"a400\": #00e676,\n \"a700\": #00c853\n);\n\n$clr-green: map-get($clr-green-list, \"base\");\n\n$clr-green-50: map-get($clr-green-list, \"50\");\n$clr-green-100: map-get($clr-green-list, \"100\");\n$clr-green-200: map-get($clr-green-list, \"200\");\n$clr-green-300: map-get($clr-green-list, \"300\");\n$clr-green-400: map-get($clr-green-list, \"400\");\n$clr-green-500: map-get($clr-green-list, \"500\");\n$clr-green-600: map-get($clr-green-list, \"600\");\n$clr-green-700: map-get($clr-green-list, \"700\");\n$clr-green-800: map-get($clr-green-list, \"800\");\n$clr-green-900: map-get($clr-green-list, \"900\");\n$clr-green-a100: map-get($clr-green-list, \"a100\");\n$clr-green-a200: map-get($clr-green-list, \"a200\");\n$clr-green-a400: map-get($clr-green-list, \"a400\");\n$clr-green-a700: map-get($clr-green-list, \"a700\");\n\n\n//\n// Light green\n//\n\n$clr-light-green-list: (\n \"base\": #8bc34a,\n \"50\": #f1f8e9,\n \"100\": #dcedc8,\n \"200\": #c5e1a5,\n \"300\": #aed581,\n \"400\": #9ccc65,\n \"500\": #8bc34a,\n \"600\": #7cb342,\n \"700\": #689f38,\n \"800\": #558b2f,\n \"900\": #33691e,\n \"a100\": #ccff90,\n \"a200\": #b2ff59,\n \"a400\": #76ff03,\n \"a700\": #64dd17\n);\n\n$clr-light-green: map-get($clr-light-green-list, \"base\");\n\n$clr-light-green-50: map-get($clr-light-green-list, \"50\");\n$clr-light-green-100: map-get($clr-light-green-list, \"100\");\n$clr-light-green-200: map-get($clr-light-green-list, \"200\");\n$clr-light-green-300: map-get($clr-light-green-list, \"300\");\n$clr-light-green-400: map-get($clr-light-green-list, \"400\");\n$clr-light-green-500: map-get($clr-light-green-list, \"500\");\n$clr-light-green-600: map-get($clr-light-green-list, \"600\");\n$clr-light-green-700: map-get($clr-light-green-list, \"700\");\n$clr-light-green-800: map-get($clr-light-green-list, \"800\");\n$clr-light-green-900: map-get($clr-light-green-list, \"900\");\n$clr-light-green-a100: map-get($clr-light-green-list, \"a100\");\n$clr-light-green-a200: map-get($clr-light-green-list, \"a200\");\n$clr-light-green-a400: map-get($clr-light-green-list, \"a400\");\n$clr-light-green-a700: map-get($clr-light-green-list, \"a700\");\n\n\n//\n// Lime\n//\n\n$clr-lime-list: (\n \"base\": #cddc39,\n \"50\": #f9fbe7,\n \"100\": #f0f4c3,\n \"200\": #e6ee9c,\n \"300\": #dce775,\n \"400\": #d4e157,\n \"500\": #cddc39,\n \"600\": #c0ca33,\n \"700\": #afb42b,\n \"800\": #9e9d24,\n \"900\": #827717,\n \"a100\": #f4ff81,\n \"a200\": #eeff41,\n \"a400\": #c6ff00,\n \"a700\": #aeea00\n);\n\n$clr-lime: map-get($clr-lime-list, \"base\");\n\n$clr-lime-50: map-get($clr-lime-list, \"50\");\n$clr-lime-100: map-get($clr-lime-list, \"100\");\n$clr-lime-200: map-get($clr-lime-list, \"200\");\n$clr-lime-300: map-get($clr-lime-list, \"300\");\n$clr-lime-400: map-get($clr-lime-list, \"400\");\n$clr-lime-500: map-get($clr-lime-list, \"500\");\n$clr-lime-600: map-get($clr-lime-list, \"600\");\n$clr-lime-700: map-get($clr-lime-list, \"700\");\n$clr-lime-800: map-get($clr-lime-list, \"800\");\n$clr-lime-900: map-get($clr-lime-list, \"900\");\n$clr-lime-a100: map-get($clr-lime-list, \"a100\");\n$clr-lime-a200: map-get($clr-lime-list, \"a200\");\n$clr-lime-a400: map-get($clr-lime-list, \"a400\");\n$clr-lime-a700: map-get($clr-lime-list, \"a700\");\n\n\n//\n// Yellow\n//\n\n$clr-yellow-list: (\n \"base\": #ffeb3b,\n \"50\": #fffde7,\n \"100\": #fff9c4,\n \"200\": #fff59d,\n \"300\": #fff176,\n \"400\": #ffee58,\n \"500\": #ffeb3b,\n \"600\": #fdd835,\n \"700\": #fbc02d,\n \"800\": #f9a825,\n \"900\": #f57f17,\n \"a100\": #ffff8d,\n \"a200\": #ffff00,\n \"a400\": #ffea00,\n \"a700\": #ffd600\n);\n\n$clr-yellow: map-get($clr-yellow-list, \"base\");\n\n$clr-yellow-50: map-get($clr-yellow-list, \"50\");\n$clr-yellow-100: map-get($clr-yellow-list, \"100\");\n$clr-yellow-200: map-get($clr-yellow-list, \"200\");\n$clr-yellow-300: map-get($clr-yellow-list, \"300\");\n$clr-yellow-400: map-get($clr-yellow-list, \"400\");\n$clr-yellow-500: map-get($clr-yellow-list, \"500\");\n$clr-yellow-600: map-get($clr-yellow-list, \"600\");\n$clr-yellow-700: map-get($clr-yellow-list, \"700\");\n$clr-yellow-800: map-get($clr-yellow-list, \"800\");\n$clr-yellow-900: map-get($clr-yellow-list, \"900\");\n$clr-yellow-a100: map-get($clr-yellow-list, \"a100\");\n$clr-yellow-a200: map-get($clr-yellow-list, \"a200\");\n$clr-yellow-a400: map-get($clr-yellow-list, \"a400\");\n$clr-yellow-a700: map-get($clr-yellow-list, \"a700\");\n\n\n//\n// amber\n//\n\n$clr-amber-list: (\n \"base\": #ffc107,\n \"50\": #fff8e1,\n \"100\": #ffecb3,\n \"200\": #ffe082,\n \"300\": #ffd54f,\n \"400\": #ffca28,\n \"500\": #ffc107,\n \"600\": #ffb300,\n \"700\": #ffa000,\n \"800\": #ff8f00,\n \"900\": #ff6f00,\n \"a100\": #ffe57f,\n \"a200\": #ffd740,\n \"a400\": #ffc400,\n \"a700\": #ffab00\n);\n\n$clr-amber: map-get($clr-amber-list, \"base\");\n\n$clr-amber-50: map-get($clr-amber-list, \"50\");\n$clr-amber-100: map-get($clr-amber-list, \"100\");\n$clr-amber-200: map-get($clr-amber-list, \"200\");\n$clr-amber-300: map-get($clr-amber-list, \"300\");\n$clr-amber-400: map-get($clr-amber-list, \"400\");\n$clr-amber-500: map-get($clr-amber-list, \"500\");\n$clr-amber-600: map-get($clr-amber-list, \"600\");\n$clr-amber-700: map-get($clr-amber-list, \"700\");\n$clr-amber-800: map-get($clr-amber-list, \"800\");\n$clr-amber-900: map-get($clr-amber-list, \"900\");\n$clr-amber-a100: map-get($clr-amber-list, \"a100\");\n$clr-amber-a200: map-get($clr-amber-list, \"a200\");\n$clr-amber-a400: map-get($clr-amber-list, \"a400\");\n$clr-amber-a700: map-get($clr-amber-list, \"a700\");\n\n\n//\n// Orange\n//\n\n$clr-orange-list: (\n \"base\": #ff9800,\n \"50\": #fff3e0,\n \"100\": #ffe0b2,\n \"200\": #ffcc80,\n \"300\": #ffb74d,\n \"400\": #ffa726,\n \"500\": #ff9800,\n \"600\": #fb8c00,\n \"700\": #f57c00,\n \"800\": #ef6c00,\n \"900\": #e65100,\n \"a100\": #ffd180,\n \"a200\": #ffab40,\n \"a400\": #ff9100,\n \"a700\": #ff6d00\n);\n\n$clr-orange: map-get($clr-orange-list, \"base\");\n\n$clr-orange-50: map-get($clr-orange-list, \"50\");\n$clr-orange-100: map-get($clr-orange-list, \"100\");\n$clr-orange-200: map-get($clr-orange-list, \"200\");\n$clr-orange-300: map-get($clr-orange-list, \"300\");\n$clr-orange-400: map-get($clr-orange-list, \"400\");\n$clr-orange-500: map-get($clr-orange-list, \"500\");\n$clr-orange-600: map-get($clr-orange-list, \"600\");\n$clr-orange-700: map-get($clr-orange-list, \"700\");\n$clr-orange-800: map-get($clr-orange-list, \"800\");\n$clr-orange-900: map-get($clr-orange-list, \"900\");\n$clr-orange-a100: map-get($clr-orange-list, \"a100\");\n$clr-orange-a200: map-get($clr-orange-list, \"a200\");\n$clr-orange-a400: map-get($clr-orange-list, \"a400\");\n$clr-orange-a700: map-get($clr-orange-list, \"a700\");\n\n\n//\n// Deep orange\n//\n\n$clr-deep-orange-list: (\n \"base\": #ff5722,\n \"50\": #fbe9e7,\n \"100\": #ffccbc,\n \"200\": #ffab91,\n \"300\": #ff8a65,\n \"400\": #ff7043,\n \"500\": #ff5722,\n \"600\": #f4511e,\n \"700\": #e64a19,\n \"800\": #d84315,\n \"900\": #bf360c,\n \"a100\": #ff9e80,\n \"a200\": #ff6e40,\n \"a400\": #ff3d00,\n \"a700\": #dd2c00\n);\n\n$clr-deep-orange: map-get($clr-deep-orange-list, \"base\");\n\n$clr-deep-orange-50: map-get($clr-deep-orange-list, \"50\");\n$clr-deep-orange-100: map-get($clr-deep-orange-list, \"100\");\n$clr-deep-orange-200: map-get($clr-deep-orange-list, \"200\");\n$clr-deep-orange-300: map-get($clr-deep-orange-list, \"300\");\n$clr-deep-orange-400: map-get($clr-deep-orange-list, \"400\");\n$clr-deep-orange-500: map-get($clr-deep-orange-list, \"500\");\n$clr-deep-orange-600: map-get($clr-deep-orange-list, \"600\");\n$clr-deep-orange-700: map-get($clr-deep-orange-list, \"700\");\n$clr-deep-orange-800: map-get($clr-deep-orange-list, \"800\");\n$clr-deep-orange-900: map-get($clr-deep-orange-list, \"900\");\n$clr-deep-orange-a100: map-get($clr-deep-orange-list, \"a100\");\n$clr-deep-orange-a200: map-get($clr-deep-orange-list, \"a200\");\n$clr-deep-orange-a400: map-get($clr-deep-orange-list, \"a400\");\n$clr-deep-orange-a700: map-get($clr-deep-orange-list, \"a700\");\n\n\n//\n// Brown\n//\n\n$clr-brown-list: (\n \"base\": #795548,\n \"50\": #efebe9,\n \"100\": #d7ccc8,\n \"200\": #bcaaa4,\n \"300\": #a1887f,\n \"400\": #8d6e63,\n \"500\": #795548,\n \"600\": #6d4c41,\n \"700\": #5d4037,\n \"800\": #4e342e,\n \"900\": #3e2723,\n);\n\n$clr-brown: map-get($clr-brown-list, \"base\");\n\n$clr-brown-50: map-get($clr-brown-list, \"50\");\n$clr-brown-100: map-get($clr-brown-list, \"100\");\n$clr-brown-200: map-get($clr-brown-list, \"200\");\n$clr-brown-300: map-get($clr-brown-list, \"300\");\n$clr-brown-400: map-get($clr-brown-list, \"400\");\n$clr-brown-500: map-get($clr-brown-list, \"500\");\n$clr-brown-600: map-get($clr-brown-list, \"600\");\n$clr-brown-700: map-get($clr-brown-list, \"700\");\n$clr-brown-800: map-get($clr-brown-list, \"800\");\n$clr-brown-900: map-get($clr-brown-list, \"900\");\n\n\n//\n// Grey\n//\n\n$clr-grey-list: (\n \"base\": #9e9e9e,\n \"50\": #fafafa,\n \"100\": #f5f5f5,\n \"200\": #eeeeee,\n \"300\": #e0e0e0,\n \"400\": #bdbdbd,\n \"500\": #9e9e9e,\n \"600\": #757575,\n \"700\": #616161,\n \"800\": #424242,\n \"900\": #212121,\n);\n\n$clr-grey: map-get($clr-grey-list, \"base\");\n\n$clr-grey-50: map-get($clr-grey-list, \"50\");\n$clr-grey-100: map-get($clr-grey-list, \"100\");\n$clr-grey-200: map-get($clr-grey-list, \"200\");\n$clr-grey-300: map-get($clr-grey-list, \"300\");\n$clr-grey-400: map-get($clr-grey-list, \"400\");\n$clr-grey-500: map-get($clr-grey-list, \"500\");\n$clr-grey-600: map-get($clr-grey-list, \"600\");\n$clr-grey-700: map-get($clr-grey-list, \"700\");\n$clr-grey-800: map-get($clr-grey-list, \"800\");\n$clr-grey-900: map-get($clr-grey-list, \"900\");\n\n\n//\n// Blue grey\n//\n\n$clr-blue-grey-list: (\n \"base\": #607d8b,\n \"50\": #eceff1,\n \"100\": #cfd8dc,\n \"200\": #b0bec5,\n \"300\": #90a4ae,\n \"400\": #78909c,\n \"500\": #607d8b,\n \"600\": #546e7a,\n \"700\": #455a64,\n \"800\": #37474f,\n \"900\": #263238,\n);\n\n$clr-blue-grey: map-get($clr-blue-grey-list, \"base\");\n\n$clr-blue-grey-50: map-get($clr-blue-grey-list, \"50\");\n$clr-blue-grey-100: map-get($clr-blue-grey-list, \"100\");\n$clr-blue-grey-200: map-get($clr-blue-grey-list, \"200\");\n$clr-blue-grey-300: map-get($clr-blue-grey-list, \"300\");\n$clr-blue-grey-400: map-get($clr-blue-grey-list, \"400\");\n$clr-blue-grey-500: map-get($clr-blue-grey-list, \"500\");\n$clr-blue-grey-600: map-get($clr-blue-grey-list, \"600\");\n$clr-blue-grey-700: map-get($clr-blue-grey-list, \"700\");\n$clr-blue-grey-800: map-get($clr-blue-grey-list, \"800\");\n$clr-blue-grey-900: map-get($clr-blue-grey-list, \"900\");\n\n\n//\n// Black\n//\n\n$clr-black-list: (\n \"base\": #000\n);\n\n$clr-black: map-get($clr-black-list, \"base\");\n\n\n//\n// White\n//\n\n$clr-white-list: (\n \"base\": #fff\n);\n\n$clr-white: map-get($clr-white-list, \"base\");\n\n\n//\n// List for all Colors for looping\n//\n\n$clr-list-all: (\n \"red\": $clr-red-list,\n \"pink\": $clr-pink-list,\n \"purple\": $clr-purple-list,\n \"deep-purple\": $clr-deep-purple-list,\n \"indigo\": $clr-indigo-list,\n \"blue\": $clr-blue-list,\n \"light-blue\": $clr-light-blue-list,\n \"cyan\": $clr-cyan-list,\n \"teal\": $clr-teal-list,\n \"green\": $clr-green-list,\n \"light-green\": $clr-light-green-list,\n \"lime\": $clr-lime-list,\n \"yellow\": $clr-yellow-list,\n \"amber\": $clr-amber-list,\n \"orange\": $clr-orange-list,\n \"deep-orange\": $clr-deep-orange-list,\n \"brown\": $clr-brown-list,\n \"grey\": $clr-grey-list,\n \"blue-grey\": $clr-blue-grey-list,\n \"black\": $clr-black-list,\n \"white\": $clr-white-list\n);\n\n\n//\n// Typography\n//\n\n$clr-ui-display-4: $clr-grey-600;\n$clr-ui-display-3: $clr-grey-600;\n$clr-ui-display-2: $clr-grey-600;\n$clr-ui-display-1: $clr-grey-600;\n$clr-ui-headline: $clr-grey-900;\n$clr-ui-title: $clr-grey-900;\n$clr-ui-subhead-1: $clr-grey-900;\n$clr-ui-body-2: $clr-grey-900;\n$clr-ui-body-1: $clr-grey-900;\n$clr-ui-caption: $clr-grey-600;\n$clr-ui-menu: $clr-grey-900;\n$clr-ui-button: $clr-grey-900;\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-footnotes-icon: svg-load(\"@mdi/svg/svg/keyboard-return.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Footnote reference\n [id^=\"fnref:\"]:target {\n scroll-margin-top: initial;\n margin-top: -1 * px2rem(48px + 24px - 4px);\n padding-top: px2rem(48px + 24px - 4px);\n }\n\n // Footnote\n [id^=\"fn:\"]:target {\n scroll-margin-top: initial;\n margin-top: -1 * px2rem(48px + 24px - 3px);\n padding-top: px2rem(48px + 24px - 3px);\n }\n\n // Footnote container\n .footnote {\n color: var(--md-default-fg-color--light);\n font-size: px2rem(12.8px);\n\n // Footnote list - omit left indentation\n ol {\n margin-left: 0;\n }\n\n // Footnote list item\n li {\n transition: color 125ms;\n\n // Darken color on target\n &:target {\n color: var(--md-default-fg-color);\n }\n\n // Show backreferences on footnote hover\n &:hover .footnote-backref,\n &:target .footnote-backref {\n transform: translateX(0);\n opacity: 1;\n }\n\n // Adjust spacing on first child\n > :first-child {\n margin-top: 0;\n }\n }\n }\n\n // Footnote backreference\n .footnote-backref {\n display: inline-block;\n color: var(--md-typeset-a-color);\n // Hack: omit Unicode arrow for replacement with icon\n font-size: 0;\n vertical-align: text-bottom;\n transform: translateX(px2rem(5px));\n opacity: 0;\n transition:\n color 250ms,\n transform 250ms 250ms,\n opacity 125ms 250ms;\n\n // [print]: Show footnote backreferences\n @media print {\n color: var(--md-typeset-a-color);\n transform: translateX(0);\n opacity: 1;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n transform: translateX(px2rem(-5px));\n }\n\n // Adjust color on hover\n &:hover {\n color: var(--md-accent-fg-color);\n }\n\n // Footnote backreference icon\n &::before {\n display: inline-block;\n width: px2rem(16px);\n height: px2rem(16px);\n background-color: currentColor;\n mask-image: var(--md-footnotes-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n\n // Flip icon vertically\n svg {\n transform: scaleX(-1)\n }\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Headerlink\n .headerlink {\n display: inline-block;\n margin-left: px2rem(10px);\n color: var(--md-default-fg-color--lighter);\n opacity: 0;\n transition:\n color 250ms,\n opacity 125ms;\n\n // [print]: Hide headerlinks\n @media print {\n display: none;\n }\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n margin-right: px2rem(10px);\n margin-left: initial;\n }\n }\n\n // Show headerlinks on parent hover\n :hover > .headerlink,\n :target > .headerlink,\n .headerlink:focus {\n opacity: 1;\n transition:\n color 250ms,\n opacity 125ms;\n }\n\n // Adjust color on parent target or focus/hover\n :target > .headerlink,\n .headerlink:focus,\n .headerlink:hover {\n color: var(--md-accent-fg-color);\n }\n\n // Adjust scroll offset for all elements with `id` attributes - general scroll\n // margin offset for anything that can be targeted. Browser support is pretty\n // decent by now, but Edge <79 and Safari (iOS and macOS) still don't support\n // it properly, so we settle with a cross-browser anchor correction solution.\n :target {\n scroll-margin-top: px2rem(48px + 24px);\n }\n\n // Adjust scroll offset for headlines of level 1-3\n h1:target,\n h2:target,\n h3:target {\n scroll-margin-top: initial;\n\n // Anchor correction hack\n &::before {\n display: block;\n margin-top: -1 * px2rem(48px + 24px - 4px);\n padding-top: px2rem(48px + 24px - 4px);\n content: \"\";\n }\n }\n\n // Adjust scroll offset for headlines of level 4\n h4:target {\n scroll-margin-top: initial;\n\n // Anchor correction hack\n &::before {\n display: block;\n margin-top: -1 * px2rem(48px + 24px - 3px);\n padding-top: px2rem(48px + 24px - 3px);\n content: \"\";\n }\n }\n\n // Adjust scroll offset for headlines of level 5-6\n h5:target,\n h6:target {\n scroll-margin-top: initial;\n\n // Anchor correction hack\n &::before {\n display: block;\n margin-top: -1 * px2rem(48px + 24px);\n padding-top: px2rem(48px + 24px);\n content: \"\";\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Arithmatex container\n div.arithmatex {\n overflow: auto;\n\n // [mobile -]: Align with body copy\n @include break-to-device(mobile) {\n margin: 0 px2rem(-16px);\n }\n\n // Arithmatex content\n > * {\n width: min-content;\n margin: 1em auto !important;\n padding: 0 px2rem(16px);\n touch-action: auto;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Deletions, additions and comments\n del.critic,\n ins.critic,\n .critic.comment {\n box-decoration-break: clone;\n }\n\n // Deletion\n del.critic {\n background-color: var(--md-typeset-del-color);\n }\n\n // Addition\n ins.critic {\n background-color: var(--md-typeset-ins-color);\n }\n\n // Comment\n .critic.comment {\n color: var(--md-code-hl-comment-color);\n\n // Comment opening mark\n &::before {\n content: \"/* \";\n }\n\n // Comment closing mark\n &::after {\n content: \" */\";\n }\n }\n\n // Critic block\n .critic.block {\n display: block;\n margin: 1em 0;\n padding-right: px2rem(16px);\n padding-left: px2rem(16px);\n overflow: auto;\n box-shadow: none;\n\n // Adjust spacing on first child\n > :first-child {\n margin-top: 0.5em;\n }\n\n // Adjust spacing on last child\n > :last-child {\n margin-bottom: 0.5em;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-details-icon: svg-load(\"@mdi/svg/svg/chevron-right.svg\");\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Details\n details {\n @extend .admonition;\n\n display: block;\n padding-top: 0;\n overflow: visible;\n\n // Details title icon - rotate icon on transition to open state\n &[open] > summary::after {\n transform: rotate(90deg);\n }\n\n // Adjust spacing for details in closed state\n &:not([open]) {\n padding-bottom: 0;\n box-shadow: none;\n\n // Hack: we cannot set `overflow: hidden` on the `details` element (which\n // is why we set it to `overflow: visible`, as the outline would not be\n // visible when focusing. Therefore, we must set the border radius on the\n // summary explicitly.\n > summary {\n border-radius: px2rem(2px);\n }\n }\n\n // Hack: omit margin collapse\n &::after {\n display: table;\n content: \"\";\n }\n }\n\n // Details title\n summary {\n @extend .admonition-title;\n\n display: block;\n min-height: px2rem(20px);\n padding: px2rem(8px) px2rem(36px) px2rem(8px) px2rem(40px);\n border-top-left-radius: px2rem(2px);\n border-top-right-radius: px2rem(2px);\n cursor: pointer;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n padding: px2rem(8px) px2rem(44px) px2rem(8px) px2rem(36px);\n }\n\n // Hide outline for pointer devices\n &:not(.focus-visible) {\n outline: none;\n -webkit-tap-highlight-color: transparent;\n }\n\n // Details marker\n &::after {\n position: absolute;\n top: px2rem(8px);\n right: px2rem(8px);\n width: px2rem(20px);\n height: px2rem(20px);\n background-color: currentColor;\n mask-image: var(--md-details-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n transform: rotate(0deg);\n transition: transform 250ms;\n content: \"\";\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: initial;\n left: px2rem(8px);\n transform: rotate(180deg);\n }\n }\n\n // Hide native details marker\n &::-webkit-details-marker {\n display: none;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Emoji and icon container\n .emojione,\n .twemoji,\n .gemoji {\n display: inline-block;\n height: px2em(18px);\n vertical-align: text-top;\n\n // Icon - inlined via mkdocs-material-extensions\n svg {\n width: px2em(18px);\n max-height: 100%;\n fill: currentColor;\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules: syntax highlighting\n// ----------------------------------------------------------------------------\n\n// Code block\n.highlight {\n\n .o, // Operator\n .ow { // Operator, word\n color: var(--md-code-hl-operator-color);\n }\n\n .p { // Punctuation\n color: var(--md-code-hl-punctuation-color);\n }\n\n .cpf, // Comment, preprocessor file\n .l, // Literal\n .s, // Literal, string\n .sb, // Literal, string backticks\n .sc, // Literal, string char\n .s2, // Literal, string double\n .si, // Literal, string interpol\n .s1, // Literal, string single\n .ss { // Literal, string symbol\n color: var(--md-code-hl-string-color);\n }\n\n .cp, // Comment, pre-processor\n .se, // Literal, string escape\n .sh, // Literal, string heredoc\n .sr, // Literal, string regex\n .sx { // Literal, string other\n color: var(--md-code-hl-special-color);\n }\n\n .m, // Number\n .mb, // Number, binary\n .mf, // Number, float\n .mh, // Number, hex\n .mi, // Number, integer\n .il, // Number, integer long\n .mo { // Number, octal\n color: var(--md-code-hl-number-color);\n }\n\n .k, // Keyword,\n .kd, // Keyword, declaration\n .kn, // Keyword, namespace\n .kp, // Keyword, pseudo\n .kr, // Keyword, reserved\n .kt { // Keyword, type\n color: var(--md-code-hl-keyword-color);\n }\n\n .kc, // Keyword, constant\n .n { // Name\n color: var(--md-code-hl-name-color);\n }\n\n .no, // Name, constant\n .nb, // Name, builtin\n .bp { // Name, builtin pseudo\n color: var(--md-code-hl-constant-color);\n }\n\n .nc, // Name, class\n .ne, // Name, exception\n .nf, // Name, function\n .nn { // Name, namespace\n color: var(--md-code-hl-function-color);\n }\n\n .nd, // Name, decorator\n .ni, // Name, entity\n .nl, // Name, label\n .nt { // Name, tag\n color: var(--md-code-hl-keyword-color);\n }\n\n .c, // Comment\n .cm, // Comment, multiline\n .c1, // Comment, single\n .ch, // Comment, shebang\n .cs, // Comment, special\n .sd { // Literal, string doc\n color: var(--md-code-hl-comment-color);\n }\n\n .na, // Name, attribute\n .nv, // Variable,\n .vc, // Variable, class\n .vg, // Variable, global\n .vi { // Variable, instance\n color: var(--md-code-hl-variable-color);\n }\n\n .ge, // Generic, emph\n .gr, // Generic, error\n .gh, // Generic, heading\n .go, // Generic, output\n .gp, // Generic, prompt\n .gs, // Generic, strong\n .gu, // Generic, subheading\n .gt { // Generic, traceback\n color: var(--md-code-hl-generic-color);\n }\n\n .gd, // Diff, delete\n .gi { // Diff, insert\n margin: 0 px2em(-2px);\n padding: 0 px2em(2px);\n border-radius: px2rem(2px);\n }\n\n .gd { // Diff, delete\n background-color: var(--md-typeset-del-color);\n }\n\n .gi { // Diff, insert\n background-color: var(--md-typeset-ins-color)\n }\n\n // Highlighted line\n .hll {\n display: block;\n margin: 0 px2em(-16px, 13.6px);\n padding: 0 px2em(16px, 13.6px);\n background-color: var(--md-code-hl-color)\n }\n\n // Code block line numbers (inline)\n [data-linenos]::before {\n position: sticky;\n left: px2em(-16px, 13.6px);\n float: left;\n margin-right: px2em(16px, 13.6px);\n margin-left: px2em(-16px, 13.6px);\n padding-left: px2em(16px, 13.6px);\n color: var(--md-default-fg-color--light);\n background-color: var(--md-code-bg-color);\n box-shadow: px2rem(-1px) 0 var(--md-default-fg-color--lightest) inset;\n content: attr(data-linenos);\n user-select: none;\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: layout\n// ----------------------------------------------------------------------------\n\n// Code block with line numbers\n.highlighttable {\n display: flow-root;\n overflow: hidden;\n\n // Set table elements to block layout, because otherwise the whole flexbox\n // hacking won't work correctly\n tbody,\n td {\n display: block;\n padding: 0;\n }\n\n // We need to use flexbox layout, because otherwise it's not possible to\n // make the code container scroll while keeping the line numbers static\n tr {\n display: flex;\n }\n\n // The pre tags are nested inside a table, so we need to omit the margin\n // because it collapses below all the overflows\n pre {\n margin: 0;\n }\n\n // Code block line numbers - disable user selection, so code can be easily\n // copied without accidentally also copying the line numbers\n .linenos {\n padding: px2em(10.5px, 13.6px) px2em(16px, 13.6px);\n padding-right: 0;\n font-size: px2em(13.6px);\n background-color: var(--md-code-bg-color);\n user-select: none;\n }\n\n // Code block line numbers container\n .linenodiv {\n padding-right: px2em(8px, 13.6px);\n box-shadow: px2rem(-1px) 0 var(--md-default-fg-color--lightest) inset;\n\n // Adjust colors and alignment\n pre {\n color: var(--md-default-fg-color--light);\n text-align: right;\n }\n }\n\n // Code block container - stretch to remaining space\n .code {\n flex: 1;\n overflow: hidden;\n }\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Code block with line numbers\n .highlighttable {\n margin: 1em 0;\n direction: ltr;\n border-radius: px2rem(2px);\n\n // Omit rounded borders on contained code block\n code {\n border-radius: 0;\n }\n }\n\n // [mobile -]: Align with body copy\n @include break-to-device(mobile) {\n\n // Top-level code block\n > .highlight {\n margin: 1em px2rem(-16px);\n\n // Highlighted line\n .hll {\n margin: 0 px2rem(-16px);\n padding: 0 px2rem(16px);\n }\n\n // Omit rounded borders\n code {\n border-radius: 0;\n }\n }\n\n // Top-level code block with line numbers\n > .highlighttable {\n margin: 1em px2rem(-16px);\n border-radius: 0;\n\n // Highlighted line\n .hll {\n margin: 0 px2rem(-16px);\n padding: 0 px2rem(16px);\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Keyboard key\n .keys {\n\n // Keyboard key icon\n kbd::before,\n kbd::after {\n position: relative;\n margin: 0;\n color: inherit;\n -moz-osx-font-smoothing: initial;\n -webkit-font-smoothing: initial;\n }\n\n // Surrounding text\n span {\n padding: 0 px2em(3.2px);\n color: var(--md-default-fg-color--light);\n }\n\n // Define keyboard keys with left icon\n @each $name, $code in (\n\n // Modifiers\n \"alt\": \"\\2387\",\n \"left-alt\": \"\\2387\",\n \"right-alt\": \"\\2387\",\n \"command\": \"\\2318\",\n \"left-command\": \"\\2318\",\n \"right-command\": \"\\2318\",\n \"control\": \"\\2303\",\n \"left-control\": \"\\2303\",\n \"right-control\": \"\\2303\",\n \"meta\": \"\\25C6\",\n \"left-meta\": \"\\25C6\",\n \"right-meta\": \"\\25C6\",\n \"option\": \"\\2325\",\n \"left-option\": \"\\2325\",\n \"right-option\": \"\\2325\",\n \"shift\": \"\\21E7\",\n \"left-shift\": \"\\21E7\",\n \"right-shift\": \"\\21E7\",\n \"super\": \"\\2756\",\n \"left-super\": \"\\2756\",\n \"right-super\": \"\\2756\",\n \"windows\": \"\\229E\",\n \"left-windows\": \"\\229E\",\n \"right-windows\": \"\\229E\",\n\n // Other keys\n \"arrow-down\": \"\\2193\",\n \"arrow-left\": \"\\2190\",\n \"arrow-right\": \"\\2192\",\n \"arrow-up\": \"\\2191\",\n \"backspace\": \"\\232B\",\n \"backtab\": \"\\21E4\",\n \"caps-lock\": \"\\21EA\",\n \"clear\": \"\\2327\",\n \"context-menu\": \"\\2630\",\n \"delete\": \"\\2326\",\n \"eject\": \"\\23CF\",\n \"end\": \"\\2913\",\n \"escape\": \"\\238B\",\n \"home\": \"\\2912\",\n \"insert\": \"\\2380\",\n \"page-down\": \"\\21DF\",\n \"page-up\": \"\\21DE\",\n \"print-screen\": \"\\2399\"\n ) {\n .key-#{$name} {\n &::before {\n padding-right: px2em(6.4px);\n content: $code;\n }\n }\n }\n\n // Define keyboard keys with right icon\n @each $name, $code in (\n \"tab\": \"\\21E5\",\n \"num-enter\": \"\\2324\",\n \"enter\": \"\\23CE\"\n ) {\n .key-#{$name} {\n &::after {\n padding-left: px2em(6.4px);\n content: $code;\n }\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Tabbed block content\n .tabbed-content {\n display: none;\n order: 99;\n width: 100%;\n box-shadow: 0 px2rem(-1px) var(--md-default-fg-color--lightest);\n\n // [print]: Show all tabs (even hidden ones) when printing\n @media print {\n display: block;\n order: initial;\n }\n\n // Code block is the only child of a tab - remove margin and mirror\n // previous (now deprecated) SuperFences code block grouping behavior\n > pre:only-child,\n > .highlight:only-child pre,\n > .highlighttable:only-child {\n margin: 0;\n\n // Omit rounded borders\n > code {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n }\n }\n\n // Adjust spacing for nested tab\n > .tabbed-set {\n margin: 0;\n }\n }\n\n // Tabbed block container\n .tabbed-set {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n margin: 1em 0;\n border-radius: px2rem(2px);\n\n // Tab radio button - the Tabbed extension will generate radio buttons with\n // labels, so tabs can be triggered without the necessity for JavaScript.\n // This is pretty cool, as it has great accessibility out-of-the box, so\n // we just hide the radio button and toggle the label color for indication.\n > input {\n position: absolute;\n width: 0;\n height: 0;\n opacity: 0;\n\n // Tab label for checked radio button\n &:checked + label {\n color: var(--md-accent-fg-color);\n border-color: var(--md-accent-fg-color);\n\n // Show tabbed block content\n & + .tabbed-content {\n display: block;\n }\n }\n\n // Tab label on focus\n &:focus + label {\n outline-style: auto;\n }\n\n // Hide outline for pointer devices\n &:not(.focus-visible) + label {\n outline: none;\n -webkit-tap-highlight-color: transparent;\n }\n }\n\n // Tab label\n > label {\n z-index: 1;\n width: auto;\n padding: px2em(12px, 12.8px) 1.25em px2em(10px, 12.8px);\n color: var(--md-default-fg-color--light);\n font-weight: 700;\n font-size: px2rem(12.8px);\n border-bottom: px2rem(2px) solid transparent;\n cursor: pointer;\n transition: color 250ms;\n\n // Tab label on hover\n &:hover {\n color: var(--md-accent-fg-color);\n }\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Icon definitions\n:root {\n --md-tasklist-icon: svg-load(\n \"@primer/octicons/build/svg/check-circle-fill-24.svg\"\n );\n --md-tasklist-icon--checked: svg-load(\n \"@primer/octicons/build/svg/check-circle-fill-24.svg\"\n );\n}\n\n// ----------------------------------------------------------------------------\n\n// Scoped in typesetted content to match specificity of regular content\n.md-typeset {\n\n // Tasklist item\n .task-list-item {\n position: relative;\n list-style-type: none;\n\n // Make checkbox items align with normal list items, but position\n // everything in ems for correct layout at smaller font sizes\n [type=\"checkbox\"] {\n position: absolute;\n top: 0.45em;\n left: -2em;\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: -2em;\n left: initial;\n }\n }\n }\n\n // Hide native checkbox, when custom classes are enabled\n .task-list-control [type=\"checkbox\"] {\n z-index: -1;\n opacity: 0;\n }\n\n // Tasklist indicator in unchecked state\n .task-list-indicator::before {\n position: absolute;\n top: 0.15em;\n left: px2em(-24px);\n width: px2em(20px);\n height: px2em(20px);\n background-color: var(--md-default-fg-color--lightest);\n mask-image: var(--md-tasklist-icon);\n mask-repeat: no-repeat;\n mask-size: contain;\n content: \"\";\n\n // Adjust for right-to-left languages\n [dir=\"rtl\"] & {\n right: px2em(-24px);\n left: initial;\n }\n }\n\n // Tasklist indicator in checked state\n [type=\"checkbox\"]:checked + .task-list-indicator::before {\n background-color: $clr-green-a400;\n mask-image: var(--md-tasklist-icon--checked);\n }\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/public/assets/stylesheets/palette.75751829.min.css b/public/assets/stylesheets/palette.75751829.min.css new file mode 100644 index 0000000..553b4a2 --- /dev/null +++ b/public/assets/stylesheets/palette.75751829.min.css @@ -0,0 +1,3 @@ +[data-md-color-accent=red]{--md-accent-fg-color: hsla(348, 100%, 55%, 1);--md-accent-fg-color--transparent: hsla(348, 100%, 55%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=pink]{--md-accent-fg-color: hsla(339, 100%, 48%, 1);--md-accent-fg-color--transparent: hsla(339, 100%, 48%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=purple]{--md-accent-fg-color: hsla(291, 96%, 62%, 1);--md-accent-fg-color--transparent: hsla(291, 96%, 62%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=deep-purple]{--md-accent-fg-color: hsla(256, 100%, 65%, 1);--md-accent-fg-color--transparent: hsla(256, 100%, 65%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=indigo]{--md-accent-fg-color: hsla(231, 99%, 66%, 1);--md-accent-fg-color--transparent: hsla(231, 99%, 66%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=blue]{--md-accent-fg-color: hsla(218, 100%, 63%, 1);--md-accent-fg-color--transparent: hsla(218, 100%, 63%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=light-blue]{--md-accent-fg-color: hsla(203, 100%, 46%, 1);--md-accent-fg-color--transparent: hsla(203, 100%, 46%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=cyan]{--md-accent-fg-color: hsla(188, 100%, 42%, 1);--md-accent-fg-color--transparent: hsla(188, 100%, 42%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=teal]{--md-accent-fg-color: hsla(172, 100%, 37%, 1);--md-accent-fg-color--transparent: hsla(172, 100%, 37%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=green]{--md-accent-fg-color: hsla(145, 100%, 39%, 1);--md-accent-fg-color--transparent: hsla(145, 100%, 39%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=light-green]{--md-accent-fg-color: hsla(97, 81%, 48%, 1);--md-accent-fg-color--transparent: hsla(97, 81%, 48%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-accent=lime]{--md-accent-fg-color: hsla(75, 100%, 46%, 1);--md-accent-fg-color--transparent: hsla(75, 100%, 46%, 0.1);--md-accent-bg-color: hsla(0, 0%, 0%, 0.87);--md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-accent=yellow]{--md-accent-fg-color: hsla(50, 100%, 50%, 1);--md-accent-fg-color--transparent: hsla(50, 100%, 50%, 0.1);--md-accent-bg-color: hsla(0, 0%, 0%, 0.87);--md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-accent=amber]{--md-accent-fg-color: hsla(40, 100%, 50%, 1);--md-accent-fg-color--transparent: hsla(40, 100%, 50%, 0.1);--md-accent-bg-color: hsla(0, 0%, 0%, 0.87);--md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-accent=orange]{--md-accent-fg-color: hsla(34, 100%, 50%, 1);--md-accent-fg-color--transparent: hsla(34, 100%, 50%, 0.1);--md-accent-bg-color: hsla(0, 0%, 0%, 0.87);--md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-accent=deep-orange]{--md-accent-fg-color: hsla(14, 100%, 63%, 1);--md-accent-fg-color--transparent: hsla(14, 100%, 63%, 0.1);--md-accent-bg-color: hsla(0, 0%, 100%, 1);--md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=red]{--md-primary-fg-color: hsla(1, 83%, 63%, 1);--md-primary-fg-color--light: hsla(0, 69%, 67%, 1);--md-primary-fg-color--dark: hsla(1, 77%, 55%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=pink]{--md-primary-fg-color: hsla(340, 82%, 52%, 1);--md-primary-fg-color--light: hsla(340, 82%, 59%, 1);--md-primary-fg-color--dark: hsla(336, 78%, 43%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=purple]{--md-primary-fg-color: hsla(291, 47%, 51%, 1);--md-primary-fg-color--light: hsla(291, 47%, 60%, 1);--md-primary-fg-color--dark: hsla(287, 65%, 40%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=deep-purple]{--md-primary-fg-color: hsla(262, 47%, 55%, 1);--md-primary-fg-color--light: hsla(262, 47%, 63%, 1);--md-primary-fg-color--dark: hsla(262, 52%, 47%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=indigo]{--md-primary-fg-color: hsla(231, 48%, 48%, 1);--md-primary-fg-color--light: hsla(231, 44%, 56%, 1);--md-primary-fg-color--dark: hsla(232, 54%, 41%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=blue]{--md-primary-fg-color: hsla(207, 90%, 54%, 1);--md-primary-fg-color--light: hsla(207, 90%, 61%, 1);--md-primary-fg-color--dark: hsla(210, 79%, 46%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=light-blue]{--md-primary-fg-color: hsla(199, 98%, 48%, 1);--md-primary-fg-color--light: hsla(199, 92%, 56%, 1);--md-primary-fg-color--dark: hsla(201, 98%, 41%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=cyan]{--md-primary-fg-color: hsla(187, 100%, 42%, 1);--md-primary-fg-color--light: hsla(187, 71%, 50%, 1);--md-primary-fg-color--dark: hsla(186, 100%, 33%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=teal]{--md-primary-fg-color: hsla(174, 100%, 29%, 1);--md-primary-fg-color--light: hsla(174, 63%, 40%, 1);--md-primary-fg-color--dark: hsla(173, 100%, 24%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=green]{--md-primary-fg-color: hsla(122, 39%, 49%, 1);--md-primary-fg-color--light: hsla(123, 38%, 57%, 1);--md-primary-fg-color--dark: hsla(123, 43%, 39%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=light-green]{--md-primary-fg-color: hsla(88, 50%, 53%, 1);--md-primary-fg-color--light: hsla(88, 50%, 60%, 1);--md-primary-fg-color--dark: hsla(92, 48%, 42%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=lime]{--md-primary-fg-color: hsla(66, 70%, 54%, 1);--md-primary-fg-color--light: hsla(66, 70%, 61%, 1);--md-primary-fg-color--dark: hsla(62, 61%, 44%, 1);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-primary=yellow]{--md-primary-fg-color: hsla(54, 100%, 62%, 1);--md-primary-fg-color--light: hsla(54, 100%, 67%, 1);--md-primary-fg-color--dark: hsla(43, 96%, 58%, 1);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-primary=amber]{--md-primary-fg-color: hsla(45, 100%, 51%, 1);--md-primary-fg-color--light: hsla(45, 100%, 58%, 1);--md-primary-fg-color--dark: hsla(38, 100%, 50%, 1);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-primary=orange]{--md-primary-fg-color: hsla(36, 100%, 57%, 1);--md-primary-fg-color--light: hsla(36, 100%, 57%, 1);--md-primary-fg-color--dark: hsla(33, 100%, 49%, 1);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54)}[data-md-color-primary=deep-orange]{--md-primary-fg-color: hsla(14, 100%, 63%, 1);--md-primary-fg-color--light: hsla(14, 100%, 70%, 1);--md-primary-fg-color--dark: hsla(14, 91%, 54%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=brown]{--md-primary-fg-color: hsla(16, 25%, 38%, 1);--md-primary-fg-color--light: hsla(16, 18%, 47%, 1);--md-primary-fg-color--dark: hsla(14, 26%, 29%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=grey]{--md-primary-fg-color: hsla(0, 0%, 46%, 1);--md-primary-fg-color--light: hsla(0, 0%, 62%, 1);--md-primary-fg-color--dark: hsla(0, 0%, 38%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=blue-grey]{--md-primary-fg-color: hsla(199, 18%, 40%, 1);--md-primary-fg-color--light: hsla(200, 18%, 46%, 1);--md-primary-fg-color--dark: hsla(199, 18%, 33%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7)}[data-md-color-primary=white]{--md-primary-fg-color: hsla(0, 0%, 100%, 1);--md-primary-fg-color--light: hsla(0, 0%, 100%, 0.7);--md-primary-fg-color--dark: hsla(0, 0%, 0%, 0.07);--md-primary-bg-color: hsla(0, 0%, 0%, 0.87);--md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54);--md-typeset-a-color: hsla(231, 48%, 48%, 1)}@media screen and (min-width: 60em){[data-md-color-primary=white] .md-search__input{background-color:rgba(0,0,0,.07)}[data-md-color-primary=white] .md-search__input+.md-search__icon{color:rgba(0,0,0,.87)}[data-md-color-primary=white] .md-search__input::-webkit-input-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::-moz-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::-ms-input-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input:hover{background-color:rgba(0,0,0,.32)}}@media screen and (min-width: 76.25em){[data-md-color-primary=white] .md-tabs{border-bottom:.05rem solid rgba(0,0,0,.07)}}[data-md-color-primary=black]{--md-primary-fg-color: hsla(0, 0%, 0%, 1);--md-primary-fg-color--light: hsla(0, 0%, 0%, 0.54);--md-primary-fg-color--dark: hsla(0, 0%, 0%, 1);--md-primary-bg-color: hsla(0, 0%, 100%, 1);--md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);--md-typeset-a-color: hsla(231, 48%, 48%, 1)}[data-md-color-primary=black] .md-header{background-color:#000}@media screen and (max-width: 59.9375em){[data-md-color-primary=black] .md-nav__source{background-color:rgba(0,0,0,.87)}}@media screen and (min-width: 60em){[data-md-color-primary=black] .md-search__input{background-color:rgba(255,255,255,.12)}[data-md-color-primary=black] .md-search__input:hover{background-color:rgba(255,255,255,.3)}}@media screen and (max-width: 76.1875em){html [data-md-color-primary=black] .md-nav--primary .md-nav__title[for=__drawer]{background-color:#000}}@media screen and (min-width: 76.25em){[data-md-color-primary=black] .md-tabs{background-color:#000}}@media screen{[data-md-color-scheme=slate]{--md-hue: 232;--md-default-fg-color: hsla(var(--md-hue), 75%, 95%, 1);--md-default-fg-color--light: hsla(var(--md-hue), 75%, 90%, 0.62);--md-default-fg-color--lighter: hsla(var(--md-hue), 75%, 90%, 0.32);--md-default-fg-color--lightest: hsla(var(--md-hue), 75%, 90%, 0.12);--md-default-bg-color: hsla(var(--md-hue), 15%, 21%, 1);--md-default-bg-color--light: hsla(var(--md-hue), 15%, 21%, 0.54);--md-default-bg-color--lighter: hsla(var(--md-hue), 15%, 21%, 0.26);--md-default-bg-color--lightest: hsla(var(--md-hue), 15%, 21%, 0.07);--md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1);--md-code-bg-color: hsla(var(--md-hue), 15%, 15%, 1);--md-code-hl-color: hsla(218, 100%, 63%, 0.15);--md-code-hl-number-color: hsla(6, 74%, 63%, 1);--md-code-hl-special-color: hsla(340, 83%, 66%, 1);--md-code-hl-function-color: hsla(291, 57%, 65%, 1);--md-code-hl-constant-color: hsla(250, 62%, 70%, 1);--md-code-hl-keyword-color: hsla(219, 66%, 64%, 1);--md-code-hl-string-color: hsla(150, 58%, 44%, 1);--md-typeset-a-color: var(--md-primary-fg-color--light);--md-typeset-mark-color: hsla(218, 100%, 63%, 0.3);--md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12);--md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2);--md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1);--md-admonition-bg-color: hsla(var(--md-hue), 0%, 100%, 0.025);--md-footer-bg-color: hsla(var(--md-hue), 15%, 12%, 0.87);--md-footer-bg-color--dark: hsla(var(--md-hue), 15%, 10%, 1)}[data-md-color-scheme=slate][data-md-color-primary=black],[data-md-color-scheme=slate][data-md-color-primary=white]{--md-typeset-a-color: hsla(231, 44%, 56%, 1)}} + +/*# sourceMappingURL=palette.75751829.min.css.map*/ \ No newline at end of file diff --git a/public/assets/stylesheets/palette.75751829.min.css.map b/public/assets/stylesheets/palette.75751829.min.css.map new file mode 100644 index 0000000..3c82193 --- /dev/null +++ b/public/assets/stylesheets/palette.75751829.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/assets/stylesheets/palette/_accent.scss","webpack:///./src/assets/stylesheets/palette/_primary.scss","webpack:///./src/assets/stylesheets/utilities/_break.scss","webpack:///./src/assets/stylesheets/palette/_scheme.scss"],"names":[],"mappings":"AA8CE,2BACE,8CACA,6DAOE,2CACA,oDAVJ,4BACE,8CACA,6DAOE,2CACA,oDAVJ,8BACE,6CACA,4DAOE,2CACA,oDAVJ,mCACE,8CACA,6DAOE,2CACA,oDAVJ,8BACE,6CACA,4DAOE,2CACA,oDAVJ,4BACE,8CACA,6DAOE,2CACA,oDAVJ,kCACE,8CACA,6DAOE,2CACA,oDAVJ,4BACE,8CACA,6DAOE,2CACA,oDAVJ,4BACE,8CACA,6DAOE,2CACA,oDAVJ,6BACE,8CACA,6DAOE,2CACA,oDAVJ,mCACE,4CACA,2DAOE,2CACA,oDAVJ,4BACE,6CACA,4DAIE,4CACA,mDAPJ,8BACE,6CACA,4DAIE,4CACA,mDAPJ,6BACE,6CACA,4DAIE,4CACA,mDAPJ,8BACE,6CACA,4DAIE,4CACA,mDAPJ,mCACE,6CACA,4DAOE,2CACA,oDCPJ,4BACE,4CACA,mDACA,kDAOE,4CACA,qDAXJ,6BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,+BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,oCACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,+BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,6BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,mCACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,6BACE,+CACA,qDACA,qDAOE,4CACA,qDAXJ,6BACE,+CACA,qDACA,qDAOE,4CACA,qDAXJ,8BACE,8CACA,qDACA,oDAOE,4CACA,qDAXJ,oCACE,6CACA,oDACA,mDAOE,4CACA,qDAXJ,6BACE,6CACA,oDACA,mDAIE,6CACA,oDARJ,+BACE,8CACA,qDACA,mDAIE,6CACA,oDARJ,8BACE,8CACA,qDACA,oDAIE,6CACA,oDARJ,+BACE,8CACA,qDACA,oDAIE,6CACA,oDARJ,oCACE,8CACA,qDACA,mDAOE,4CACA,qDAXJ,8BACE,6CACA,oDACA,mDAOE,4CACA,qDAXJ,6BACE,2CACA,kDACA,iDAOE,4CACA,qDAXJ,kCACE,8CACA,qDACA,oDAOE,4CACA,qDAUN,8BACE,4CACA,qDACA,mDACA,6CACA,oDAGA,6CC6GE,oCDvGA,gDACE,iCAGA,iEACE,sBAIF,2EACE,sBADF,kEACE,sBADF,uEACE,sBADF,6DACE,sBAIF,sDACE,kCCwFJ,uCD/EA,uCACE,4CAUN,8BACE,0CACA,oDACA,gDACA,4CACA,qDAGA,6CAGA,yCACE,sBC0EA,yCDnEA,8CACE,kCCgDF,oCDxCA,gDACE,uCAGA,sDACE,uCCqDJ,yCD5CA,iFACE,uBCyBF,uCDjBA,uCACE,uBEhJN,cAGE,6BAKE,cAGA,wDACA,kEACA,oEACA,qEACA,wDACA,kEACA,oEACA,qEAGA,qDACA,qDAGA,+CACA,gDACA,mDACA,oDACA,oDACA,mDACA,kDAGA,wDAGA,mDAGA,4DACA,kEACA,gEAGA,+DAGA,0DACA,6DAGA,oHAIE,8C","file":"assets/stylesheets/palette.75751829.min.css","sourcesContent":["////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n@each $name, $color in (\n \"red\": $clr-red-a400,\n \"pink\": $clr-pink-a400,\n \"purple\": $clr-purple-a200,\n \"deep-purple\": $clr-deep-purple-a200,\n \"indigo\": $clr-indigo-a200,\n \"blue\": $clr-blue-a200,\n \"light-blue\": $clr-light-blue-a700,\n \"cyan\": $clr-cyan-a700,\n \"teal\": $clr-teal-a700,\n \"green\": $clr-green-a700,\n \"light-green\": $clr-light-green-a700,\n \"lime\": $clr-lime-a700,\n \"yellow\": $clr-yellow-a700,\n \"amber\": $clr-amber-a700,\n \"orange\": $clr-orange-a400,\n \"deep-orange\": $clr-deep-orange-a200\n) {\n\n // Color palette\n [data-md-color-accent=\"#{$name}\"] {\n --md-accent-fg-color: hsla(#{hex2hsl($color)}, 1);\n --md-accent-fg-color--transparent: hsla(#{hex2hsl($color)}, 0.1);\n\n // Inverted text for lighter shades\n @if index(\"lime\" \"yellow\" \"amber\" \"orange\", $name) {\n --md-accent-bg-color: hsla(0, 0%, 0%, 0.87);\n --md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54);\n } @else {\n --md-accent-bg-color: hsla(0, 0%, 100%, 1);\n --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7);\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n@each $name, $colors in (\n \"red\": $clr-red-400 $clr-red-300 $clr-red-600,\n \"pink\": $clr-pink-500 $clr-pink-400 $clr-pink-700,\n \"purple\": $clr-purple-400 $clr-purple-300 $clr-purple-600,\n \"deep-purple\": $clr-deep-purple-400 $clr-deep-purple-300 $clr-deep-purple-500,\n \"indigo\": $clr-indigo-500 $clr-indigo-400 $clr-indigo-700,\n \"blue\": $clr-blue-500 $clr-blue-400 $clr-blue-700,\n \"light-blue\": $clr-light-blue-500 $clr-light-blue-400 $clr-light-blue-700,\n \"cyan\": $clr-cyan-500 $clr-cyan-400 $clr-cyan-700,\n \"teal\": $clr-teal-500 $clr-teal-400 $clr-teal-700,\n \"green\": $clr-green-500 $clr-green-400 $clr-green-700,\n \"light-green\": $clr-light-green-500 $clr-light-green-400 $clr-light-green-700,\n \"lime\": $clr-lime-500 $clr-lime-400 $clr-lime-700,\n \"yellow\": $clr-yellow-500 $clr-yellow-400 $clr-yellow-700,\n \"amber\": $clr-amber-500 $clr-amber-400 $clr-amber-700,\n \"orange\": $clr-orange-400 $clr-orange-400 $clr-orange-600,\n \"deep-orange\": $clr-deep-orange-400 $clr-deep-orange-300 $clr-deep-orange-600,\n \"brown\": $clr-brown-500 $clr-brown-400 $clr-brown-700,\n \"grey\": $clr-grey-600 $clr-grey-500 $clr-grey-700,\n \"blue-grey\": $clr-blue-grey-600 $clr-blue-grey-500 $clr-blue-grey-700\n) {\n\n // Color palette\n [data-md-color-primary=\"#{$name}\"] {\n --md-primary-fg-color: hsla(#{hex2hsl(nth($colors, 1))}, 1);\n --md-primary-fg-color--light: hsla(#{hex2hsl(nth($colors, 2))}, 1);\n --md-primary-fg-color--dark: hsla(#{hex2hsl(nth($colors, 3))}, 1);\n\n // Inverted text for lighter shades\n @if index(\"lime\" \"yellow\" \"amber\" \"orange\", $name) {\n --md-primary-bg-color: hsla(0, 0%, 0%, 0.87);\n --md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54);\n } @else {\n --md-primary-bg-color: hsla(0, 0%, 100%, 1);\n --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);\n }\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: white\n// ----------------------------------------------------------------------------\n\n// Color palette\n[data-md-color-primary=\"white\"] {\n --md-primary-fg-color: hsla(0, 0%, 100%, 1);\n --md-primary-fg-color--light: hsla(0, 0%, 100%, 0.7);\n --md-primary-fg-color--dark: hsla(0, 0%, 0%, 0.07);\n --md-primary-bg-color: hsla(0, 0%, 0%, 0.87);\n --md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54);\n\n // Typeset color shades\n --md-typeset-a-color: hsla(#{hex2hsl($clr-indigo-500)}, 1);\n\n // [tablet portrait +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n\n // Search input\n .md-search__input {\n background-color: hsla(0, 0%, 0%, 0.07);\n\n // Search icon color\n + .md-search__icon {\n color: hsla(0, 0%, 0%, 0.87);\n }\n\n // Placeholder color\n &::placeholder {\n color: hsla(0, 0%, 0%, 0.54);\n }\n\n // Hovered search field\n &:hover {\n background-color: hsla(0, 0%, 0%, 0.32);\n }\n }\n }\n\n // [screen +]: Add bottom border for tabs\n @include break-from-device(screen) {\n\n // Navigation tabs\n .md-tabs {\n border-bottom: px2rem(1px) solid hsla(0, 0%, 0%, 0.07);\n }\n }\n}\n\n// ----------------------------------------------------------------------------\n// Rules: black\n// ----------------------------------------------------------------------------\n\n// Color palette\n[data-md-color-primary=\"black\"] {\n --md-primary-fg-color: hsla(0, 0%, 0%, 1);\n --md-primary-fg-color--light: hsla(0, 0%, 0%, 0.54);\n --md-primary-fg-color--dark: hsla(0, 0%, 0%, 1);\n --md-primary-bg-color: hsla(0, 0%, 100%, 1);\n --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7);\n\n // Text color shades\n --md-typeset-a-color: hsla(#{hex2hsl($clr-indigo-500)}, 1);\n\n // Header\n .md-header {\n background-color: hsla(0, 0%, 0%, 1);\n }\n\n // [tablet portrait -]: Layered navigation\n @include break-to-device(tablet portrait) {\n\n // Repository information container\n .md-nav__source {\n background-color: hsla(0, 0%, 0%, 0.87);\n }\n }\n\n // [tablet landscape +]: Header-embedded search\n @include break-from-device(tablet landscape) {\n\n // Search input\n .md-search__input {\n background-color: hsla(0, 0%, 100%, 0.12);\n\n // Search form on hover\n &:hover {\n background-color: hsla(0, 0%, 100%, 0.3);\n }\n }\n }\n\n // [tablet -]: Layered navigation\n @include break-to-device(tablet) {\n\n // Site title in main navigation\n html & .md-nav--primary .md-nav__title[for=\"__drawer\"] {\n background-color: hsla(0, 0%, 0%, 1);\n }\n }\n\n // [screen +]: Set background color for tabs\n @include break-from-device(screen) {\n\n // Navigation tabs\n .md-tabs {\n background-color: hsla(0, 0%, 0%, 1);\n }\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Variables\n// ----------------------------------------------------------------------------\n\n///\n/// Device-specific breakpoints\n///\n/// @example\n/// $break-devices: (\n/// mobile: (\n/// portrait: 220px 479px,\n/// landscape: 480px 719px\n/// ),\n/// tablet: (\n/// portrait: 720px 959px,\n/// landscape: 960px 1219px\n/// ),\n/// screen: (\n/// small: 1220px 1599px,\n/// medium: 1600px 1999px,\n/// large: 2000px\n/// )\n/// );\n///\n$break-devices: () !default;\n\n// ----------------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------------\n\n///\n/// Choose minimum and maximum device widths\n///\n@function break-select-min-max($devices) {\n $min: 1000000;\n $max: 0;\n @each $key, $value in $devices {\n @while type-of($value) == map {\n $value: break-select-min-max($value);\n }\n @if type-of($value) == list {\n @each $number in $value {\n @if type-of($number) == number {\n $min: min($number, $min);\n @if $max != null {\n $max: max($number, $max);\n }\n } @else {\n @error \"Invalid number: #{$number}\";\n }\n }\n } @else if type-of($value) == number {\n $min: min($value, $min);\n $max: null;\n } @else {\n @error \"Invalid value: #{$value}\";\n }\n }\n @return $min, $max;\n}\n\n///\n/// Select minimum and maximum widths for a device breakpoint\n///\n@function break-select-device($device) {\n $current: $break-devices;\n @for $n from 1 through length($device) {\n @if type-of($current) == map {\n $current: map-get($current, nth($device, $n));\n } @else {\n @error \"Invalid device map: #{$devices}\";\n }\n }\n @if type-of($current) == list or type-of($current) == number {\n $current: (default: $current);\n }\n @return break-select-min-max($current);\n}\n\n// ----------------------------------------------------------------------------\n// Mixins\n// ----------------------------------------------------------------------------\n\n///\n/// A minimum-maximum media query breakpoint\n///\n@mixin break-at($breakpoint) {\n @if type-of($breakpoint) == number {\n @media screen and (min-width: $breakpoint) {\n @content;\n }\n } @else if type-of($breakpoint) == list {\n $min: nth($breakpoint, 1);\n $max: nth($breakpoint, 2);\n @if type-of($min) == number and type-of($max) == number {\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// An orientation media query breakpoint\n///\n@mixin break-at-orientation($breakpoint) {\n @if type-of($breakpoint) == string {\n @media screen and (orientation: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A maximum-aspect-ratio media query breakpoint\n///\n@mixin break-at-ratio($breakpoint) {\n @if type-of($breakpoint) == number {\n @media screen and (max-aspect-ratio: $breakpoint) {\n @content;\n }\n } @else {\n @error \"Invalid breakpoint: #{$breakpoint}\";\n }\n}\n\n///\n/// A minimum-maximum media query device breakpoint\n///\n@mixin break-at-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n @if nth($breakpoint, 2) != null {\n $min: nth($breakpoint, 1);\n $max: nth($breakpoint, 2);\n @media screen and (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A minimum media query device breakpoint\n///\n@mixin break-from-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n $min: nth($breakpoint, 1);\n @media screen and (min-width: $min) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n\n///\n/// A maximum media query device breakpoint\n///\n@mixin break-to-device($device) {\n @if type-of($device) == string {\n $device: $device,;\n }\n @if type-of($device) == list {\n $breakpoint: break-select-device($device);\n $max: nth($breakpoint, 2);\n @media screen and (max-width: $max) {\n @content;\n }\n } @else {\n @error \"Invalid device: #{$device}\";\n }\n}\n","////\n/// Copyright (c) 2016-2020 Martin Donath \n///\n/// Permission is hereby granted, free of charge, to any person obtaining a\n/// copy of this software and associated documentation files (the \"Software\"),\n/// to deal in the Software without restriction, including without limitation\n/// the rights to use, copy, modify, merge, publish, distribute, sublicense,\n/// and/or sell copies of the Software, and to permit persons to whom the\n/// Software is furnished to do so, subject to the following conditions:\n///\n/// The above copyright notice and this permission notice shall be included in\n/// all copies or substantial portions of the Software.\n///\n/// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL\n/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n/// DEALINGS\n////\n\n// ----------------------------------------------------------------------------\n// Rules\n// ----------------------------------------------------------------------------\n\n// Only use dark mode on screens\n@media screen {\n\n // Slate theme, i.e. dark mode\n [data-md-color-scheme=\"slate\"] {\n\n // Slate's hue in the range [0,360] - change this variable to alter the tone\n // of the theme, e.g. to make it more redish or greenish. This is a slate-\n // specific variable, but the same approach may be adapted to custom themes.\n --md-hue: 232;\n\n // Default color shades\n --md-default-fg-color: hsla(var(--md-hue), 75%, 95%, 1);\n --md-default-fg-color--light: hsla(var(--md-hue), 75%, 90%, 0.62);\n --md-default-fg-color--lighter: hsla(var(--md-hue), 75%, 90%, 0.32);\n --md-default-fg-color--lightest: hsla(var(--md-hue), 75%, 90%, 0.12);\n --md-default-bg-color: hsla(var(--md-hue), 15%, 21%, 1);\n --md-default-bg-color--light: hsla(var(--md-hue), 15%, 21%, 0.54);\n --md-default-bg-color--lighter: hsla(var(--md-hue), 15%, 21%, 0.26);\n --md-default-bg-color--lightest: hsla(var(--md-hue), 15%, 21%, 0.07);\n\n // Code color shades\n --md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 1);\n --md-code-bg-color: hsla(var(--md-hue), 15%, 15%, 1);\n\n // Code highlighting color shades\n --md-code-hl-color: hsla(#{hex2hsl($clr-blue-a200)}, 0.15);\n --md-code-hl-number-color: hsla(6, 74%, 63%, 1);\n --md-code-hl-special-color: hsla(340, 83%, 66%, 1);\n --md-code-hl-function-color: hsla(291, 57%, 65%, 1);\n --md-code-hl-constant-color: hsla(250, 62%, 70%, 1);\n --md-code-hl-keyword-color: hsla(219, 66%, 64%, 1);\n --md-code-hl-string-color: hsla(150, 58%, 44%, 1);\n\n // Typeset color shades\n --md-typeset-a-color: var(--md-primary-fg-color--light);\n\n // Typeset `mark` color shades\n --md-typeset-mark-color: hsla(#{hex2hsl($clr-blue-a200)}, 0.3);\n\n // Typeset `kbd` color shades\n --md-typeset-kbd-color: hsla(var(--md-hue), 15%, 94%, 0.12);\n --md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 94%, 0.2);\n --md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1);\n\n // Admonition color shades\n --md-admonition-bg-color: hsla(var(--md-hue), 0%, 100%, 0.025);\n\n // Footer color shades\n --md-footer-bg-color: hsla(var(--md-hue), 15%, 12%, 0.87);\n --md-footer-bg-color--dark: hsla(var(--md-hue), 15%, 10%, 1);\n\n // Black and white primary colors\n &[data-md-color-primary=\"black\"],\n &[data-md-color-primary=\"white\"] {\n\n // Typeset color shades\n --md-typeset-a-color: hsla(#{hex2hsl($clr-indigo-400)}, 1);\n }\n }\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/public/cryptography/asymmetric/edwards25519/index.html b/public/cryptography/asymmetric/edwards25519/index.html new file mode 100644 index 0000000..a2ba117 --- /dev/null +++ b/public/cryptography/asymmetric/edwards25519/index.html @@ -0,0 +1,1204 @@ + + + + + + + + + + + + + + + + + + + + + + + Edwards25519 Elliptic Curve - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Edwards25519 Elliptic Curve

    +
    +

    Note

    +

    Author is nowhere close to being a cryptographer. Be sceptical on accuracy.

    +
    +
    +

    Note

    +

    This article is only about the underlying curve. Public key derivation and signing algorithm will be treated separately.

    +
    +

    Monero employs edwards25519 elliptic curve as a basis for its key pair generation.

    +

    The curve comes from the Ed25519 signature scheme. While Monero takes the curve unchanged, it does not exactly follow rest of the Ed25519.

    +

    The edwards25519 curve is birationally equivalent to Curve25519.

    +

    Definition

    +

    This is the standard edwards25519 curve definition, no Monero specific stuff here, +except the naming convention. The convention comes from the CryptoNote +whitepaper and is widely used in Monero literature.

    +

    Curve equation

    +
    −x^2 + y^2 = 1 − (121665/121666) * x^2 * y^2
    +
    +

    Note:

    +
      +
    • curve is in two dimensions (nothing fancy, like all the curves is high school)
    • +
    • curve is mirrored below y axis due to y^2 part of the equation (not a polynomial)
    • +
    +

    Base point: G

    +

    The base point is a specific point on the curve. It is used +as a basis for further calculations. It is an arbitrary choice +by the curve authors, just to standardize the scheme.

    +

    Note that it is enough to specify the y value and the sign of the x value. +That's because the specific x can be calculated from the curve equation.

    +
    G = (x, 4/5)  # take the point with the positive x
    +
    +# The hex representation of the base point
    +5866666666666666666666666666666666666666666666666666666666666666
    +
    +

    Prime order of the base point: l

    +

    In layment terms, the "canvas" where the curve is drawn is assumed +to have a finite "resolution", so point coordinates must "wrap around" +at some point. This is achieved by modulo the l value (lowercase L). +In other words, the l defines the maximum scalar we can use.

    +
    l = 2^252 + 27742317777372353535851937790883648493
    +# => 7237005577332262213973186563042994240857116359379907606001950938285454250989
    +
    +

    The l is a prime number specified by the curve authors.

    +

    In practice this is the private key's strength.

    +

    Total number of points on the curve

    +

    The total number of points on the curve is also a prime number:

    +
    q = 2^255 - 19
    +
    +

    In practice not all points are "useful" and so the private key strength is limited to l describe above.

    +

    Implementation

    +

    Monero uses (apparently modified) Ref10 implementation by Daniel J. Bernstein.

    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/cryptography/asymmetric/introduction/index.html b/public/cryptography/asymmetric/introduction/index.html new file mode 100644 index 0000000..10bc0b7 --- /dev/null +++ b/public/cryptography/asymmetric/introduction/index.html @@ -0,0 +1,1018 @@ + + + + + + + + + + + + + + + + + + + + + + + Asymmetric Cryptography in Moner - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Asymmetric Cryptography in Monero

    +
    +

    Note

    +

    Author is nowhere close to being a cryptographer. Be sceptical on accuracy.

    +
    +

    Before we get to Monero specific stuff, a little bit of context. We are talking asymmetric cryptography here. +The "asymmetric" simply means the are two keys:

    +
      +
    • the private key (used primarily for signing data and for decrypting data)
    • +
    • the public key (used primarily for signature verification and encrypting data)
    • +
    +

    This is in contrast to symmetric cryptography which uses a single key. This key is a secret shared among the parties.

    +

    Historically, asymmetric cryptography was based on the problem of factorization of a very large integers +back into prime numbers (which is practically impossible for large enough integers).

    +

    Recently, asymmetric cryptography is based on a mathematical notion of elliptic curves. +Edwards25519 is a specific, well researched and standardized elliptic curve used in Monero.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/cryptography/asymmetric/key-image/index.html b/public/cryptography/asymmetric/key-image/index.html new file mode 100644 index 0000000..b16a4fd --- /dev/null +++ b/public/cryptography/asymmetric/key-image/index.html @@ -0,0 +1,1098 @@ + + + + + + + + + + + + + + + + + + + + + + + Monero Private Key Image - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Monero Private Key Image

    +
    +

    Note

    +

    Author is nowhere close to being a cryptographer. Be sceptical on accuracy.

    +
    +

    Private key image serves to detect double spending attempts.

    +

    In Monero funds are always sent to a one-time public key P. +Related one-time private key x is specific to unspent output.

    +

    As output can be spent only once (in whole), the related private key can be used only once as well.

    +

    Thus, specific private key image I being present on the blockchain means +that related output was already spent, and subsequent attempts must not be allowed.

    +

    This whole scheme is necessary because Monero uses Ring Signatures +which make it impossible to know whom exactly signed the transaction. +This is why a simple Bitcoin-like double spending check wouldn't work here.

    +

    Definition

    +
    I = x*Hp(P)
    +
    +

    Where:

    +
      +
    • I - private key image (or "key image" for short)
    • +
    • x - one-time private key used to unlock an unspent output
    • +
    • P - one-time public key of an unspent output
    • +
    • Hp() - hash function accepting an EC point as an argument
    • +
    +

    The P comes from this:

    +
    P = xG
    +
    +

    Where G is the edwards25519 base point.

    +

    Substitute P with xG and we get:

    +
    I = x*Hp(xG)
    +
    +

    The key image I is a one-way function of the private key x.

    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/cryptography/asymmetric/private-key/index.html b/public/cryptography/asymmetric/private-key/index.html new file mode 100644 index 0000000..34815b1 --- /dev/null +++ b/public/cryptography/asymmetric/private-key/index.html @@ -0,0 +1,1165 @@ + + + + + + + + + + + + + + + + + + + + + + + Private Keys in Monero - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Private Keys in Monero

    +
    +

    Note

    +

    Author is nowhere close to being a cryptographer. Be sceptical on accuracy.

    +
    +

    In Monero, the root private key is generated randomly. Other private keys are derived deterministically from the root private key.

    +

    Private key must be kept secret.

    +

    Private key is a large integer impossible to guess, like: +108555083659983933209597798445644913612440610624038028786991485007418559037440

    +

    Private key is 256 bits long.

    +

    Private key is a scalar, meaning it is a single value.

    +

    In equations scalars are represented by lowercase letters.

    +

    Relation to Ed25519

    +

    Being simply a random integer, private key is not specific to any particular asymmetric cryptography scheme.

    +

    In context of Monero EC cryptography the private key is a number the base point G is multiplied by. +The result of the multiplication is the public key P (another point on the curve). +Multiplication of a point by a number has a very special definition in EC cryptography. +See this this guide for details.

    +

    Key strength

    +

    Before deriving the public key, private key is subject to modulo l, +where l is the maximum scalar allowed by the edwards25519 curve.

    +

    The l is on the order of 2^252, so the effective key strength is technically 252 bits, not 256 bits. +This is standard for EC cryptography and is more of a cosmetic nuance than any concern.

    +

    Encoding

    +

    In user-facing contexts, the private key integer is:

    +
      +
    1. Taken modulo l to avoid malleability
    2. +
    3. Put as array of 32 bytes in a little-endian direction (the first byte is the least significant)
    4. +
    5. Converted to hexadecimal form, like: b3588a87056fb21dc4d052d59e83b54293882e646b543c29478e4cf45c28a402
    6. +
    +

    Private spend key

    +

    Private spend key is used to spend moneros.

    +

    More specifically, it is used to build one-time private keys which allow to spend related outputs.

    +

    Private view key

    +

    Private view key is used to recognize your incoming transactions on the otherwise opaque blockchain.

    +

    One-time private keys

    +

    One-time private key like construct is used in stealth addresses.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/cryptography/asymmetric/public-key/index.html b/public/cryptography/asymmetric/public-key/index.html new file mode 100644 index 0000000..b74d831 --- /dev/null +++ b/public/cryptography/asymmetric/public-key/index.html @@ -0,0 +1,1090 @@ + + + + + + + + + + + + + + + + + + + + + + + Public Keys in Monero - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Public Keys in Monero

    +
    +

    Note

    +

    Author is nowhere close to being a cryptographer. Be sceptical on accuracy.

    +
    +

    Public key is deterministically derived from private key based on edwards25519 curve with a little Monero-specific twist.

    +

    Public key is meant to be shared. Assuming correct implementation, it is not practically possible to recover private key from public key.

    +

    Public key is a point (x,y) on the elliptic curve.

    +

    In equations points are represented by uppercase letters.

    +

    In user-facing contexts, public key is encoded in a little-endian hexadecimal form, like: +016a941812293cf9a86071060fb090ab38d67945e659968cb8cf30e1bc725683

    +

    Deriving public key

    +

    Say:

    +
      +
    • P is a public key
    • +
    • x is a private key
    • +
    • G is a "base point"; this is simply a constant specific to edwards25519; this point lies on the elliptic curve
    • +
    +

    Then:

    +
    P = xG
    +
    +

    The public key is simply the base point (G) multiplied by the private key (x). +Multiplying the point is adding the point to itself a number of times.

    +

    However, the addition is not a simple vector addition. It has a very specific +definition nicely described in this article. +What is important is that result of addition is always a point on the curve. +For example, G + G is another point on the curve.

    +

    Use cases

    +

    Monero address is composed of public spend key and public view key. +These keys are used to build stealth addresses to receive payments.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/cryptography/base58/index.html b/public/cryptography/base58/index.html new file mode 100644 index 0000000..26cead9 --- /dev/null +++ b/public/cryptography/base58/index.html @@ -0,0 +1,1054 @@ + + + + + + + + + + + + + + + + + + + + + + + Base58 - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Base58

    +

    Base58 is a binary-to-text encoding scheme. It is similar to Base64 but has been modified to avoid both non-alphanumeric characters and letters which might look ambiguous when printed. The characters excluded in relation to Base64 are: IOl0+/

    +

    Base58 does not strictly specify the format. This results in some implementations being incompatible with others, for example with regard to alphabet order.

    +

    For details, see Wikipedia.

    +

    Base58 in Monero

    +

    Monero has its own variant of Base58.

    +

    In Monero the Base58 encoding is performed in 8-byte blocks, except the last block which is the remaining (8 or less) bytes .

    +

    The 8-byte block converts to 11 or less Base58 characters. If the block converted to less then 11 characters, the output is padded with "1"s (0 in Base58). The final block is padded as well to whatever would be the maximum size of this number of bytes encoded in Base58.

    +

    The advantage of Monero implementation is that output is of a fixed size which is not the case with plain Base58. The disadvantage is that default libraries won't work.

    +

    For details, see reference C++ Base58 implementation and unofficial Python Base58 implementation.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/cryptography/introduction/index.html b/public/cryptography/introduction/index.html new file mode 100644 index 0000000..c0681f4 --- /dev/null +++ b/public/cryptography/introduction/index.html @@ -0,0 +1,1005 @@ + + + + + + + + + + + + + + + + + + + + + + + Cryptography in Monero - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Cryptography in Monero

    +

    Monero uses a wide variety of cryptographic primitives for various use cases.

    +

    Comparing to altcoins, Monero cryptography is considered conservative, sound and robust.

    +

    Comparing to Bitcoin, Monero uses much more primitives, and some of them are more advanced, especially those related to privacy and Proof of Work. +Some choices are deliberately non-standard (for better or worse) - oftentimes a legacy of the CryptoNote protocol.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/cryptography/keccak-256/index.html b/public/cryptography/keccak-256/index.html new file mode 100644 index 0000000..8e50f33 --- /dev/null +++ b/public/cryptography/keccak-256/index.html @@ -0,0 +1,1102 @@ + + + + + + + + + + + + + + + + + + + + + + + Keccak-256 Hash Function - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Keccak-256 Hash Function

    +

    Monero employs Keccak as a hashing function. In most context specifically Keccak-256 is used, +providing 32-byte hashes.

    +

    Keccak is the leading hashing function, designed by non-NSA designers. +Keccak won NIST competition to become the official SHA3.

    +

    Use Cases

    +

    Monero does not employ Keccak for Proof-of-Work. Instead, Keccak is used for:

    +
      +
    • random number generator
    • +
    • block hashing
    • +
    • transaction hashing
    • +
    • stealth address private key image (for double spend protection)
    • +
    • public address checksum
    • +
    • RingCT
    • +
    • multisig
    • +
    • bulletproofs
    • +
    +

    ...and likely a few other things.

    +

    Keccak-256 vs SHA3-256

    +

    SHA3-256 is Keccak-256, except NIST changed padding. +For that reason original Keccak-256 gives in a different hash value than NIST SHA3-256.

    +

    Monero uses original Keccak-256. +The NIST standard was only published on August 2015, while Monero went live on 18 April 2014.

    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/cryptography/prng/index.html b/public/cryptography/prng/index.html new file mode 100644 index 0000000..0463aa7 --- /dev/null +++ b/public/cryptography/prng/index.html @@ -0,0 +1,1077 @@ + + + + + + + + + + + + + + + + + + + + + + + Monero Pseudorandom Number Generator - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Monero Pseudorandom Number Generator

    +

    Monero uses PRNG based on the Keccak hashing function. +Basically, output of the previous hashing round is input for the next one.

    +

    The initial seed comes from entropy sources provided by operating system. +On Linux and MacOS the seed comes from /dev/urandom. +On Windows the WinAPI CryptGenRandom call is used for seeding.

    +

    There is no reseeding.

    +

    Caveats

    +
      +
    • This concerns the reference C++ implementation of Monero. +Please note there are many alternative implementations of private key generation, +including JavaScript, Python, Android/Java. These should be researched case by case for correctness.
    • +
    • In Monero source code you can also find libsodium based random bytes generator. It is part of the embedded library and apparently is not used in actual Monero code.
    • +
    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/extra.css b/public/extra.css new file mode 100644 index 0000000..3d3332e --- /dev/null +++ b/public/extra.css @@ -0,0 +1,2 @@ +/*button[data-md-color-accent],button[data-md-color-primary]{width:13rem;margin-bottom:.4rem;padding:2.4rem .8rem .4rem;-webkit-transition:background-color .25s,opacity .25s;transition:background-color .25s,opacity .25s;border-radius:.2rem;color:#fff;font-size:1.28rem;text-align:left;cursor:pointer}button[data-md-color-accent]:hover,button[data-md-color-primary]:hover{opacity:.75}button[data-md-color-primary=red]{background-color:#ef5350}[data-md-color-primary=red] .md-typeset a{color:#ef5350}[data-md-color-primary=red] .md-header,[data-md-color-primary=red] .md-hero{background-color:#ef5350}[data-md-color-primary=red] .md-nav__link--active,[data-md-color-primary=red] .md-nav__link:active{color:#ef5350}[data-md-color-primary=red] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=pink]{background-color:#e91e63}[data-md-color-primary=pink] .md-typeset a{color:#e91e63}[data-md-color-primary=pink] .md-header,[data-md-color-primary=pink] .md-hero{background-color:#e91e63}[data-md-color-primary=pink] .md-nav__link--active,[data-md-color-primary=pink] .md-nav__link:active{color:#e91e63}[data-md-color-primary=pink] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=purple]{background-color:#ab47bc}[data-md-color-primary=purple] .md-typeset a{color:#ab47bc}[data-md-color-primary=purple] .md-header,[data-md-color-primary=purple] .md-hero{background-color:#ab47bc}[data-md-color-primary=purple] .md-nav__link--active,[data-md-color-primary=purple] .md-nav__link:active{color:#ab47bc}[data-md-color-primary=purple] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=deep-purple]{background-color:#7e57c2}[data-md-color-primary=deep-purple] .md-typeset a{color:#7e57c2}[data-md-color-primary=deep-purple] .md-header,[data-md-color-primary=deep-purple] .md-hero{background-color:#7e57c2}[data-md-color-primary=deep-purple] .md-nav__link--active,[data-md-color-primary=deep-purple] .md-nav__link:active{color:#7e57c2}[data-md-color-primary=deep-purple] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=indigo]{background-color:#3f51b5}[data-md-color-primary=indigo] .md-typeset a{color:#3f51b5}[data-md-color-primary=indigo] .md-header,[data-md-color-primary=indigo] .md-hero{background-color:#3f51b5}[data-md-color-primary=indigo] .md-nav__link--active,[data-md-color-primary=indigo] .md-nav__link:active{color:#3f51b5}[data-md-color-primary=indigo] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=blue]{background-color:#2196f3}[data-md-color-primary=blue] .md-typeset a{color:#2196f3}[data-md-color-primary=blue] .md-header,[data-md-color-primary=blue] .md-hero{background-color:#2196f3}[data-md-color-primary=blue] .md-nav__link--active,[data-md-color-primary=blue] .md-nav__link:active{color:#2196f3}[data-md-color-primary=blue] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=light-blue]{background-color:#03a9f4}[data-md-color-primary=light-blue] .md-typeset a{color:#03a9f4}[data-md-color-primary=light-blue] .md-header,[data-md-color-primary=light-blue] .md-hero{background-color:#03a9f4}[data-md-color-primary=light-blue] .md-nav__link--active,[data-md-color-primary=light-blue] .md-nav__link:active{color:#03a9f4}[data-md-color-primary=light-blue] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=cyan]{background-color:#00bcd4}[data-md-color-primary=cyan] .md-typeset a{color:#00bcd4}[data-md-color-primary=cyan] .md-header,[data-md-color-primary=cyan] .md-hero{background-color:#00bcd4}[data-md-color-primary=cyan] .md-nav__link--active,[data-md-color-primary=cyan] .md-nav__link:active{color:#00bcd4}[data-md-color-primary=cyan] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=teal]{background-color:#009688}[data-md-color-primary=teal] .md-typeset a{color:#009688}[data-md-color-primary=teal] .md-header,[data-md-color-primary=teal] .md-hero{background-color:#009688}[data-md-color-primary=teal] .md-nav__link--active,[data-md-color-primary=teal] .md-nav__link:active{color:#009688}[data-md-color-primary=teal] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=green]{background-color:#4caf50}[data-md-color-primary=green] .md-typeset a{color:#4caf50}[data-md-color-primary=green] .md-header,[data-md-color-primary=green] .md-hero{background-color:#4caf50}[data-md-color-primary=green] .md-nav__link--active,[data-md-color-primary=green] .md-nav__link:active{color:#4caf50}[data-md-color-primary=green] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=light-green]{background-color:#7cb342}[data-md-color-primary=light-green] .md-typeset a{color:#7cb342}[data-md-color-primary=light-green] .md-header,[data-md-color-primary=light-green] .md-hero{background-color:#7cb342}[data-md-color-primary=light-green] .md-nav__link--active,[data-md-color-primary=light-green] .md-nav__link:active{color:#7cb342}[data-md-color-primary=light-green] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=lime]{background-color:#c0ca33}[data-md-color-primary=lime] .md-typeset a{color:#c0ca33}[data-md-color-primary=lime] .md-header,[data-md-color-primary=lime] .md-hero{background-color:#c0ca33}[data-md-color-primary=lime] .md-nav__link--active,[data-md-color-primary=lime] .md-nav__link:active{color:#c0ca33}[data-md-color-primary=lime] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=yellow]{background-color:#f9a825}[data-md-color-primary=yellow] .md-typeset a{color:#f9a825}[data-md-color-primary=yellow] .md-header,[data-md-color-primary=yellow] .md-hero{background-color:#f9a825}[data-md-color-primary=yellow] .md-nav__link--active,[data-md-color-primary=yellow] .md-nav__link:active{color:#f9a825}[data-md-color-primary=yellow] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=amber]{background-color:#ffa000}[data-md-color-primary=amber] .md-typeset a{color:#ffa000}[data-md-color-primary=amber] .md-header,[data-md-color-primary=amber] .md-hero{background-color:#ffa000}[data-md-color-primary=amber] .md-nav__link--active,[data-md-color-primary=amber] .md-nav__link:active{color:#ffa000}[data-md-color-primary=amber] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=orange]{background-color:#fb8c00}[data-md-color-primary=orange] .md-typeset a{color:#fb8c00}[data-md-color-primary=orange] .md-header,[data-md-color-primary=orange] .md-hero{background-color:#fb8c00}[data-md-color-primary=orange] .md-nav__link--active,[data-md-color-primary=orange] .md-nav__link:active{color:#fb8c00}[data-md-color-primary=orange] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=deep-orange]{background-color:#ff6600}[data-md-color-primary=deep-orange] .md-typeset a{color:#ff6600}[data-md-color-primary=deep-orange] .md-header,[data-md-color-primary=deep-orange] .md-hero{background-color:#ff6600}[data-md-color-primary=deep-orange] .md-nav__link--active,[data-md-color-primary=deep-orange] .md-nav__link:active{color:#ff6600}[data-md-color-primary=deep-orange] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=brown]{background-color:#795548}[data-md-color-primary=brown] .md-typeset a{color:#795548}[data-md-color-primary=brown] .md-header,[data-md-color-primary=brown] .md-hero{background-color:#795548}[data-md-color-primary=brown] .md-nav__link--active,[data-md-color-primary=brown] .md-nav__link:active{color:#795548}[data-md-color-primary=brown] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=grey]{background-color:#757575}[data-md-color-primary=grey] .md-typeset a{color:#757575}[data-md-color-primary=grey] .md-header,[data-md-color-primary=grey] .md-hero{background-color:#757575}[data-md-color-primary=grey] .md-nav__link--active,[data-md-color-primary=grey] .md-nav__link:active{color:#757575}[data-md-color-primary=grey] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=blue-grey]{background-color:#546e7a}[data-md-color-primary=blue-grey] .md-typeset a{color:#546e7a}[data-md-color-primary=blue-grey] .md-header,[data-md-color-primary=blue-grey] .md-hero{background-color:#546e7a}[data-md-color-primary=blue-grey] .md-nav__link--active,[data-md-color-primary=blue-grey] .md-nav__link:active{color:#546e7a}[data-md-color-primary=blue-grey] .md-nav__item--nested>.md-nav__link{color:inherit}button[data-md-color-primary=white]{-webkit-box-shadow:0 0 .1rem rgba(0,0,0,.54) inset;box-shadow:inset 0 0 .1rem rgba(0,0,0,.54)}[data-md-color-primary=white] .md-header,[data-md-color-primary=white] .md-hero,button[data-md-color-primary=white]{background-color:#fff;color:rgba(0,0,0,.87)}[data-md-color-primary=white] .md-hero--expand{border-bottom:.1rem solid rgba(0,0,0,.07)}button[data-md-color-accent=red]{background-color:#ff1744}[data-md-color-accent=red] .md-typeset a:active,[data-md-color-accent=red] .md-typeset a:hover{color:#ff1744}[data-md-color-accent=red] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=red] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ff1744}[data-md-color-accent=red] .md-nav__link:focus,[data-md-color-accent=red] .md-nav__link:hover,[data-md-color-accent=red] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=red] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=red] .md-typeset .md-clipboard:active:before,[data-md-color-accent=red] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=red] .md-typeset [id] .headerlink:focus,[data-md-color-accent=red] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=red] .md-typeset [id]:target .headerlink{color:#ff1744}[data-md-color-accent=red] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff1744}[data-md-color-accent=red] .md-search-result__link:hover,[data-md-color-accent=red] .md-search-result__link[data-md-state=active]{background-color:rgba(255,23,68,.1)}[data-md-color-accent=red] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff1744}[data-md-color-accent=red] .md-source-file:hover:before{background-color:#ff1744}button[data-md-color-accent=pink]{background-color:#f50057}[data-md-color-accent=pink] .md-typeset a:active,[data-md-color-accent=pink] .md-typeset a:hover{color:#f50057}[data-md-color-accent=pink] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=pink] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#f50057}[data-md-color-accent=pink] .md-nav__link:focus,[data-md-color-accent=pink] .md-nav__link:hover,[data-md-color-accent=pink] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=pink] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=pink] .md-typeset .md-clipboard:active:before,[data-md-color-accent=pink] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=pink] .md-typeset [id] .headerlink:focus,[data-md-color-accent=pink] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=pink] .md-typeset [id]:target .headerlink{color:#f50057}[data-md-color-accent=pink] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#f50057}[data-md-color-accent=pink] .md-search-result__link:hover,[data-md-color-accent=pink] .md-search-result__link[data-md-state=active]{background-color:rgba(245,0,87,.1)}[data-md-color-accent=pink] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#f50057}[data-md-color-accent=pink] .md-source-file:hover:before{background-color:#f50057}button[data-md-color-accent=purple]{background-color:#e040fb}[data-md-color-accent=purple] .md-typeset a:active,[data-md-color-accent=purple] .md-typeset a:hover{color:#e040fb}[data-md-color-accent=purple] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=purple] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#e040fb}[data-md-color-accent=purple] .md-nav__link:focus,[data-md-color-accent=purple] .md-nav__link:hover,[data-md-color-accent=purple] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=purple] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=purple] .md-typeset .md-clipboard:active:before,[data-md-color-accent=purple] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=purple] .md-typeset [id] .headerlink:focus,[data-md-color-accent=purple] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=purple] .md-typeset [id]:target .headerlink{color:#e040fb}[data-md-color-accent=purple] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#e040fb}[data-md-color-accent=purple] .md-search-result__link:hover,[data-md-color-accent=purple] .md-search-result__link[data-md-state=active]{background-color:rgba(224,64,251,.1)}[data-md-color-accent=purple] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#e040fb}[data-md-color-accent=purple] .md-source-file:hover:before{background-color:#e040fb}button[data-md-color-accent=deep-purple]{background-color:#7c4dff}[data-md-color-accent=deep-purple] .md-typeset a:active,[data-md-color-accent=deep-purple] .md-typeset a:hover{color:#7c4dff}[data-md-color-accent=deep-purple] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=deep-purple] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#7c4dff}[data-md-color-accent=deep-purple] .md-nav__link:focus,[data-md-color-accent=deep-purple] .md-nav__link:hover,[data-md-color-accent=deep-purple] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=deep-purple] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=deep-purple] .md-typeset .md-clipboard:active:before,[data-md-color-accent=deep-purple] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=deep-purple] .md-typeset [id] .headerlink:focus,[data-md-color-accent=deep-purple] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=deep-purple] .md-typeset [id]:target .headerlink{color:#7c4dff}[data-md-color-accent=deep-purple] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#7c4dff}[data-md-color-accent=deep-purple] .md-search-result__link:hover,[data-md-color-accent=deep-purple] .md-search-result__link[data-md-state=active]{background-color:rgba(124,77,255,.1)}[data-md-color-accent=deep-purple] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#7c4dff}[data-md-color-accent=deep-purple] .md-source-file:hover:before{background-color:#7c4dff}button[data-md-color-accent=indigo]{background-color:#536dfe}[data-md-color-accent=indigo] .md-typeset a:active,[data-md-color-accent=indigo] .md-typeset a:hover{color:#536dfe}[data-md-color-accent=indigo] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=indigo] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#536dfe}[data-md-color-accent=indigo] .md-nav__link:focus,[data-md-color-accent=indigo] .md-nav__link:hover,[data-md-color-accent=indigo] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=indigo] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=indigo] .md-typeset .md-clipboard:active:before,[data-md-color-accent=indigo] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=indigo] .md-typeset [id] .headerlink:focus,[data-md-color-accent=indigo] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=indigo] .md-typeset [id]:target .headerlink{color:#536dfe}[data-md-color-accent=indigo] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#536dfe}[data-md-color-accent=indigo] .md-search-result__link:hover,[data-md-color-accent=indigo] .md-search-result__link[data-md-state=active]{background-color:rgba(83,109,254,.1)}[data-md-color-accent=indigo] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#536dfe}[data-md-color-accent=indigo] .md-source-file:hover:before{background-color:#536dfe}button[data-md-color-accent=blue]{background-color:#448aff}[data-md-color-accent=blue] .md-typeset a:active,[data-md-color-accent=blue] .md-typeset a:hover{color:#448aff}[data-md-color-accent=blue] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=blue] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#448aff}[data-md-color-accent=blue] .md-nav__link:focus,[data-md-color-accent=blue] .md-nav__link:hover,[data-md-color-accent=blue] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=blue] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=blue] .md-typeset .md-clipboard:active:before,[data-md-color-accent=blue] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=blue] .md-typeset [id] .headerlink:focus,[data-md-color-accent=blue] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=blue] .md-typeset [id]:target .headerlink{color:#448aff}[data-md-color-accent=blue] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#448aff}[data-md-color-accent=blue] .md-search-result__link:hover,[data-md-color-accent=blue] .md-search-result__link[data-md-state=active]{background-color:rgba(68,138,255,.1)}[data-md-color-accent=blue] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#448aff}[data-md-color-accent=blue] .md-source-file:hover:before{background-color:#448aff}button[data-md-color-accent=light-blue]{background-color:#0091ea}[data-md-color-accent=light-blue] .md-typeset a:active,[data-md-color-accent=light-blue] .md-typeset a:hover{color:#0091ea}[data-md-color-accent=light-blue] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=light-blue] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#0091ea}[data-md-color-accent=light-blue] .md-nav__link:focus,[data-md-color-accent=light-blue] .md-nav__link:hover,[data-md-color-accent=light-blue] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=light-blue] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=light-blue] .md-typeset .md-clipboard:active:before,[data-md-color-accent=light-blue] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=light-blue] .md-typeset [id] .headerlink:focus,[data-md-color-accent=light-blue] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=light-blue] .md-typeset [id]:target .headerlink{color:#0091ea}[data-md-color-accent=light-blue] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#0091ea}[data-md-color-accent=light-blue] .md-search-result__link:hover,[data-md-color-accent=light-blue] .md-search-result__link[data-md-state=active]{background-color:rgba(0,145,234,.1)}[data-md-color-accent=light-blue] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#0091ea}[data-md-color-accent=light-blue] .md-source-file:hover:before{background-color:#0091ea}button[data-md-color-accent=cyan]{background-color:#00b8d4}[data-md-color-accent=cyan] .md-typeset a:active,[data-md-color-accent=cyan] .md-typeset a:hover{color:#00b8d4}[data-md-color-accent=cyan] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=cyan] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#00b8d4}[data-md-color-accent=cyan] .md-nav__link:focus,[data-md-color-accent=cyan] .md-nav__link:hover,[data-md-color-accent=cyan] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=cyan] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=cyan] .md-typeset .md-clipboard:active:before,[data-md-color-accent=cyan] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=cyan] .md-typeset [id] .headerlink:focus,[data-md-color-accent=cyan] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=cyan] .md-typeset [id]:target .headerlink{color:#00b8d4}[data-md-color-accent=cyan] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00b8d4}[data-md-color-accent=cyan] .md-search-result__link:hover,[data-md-color-accent=cyan] .md-search-result__link[data-md-state=active]{background-color:rgba(0,184,212,.1)}[data-md-color-accent=cyan] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00b8d4}[data-md-color-accent=cyan] .md-source-file:hover:before{background-color:#00b8d4}button[data-md-color-accent=teal]{background-color:#00bfa5}[data-md-color-accent=teal] .md-typeset a:active,[data-md-color-accent=teal] .md-typeset a:hover{color:#00bfa5}[data-md-color-accent=teal] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=teal] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#00bfa5}[data-md-color-accent=teal] .md-nav__link:focus,[data-md-color-accent=teal] .md-nav__link:hover,[data-md-color-accent=teal] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=teal] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=teal] .md-typeset .md-clipboard:active:before,[data-md-color-accent=teal] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=teal] .md-typeset [id] .headerlink:focus,[data-md-color-accent=teal] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=teal] .md-typeset [id]:target .headerlink{color:#00bfa5}[data-md-color-accent=teal] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00bfa5}[data-md-color-accent=teal] .md-search-result__link:hover,[data-md-color-accent=teal] .md-search-result__link[data-md-state=active]{background-color:rgba(0,191,165,.1)}[data-md-color-accent=teal] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00bfa5}[data-md-color-accent=teal] .md-source-file:hover:before{background-color:#00bfa5}button[data-md-color-accent=green]{background-color:#00c853}[data-md-color-accent=green] .md-typeset a:active,[data-md-color-accent=green] .md-typeset a:hover{color:#00c853}[data-md-color-accent=green] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=green] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#00c853}[data-md-color-accent=green] .md-nav__link:focus,[data-md-color-accent=green] .md-nav__link:hover,[data-md-color-accent=green] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=green] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=green] .md-typeset .md-clipboard:active:before,[data-md-color-accent=green] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=green] .md-typeset [id] .headerlink:focus,[data-md-color-accent=green] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=green] .md-typeset [id]:target .headerlink{color:#00c853}[data-md-color-accent=green] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00c853}[data-md-color-accent=green] .md-search-result__link:hover,[data-md-color-accent=green] .md-search-result__link[data-md-state=active]{background-color:rgba(0,200,83,.1)}[data-md-color-accent=green] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#00c853}[data-md-color-accent=green] .md-source-file:hover:before{background-color:#00c853}button[data-md-color-accent=light-green]{background-color:#64dd17}[data-md-color-accent=light-green] .md-typeset a:active,[data-md-color-accent=light-green] .md-typeset a:hover{color:#64dd17}[data-md-color-accent=light-green] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=light-green] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#64dd17}[data-md-color-accent=light-green] .md-nav__link:focus,[data-md-color-accent=light-green] .md-nav__link:hover,[data-md-color-accent=light-green] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=light-green] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=light-green] .md-typeset .md-clipboard:active:before,[data-md-color-accent=light-green] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=light-green] .md-typeset [id] .headerlink:focus,[data-md-color-accent=light-green] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=light-green] .md-typeset [id]:target .headerlink{color:#64dd17}[data-md-color-accent=light-green] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#64dd17}[data-md-color-accent=light-green] .md-search-result__link:hover,[data-md-color-accent=light-green] .md-search-result__link[data-md-state=active]{background-color:rgba(100,221,23,.1)}[data-md-color-accent=light-green] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#64dd17}[data-md-color-accent=light-green] .md-source-file:hover:before{background-color:#64dd17}button[data-md-color-accent=lime]{background-color:#aeea00}[data-md-color-accent=lime] .md-typeset a:active,[data-md-color-accent=lime] .md-typeset a:hover{color:#aeea00}[data-md-color-accent=lime] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=lime] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#aeea00}[data-md-color-accent=lime] .md-nav__link:focus,[data-md-color-accent=lime] .md-nav__link:hover,[data-md-color-accent=lime] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=lime] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=lime] .md-typeset .md-clipboard:active:before,[data-md-color-accent=lime] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=lime] .md-typeset [id] .headerlink:focus,[data-md-color-accent=lime] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=lime] .md-typeset [id]:target .headerlink{color:#aeea00}[data-md-color-accent=lime] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#aeea00}[data-md-color-accent=lime] .md-search-result__link:hover,[data-md-color-accent=lime] .md-search-result__link[data-md-state=active]{background-color:rgba(174,234,0,.1)}[data-md-color-accent=lime] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#aeea00}[data-md-color-accent=lime] .md-source-file:hover:before{background-color:#aeea00}button[data-md-color-accent=yellow]{background-color:#ffd600}[data-md-color-accent=yellow] .md-typeset a:active,[data-md-color-accent=yellow] .md-typeset a:hover{color:#ffd600}[data-md-color-accent=yellow] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=yellow] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ffd600}[data-md-color-accent=yellow] .md-nav__link:focus,[data-md-color-accent=yellow] .md-nav__link:hover,[data-md-color-accent=yellow] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=yellow] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=yellow] .md-typeset .md-clipboard:active:before,[data-md-color-accent=yellow] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=yellow] .md-typeset [id] .headerlink:focus,[data-md-color-accent=yellow] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=yellow] .md-typeset [id]:target .headerlink{color:#ffd600}[data-md-color-accent=yellow] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ffd600}[data-md-color-accent=yellow] .md-search-result__link:hover,[data-md-color-accent=yellow] .md-search-result__link[data-md-state=active]{background-color:rgba(255,214,0,.1)}[data-md-color-accent=yellow] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ffd600}[data-md-color-accent=yellow] .md-source-file:hover:before{background-color:#ffd600}button[data-md-color-accent=amber]{background-color:#ffab00}[data-md-color-accent=amber] .md-typeset a:active,[data-md-color-accent=amber] .md-typeset a:hover{color:#ffab00}[data-md-color-accent=amber] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=amber] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ffab00}[data-md-color-accent=amber] .md-nav__link:focus,[data-md-color-accent=amber] .md-nav__link:hover,[data-md-color-accent=amber] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=amber] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=amber] .md-typeset .md-clipboard:active:before,[data-md-color-accent=amber] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=amber] .md-typeset [id] .headerlink:focus,[data-md-color-accent=amber] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=amber] .md-typeset [id]:target .headerlink{color:#ffab00}[data-md-color-accent=amber] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ffab00}[data-md-color-accent=amber] .md-search-result__link:hover,[data-md-color-accent=amber] .md-search-result__link[data-md-state=active]{background-color:rgba(255,171,0,.1)}[data-md-color-accent=amber] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ffab00}[data-md-color-accent=amber] .md-source-file:hover:before{background-color:#ffab00}button[data-md-color-accent=orange]{background-color:#ff9100}[data-md-color-accent=orange] .md-typeset a:active,[data-md-color-accent=orange] .md-typeset a:hover{color:#ff9100}[data-md-color-accent=orange] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=orange] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ff9100}[data-md-color-accent=orange] .md-nav__link:focus,[data-md-color-accent=orange] .md-nav__link:hover,[data-md-color-accent=orange] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=orange] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=orange] .md-typeset .md-clipboard:active:before,[data-md-color-accent=orange] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=orange] .md-typeset [id] .headerlink:focus,[data-md-color-accent=orange] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=orange] .md-typeset [id]:target .headerlink{color:#ff9100}[data-md-color-accent=orange] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff9100}[data-md-color-accent=orange] .md-search-result__link:hover,[data-md-color-accent=orange] .md-search-result__link[data-md-state=active]{background-color:rgba(255,145,0,.1)}[data-md-color-accent=orange] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff9100}[data-md-color-accent=orange] .md-source-file:hover:before{background-color:#ff9100}button[data-md-color-accent=deep-orange]{background-color:#ff6e40}[data-md-color-accent=deep-orange] .md-typeset a:active,[data-md-color-accent=deep-orange] .md-typeset a:hover{color:#ff6e40}[data-md-color-accent=deep-orange] .md-typeset .codehilite pre::-webkit-scrollbar-thumb:hover,[data-md-color-accent=deep-orange] .md-typeset pre code::-webkit-scrollbar-thumb:hover{background-color:#ff6e40}[data-md-color-accent=deep-orange] .md-nav__link:focus,[data-md-color-accent=deep-orange] .md-nav__link:hover,[data-md-color-accent=deep-orange] .md-typeset .footnote li:hover .footnote-backref:hover,[data-md-color-accent=deep-orange] .md-typeset .footnote li:target .footnote-backref,[data-md-color-accent=deep-orange] .md-typeset .md-clipboard:active:before,[data-md-color-accent=deep-orange] .md-typeset .md-clipboard:hover:before,[data-md-color-accent=deep-orange] .md-typeset [id] .headerlink:focus,[data-md-color-accent=deep-orange] .md-typeset [id]:hover .headerlink:hover,[data-md-color-accent=deep-orange] .md-typeset [id]:target .headerlink{color:#ff6e40}[data-md-color-accent=deep-orange] .md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff6e40}[data-md-color-accent=deep-orange] .md-search-result__link:hover,[data-md-color-accent=deep-orange] .md-search-result__link[data-md-state=active]{background-color:rgba(255,110,64,.1)}[data-md-color-accent=deep-orange] .md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:#ff6e40}[data-md-color-accent=deep-orange] .md-source-file:hover:before{background-color:#ff6e40}@media only screen and (max-width:59.9375em){[data-md-color-primary=red] .md-nav__source{background-color:rgba(190,66,64,.9675)}[data-md-color-primary=pink] .md-nav__source{background-color:rgba(185,24,79,.9675)}[data-md-color-primary=purple] .md-nav__source{background-color:rgba(136,57,150,.9675)}[data-md-color-primary=deep-purple] .md-nav__source{background-color:rgba(100,69,154,.9675)}[data-md-color-primary=indigo] .md-nav__source{background-color:rgba(50,64,144,.9675)}[data-md-color-primary=blue] .md-nav__source{background-color:rgba(26,119,193,.9675)}[data-md-color-primary=light-blue] .md-nav__source{background-color:rgba(2,134,194,.9675)}[data-md-color-primary=cyan] .md-nav__source{background-color:rgba(0,150,169,.9675)}[data-md-color-primary=teal] .md-nav__source{background-color:rgba(0,119,108,.9675)}[data-md-color-primary=green] .md-nav__source{background-color:rgba(60,139,64,.9675)}[data-md-color-primary=light-green] .md-nav__source{background-color:rgba(99,142,53,.9675)}[data-md-color-primary=lime] .md-nav__source{background-color:rgba(153,161,41,.9675)}[data-md-color-primary=yellow] .md-nav__source{background-color:rgba(198,134,29,.9675)}[data-md-color-primary=amber] .md-nav__source{background-color:rgba(203,127,0,.9675)}[data-md-color-primary=orange] .md-nav__source{background-color:rgba(200,111,0,.9675)}[data-md-color-primary=deep-orange] .md-nav__source{background-color:rgba(203,89,53,.9675)}[data-md-color-primary=brown] .md-nav__source{background-color:rgba(96,68,57,.9675)}[data-md-color-primary=grey] .md-nav__source{background-color:rgba(93,93,93,.9675)}[data-md-color-primary=blue-grey] .md-nav__source{background-color:rgba(67,88,97,.9675)}[data-md-color-primary=white] .md-nav__source{background-color:rgba(0,0,0,.07);color:rgba(0,0,0,.87)}}@media only screen and (max-width:76.1875em){html [data-md-color-primary=red] .md-nav--primary .md-nav__title--site{background-color:#ef5350}html [data-md-color-primary=pink] .md-nav--primary .md-nav__title--site{background-color:#e91e63}html [data-md-color-primary=purple] .md-nav--primary .md-nav__title--site{background-color:#ab47bc}html [data-md-color-primary=deep-purple] .md-nav--primary .md-nav__title--site{background-color:#7e57c2}html [data-md-color-primary=indigo] .md-nav--primary .md-nav__title--site{background-color:#3f51b5}html [data-md-color-primary=blue] .md-nav--primary .md-nav__title--site{background-color:#2196f3}html [data-md-color-primary=light-blue] .md-nav--primary .md-nav__title--site{background-color:#03a9f4}html [data-md-color-primary=cyan] .md-nav--primary .md-nav__title--site{background-color:#00bcd4}html [data-md-color-primary=teal] .md-nav--primary .md-nav__title--site{background-color:#009688}html [data-md-color-primary=green] .md-nav--primary .md-nav__title--site{background-color:#4caf50}html [data-md-color-primary=light-green] .md-nav--primary .md-nav__title--site{background-color:#7cb342}html [data-md-color-primary=lime] .md-nav--primary .md-nav__title--site{background-color:#c0ca33}html [data-md-color-primary=yellow] .md-nav--primary .md-nav__title--site{background-color:#f9a825}html [data-md-color-primary=amber] .md-nav--primary .md-nav__title--site{background-color:#ffa000}html [data-md-color-primary=orange] .md-nav--primary .md-nav__title--site{background-color:#fb8c00}html [data-md-color-primary=deep-orange] .md-nav--primary .md-nav__title--site{background-color:#ff6600}html [data-md-color-primary=brown] .md-nav--primary .md-nav__title--site{background-color:#795548}html [data-md-color-primary=grey] .md-nav--primary .md-nav__title--site{background-color:#757575}html [data-md-color-primary=blue-grey] .md-nav--primary .md-nav__title--site{background-color:#546e7a}html [data-md-color-primary=white] .md-nav--primary .md-nav__title--site{background-color:#fff;color:rgba(0,0,0,.87)}[data-md-color-primary=white] .md-hero{border-bottom:.1rem solid rgba(0,0,0,.07)}}@media only screen and (min-width:76.25em){[data-md-color-primary=red] .md-tabs{background-color:#ef5350}[data-md-color-primary=pink] .md-tabs{background-color:#e91e63}[data-md-color-primary=purple] .md-tabs{background-color:#ab47bc}[data-md-color-primary=deep-purple] .md-tabs{background-color:#7e57c2}[data-md-color-primary=indigo] .md-tabs{background-color:#3f51b5}[data-md-color-primary=blue] .md-tabs{background-color:#2196f3}[data-md-color-primary=light-blue] .md-tabs{background-color:#03a9f4}[data-md-color-primary=cyan] .md-tabs{background-color:#00bcd4}[data-md-color-primary=teal] .md-tabs{background-color:#009688}[data-md-color-primary=green] .md-tabs{background-color:#4caf50}[data-md-color-primary=light-green] .md-tabs{background-color:#7cb342}[data-md-color-primary=lime] .md-tabs{background-color:#c0ca33}[data-md-color-primary=yellow] .md-tabs{background-color:#f9a825}[data-md-color-primary=amber] .md-tabs{background-color:#ffa000}[data-md-color-primary=orange] .md-tabs{background-color:#fb8c00}[data-md-color-primary=deep-orange] .md-tabs{background-color:#ff6600}[data-md-color-primary=brown] .md-tabs{background-color:#795548}[data-md-color-primary=grey] .md-tabs{background-color:#757575}[data-md-color-primary=blue-grey] .md-tabs{background-color:#546e7a}[data-md-color-primary=white] .md-tabs{border-bottom:.1rem solid rgba(0,0,0,.07);background-color:#fff;color:rgba(0,0,0,.87)}}@media only screen and (min-width:60em){[data-md-color-primary=white] .md-search__input{background-color:rgba(0,0,0,.07)}[data-md-color-primary=white] .md-search__input::-webkit-input-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input:-ms-input-placeholder,[data-md-color-primary=white] .md-search__input::-ms-input-placeholder{color:rgba(0,0,0,.54)}[data-md-color-primary=white] .md-search__input::placeholder{color:rgba(0,0,0,.54)}}*/ +/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJhc3NldHMvc3R5bGVzaGVldHMvYXBwbGljYXRpb24tcGFsZXR0ZS43OTI0MzFjMS5jc3MiLCJzb3VyY2VSb290IjoiIn0=*/ diff --git a/public/images/monero-dir.png b/public/images/monero-dir.png new file mode 100644 index 0000000000000000000000000000000000000000..664158fa5dc58666177e1c4cd44af649e743d69d GIT binary patch literal 20052 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 literal 0 HcmV?d00001 diff --git a/public/images/monero.svg b/public/images/monero.svg new file mode 100644 index 0000000..af777a4 --- /dev/null +++ b/public/images/monero.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/sheets-icon.png b/public/images/sheets-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f55b0b6e8a4a60cf633b393b2db670727c81af83 GIT binary patch literal 29698 zcmeIZc|4Tu|2KTjAd#Xd?G&WRExpl~PhlQi(zmQe;aE38h6O zLK$+AeMYvy%sJ0-j_T_2y}q8`^W69Sy8qEj%yAy)vAsX<&-?Q^j`N)JW_$IQaB(vtre&NI`F{zItT}PxO@6&1Zr<)^{W9sqnG723$t$Vb<^Iw z9UV~k;2tyKodj>Zu!^jTjHA4Qvap)Etb&Sy@-~I7!iw?=N^KY0v z!ax6Q*5L-9w7i|1H7s`N{TvRIv^O8~_4U$_lM4t4kPT3hC3w5YDX6Qf%gHOsDJsf< zJ7j!Ldipv9%6R&S%y#mtpIvw#M{idzUsr;sFxs!fQG%bZ_U6s#K)?U}T$hK}?}0ph zeqskulnZq5l2eeCm;1LyPL99Zc=>s|v!>?cD2I2)d*D5NeLy>fe{JV=jNnV~IY#&| zL;kM*uLA>{?Ah~s?0=oFhsVDT?c=-KA3*RE(tmB~v;U+QUd{sVL-6x<#P9Y8OA-0E z)%&_S|81Oq^n}*@*SX^ZUH?lnv}U#$iwd(A(gJJM*y)XT@FjTfClK6qW?5$T3qs+Y zJB1~zTs@r#0X~via&zzg+thz|gx}@hi`M~ER0brJQIOv+udE@jrlFuLEw7*j`d>uR;@rJu} zzy(=XS0@c61vOPCWtD9*4)XGfGS14%M`ey~+vY6eu+8zPvbv&zqRLTc7KnTH{Mr0J zy52=_^g|uxXV*@kYsI5SRaMlK@iNM)M-^n0os{Ke9Pp0vGKx;9emEahRaA5Q)%73E z|D$VDZ&x644(@;4gUk$9a&3_DK;OYaYdGZg+0^+h{Y#;u_Kd=6(aCc?Nk(YzF z4<2vzka&0PP}fd4a;XZ!!7 z`F|fH;27R>K8Kp^ignk2@5G1T>>J?VjowYywdGJq80sZ~6>7Uhen_AD`^v~+KP5*9r zz|+-NNAc%qb1whU3JsF8GQJPwb9fz96%{2FExEau=e96&4aB=2+~o@N)(2G)6$LO9 ztI^z=e{E^~Ut9iB^RwlwvHr-tSPnRQ6=ZfGsg(PjRsM%>{#LL5oge;Q(*Mq0=k&EO z$Q(fCFD}3}KR$D67vP!$$o$0xxaP-aPVE9*a{!sYxB%Du_{^zYfNKsQ^A{K3njfDz zwF_{~0c8H-0$lUsGpBX|t~r3rUtEA|ethQCF2FShkok)XaLtd;oZ1Dr<^VE(aRILR z@tIS*0M{Hq<}WV5H9tOcY8T*|1IYZv1-RzNXHM+`Typ@KzqkO`{P@hNU4Uy2AoCX& z;F=$wIkgLL%>iWo;sRXr<1?pr0j@cK%wJr9Ykqv@)Goj^2ax%T3vkVk&z#x?xaI&d ze{lh>`SF=ky8zc5K;|zlz%@TUb7~jhnghuE#Ra(L$7fFM0$g(dnZLLI*Zla*sa=3; z4j}Uv=Y@;=@9$~iJ;9eV1HiX1i%L3);2WI6js_NcASg%-f`}0iG{ppe`yj|q9)kLh zK#;}_2ofa3+E?j;FM?(o?%KXTuyycj@Z&8m+rN*HKgJi9kd>4Ybcw?8#KW7D3UiOt@v` zZ$8bpdOra&~8Hur-(EZx(=>M=N9P zr1~O7Lvm6_tvamsG zajRTkaqPxIEOO)QVQS9(sSeyKy4dSiQs?h&llfMe?b%H4i9uepiS=bC(fRL3zbx@u zs;ly2we^g>C?h-dmMG(C>Vp&Z&Z9YbR7 zaf3~{gashQP&#?Cl@d2r!~Iq!)=on5)~m})kWW?QaHc4gB8PEpJa#|2I=UIAGe}!r zn_+>uFUou;{fG=t7b=~$mt4j?+)!tDGvPC6)xnFnAX)iFDS9_mV#(^K=$|XT+alkH zD|96wr$z5X1=7)txigkD0<9j?W>%9^yK+VS_CP3Sh1Opsbs91wbhW&Qpil>wDW(Lxx)y$3tjf9vX8xHd#ZC~ z(~VnC`_6>2<}-wU+9Y*hZEfsesa$ct%d&Gz*tj@|w?&YiKG^ru5|1OE4Yi5%av^%6 z^)WKl-qZyI z3Ttr%Bk`$6tbX_?K6@cXx9wa+uYkY2v96W6z>hclai`J;rU$X+=+S)-M@w_LB^;RN zMl11xVJaunF#Acv^~`2=Q8gi*(81_y5a58#J0$w`+MM|Ms}(}@3i43*Rx6#&54P?h zhtOzGB3QSq`^Ib(AyM7=**OmfVZdT#wLU&=x}kjln;Wp0L>#hM~;uWXxguhf2 zgWmR3em-|LcazZZ)5eNTF1{G1l3mMvxsR4TEBAOBo(;Y)mGvZlhF$sU*oHixnsyV^ z3JoyzmiY6&^og4ir^a_l_zWM12VQwA4&)4F!Ji$g4~aQsImdog)(jYwL5G82k=M$1 zPK93985oJL?M*;UU@u3X5!%8f@=mm`&H4MK4fojjxQS%3as$Qst^oZl=ix&Zi;>U{ z5`$wAQ=@~NBzkd=((7e)?>CfOLa7$|9%)7b9uG9Q3@MmXk5VT&;U$ROH`2so*VR?; zM74dLxdNA>HaMlp_93v9qwezCkLBdNZg!YL#pSUpHzbIb4pY|%F0uf|EMG?#10JqBloN|Z{HmE_9}kK-h`fm%oUQ~5-vt&zXnqnHA(E^bIsi z95u;=%OIsFL9B0St6ef)8?LJFHjTV8U&4e>E(rt^a&00-zZ!HtT1yN7N zlO&SCl66asiPp9;VHZzkIq3&H2KPpg_Gw8%VlXwGkDM9hX6?8x&Mm34V?qq&%>+ANJ*i5@n-NUO5B%pk041)ur zmsXNqyx~FinF0rRa5w8pdr;u;=L4us9|+PJa5-6%9#Ya<=RKCRkISIhsQeSF%4+%I zvr^FBOBuk>Z;?V}zC2)7OYMXZ^1n?u~!! zodn@sCmtbfi}sJ^Q#H zqq8*xd(&{@QcH0P;XZ3%u_H4s(Cv~|vPSOhx6=vZC05v2c}u0&o;MRqhFH9Q-~$u_ zK-gURT=b&KRb{fOWc(qnu1xaak|g8O-uVw+`qLPyj$fF|9dRYO0H}&l#Xb z`|`$K0G0XVAO*CV7jcxroVb3U^88121fl3#YxC}FkYeqwtnlSA^3Fx}oG?5RkmgKe zIvMM(5(~5NaUvscxD8=iJSoJjOrwE%pR1Dx+Nnru#=wGQpLpr%2e508Z|RennXvco zz&Afv{L2J@LImW-(VAB?{amou#9D&oO8dJxo2aDD*k*Jx5KzY%+Ds8Iku>0!{M7Ot zi*Oo1M5ItiL2Jrtm@GS;x86p@np0X#_(0w)A6cXmMpqHMs@a+8SH;}VWtOpZ?=`X4 z!9ZF{@1TP57C|MG)I&?s;Wv9^$A7t9E12H94s{t8MxPGvr3&rjI>_+Vy;&AKL91uU zDFl=lp7O6xBG8h8;+mwQSNuV(ffgNtZ!^B?L249oE;0wy+r3xDhtJ&QGsM z>cn%3C0}_j+Tu6s*m|F?#!QFdX!|(*AD3k{JihWyv}HWcN1u!e97O#NNF+oLk;0g# zw3y_sD>4Pp2imElL?`E&zc`d;F5u52uM^MSGz@xE#)#h#*rJldBZ(1!u(QOi zOMvi(6Ya)1K~tC$4#FHnBAh=G5aI^dU?rZGe_U@VK6RXTgt7jfZWPV#00jPS}NhIO;un!L~)7l!9>#YT|tI0A$0 ziR|$VUh;F+74S<_HspYg=T#s-u4O|XzIXt&Kp}DrLSt!a)aw_Y--^DgjO@8&r_YrP z@lnZB-r;B{$rIVXwtB=Q7LdpcI;Um;>^_rU7yHggS0vFecc4iAGFJD#^46w-yxtCq zIMRqw)0fUvc6U-T^k)FIQkw-;&3-Q@>edxWgURf>SnATD^S6yY_TsY}9$ZnqI(WaO zOP^O~@`oVDPv|&d>SQ|mOY56uqqXaJ%Q~Z2kqk9dVmUePCI;!UE^Dwb&@;#8N^s34 zdib0)FxSO2&5`4W(cmf+axv8|VW6U0f92Yj5Z{4S<~hiGdnM$%xYk zMf;uou1_CxF<FUS*uLj_-kX>7!qQu={dfkJ|G@!Y zU&@P}+^dmlJFMj}|K-vM!tzvzuZHT3}S4J#Yl;cj1oC z%-53f=rfT5KC6!8iU}WAzGdjYlNo|VT@XYEz=!i$mn0UC9~m$Yp;yQabWRxVzD9iQ zp$}9c`e}lb+PjS);VWh(e6!dI(Zvfi?#VYa_mHwpwP-74{M){)JMu$J_4|hf1 zzIfB+Pc=fcSWmF$_027P@PS?N_R<@Fp#nVJZp{0fPGrf&mS~bGnx--n6sjc_U(^}@ zsyVJUdFs$)9ZuBxO$(7LjTO4LzVl2hWfWwhC@Gq=vc&09IU=(~OjmCyf8T}dneomN z+}%3zq>4cBd@%TA^3jHu9NGqAI#5`qk?ZosJE{$lQLEWq4`cr8zETxw{G5x+1R4neP>tF)UfUJ8%>@2 zZKNNrA&d%wYjK;o$i+{K9XYmi$cA@GVDK4PSEP(T-g3cBl&M)@^@JR=@iOiK`0T?= zokY)M!kZ08`je`6*E~XQUR*)V(LgG3{Iq5v<~YtyD>v)t-L#s)*31hVCwFOg)5Uwa zf;VQCmiTA37_7XZo0c!-krC(c>EYJwtksT@>jORw`#=412#F#2wdAbtYg1&i+Irs{ zdM?M(44ekt>VB%FM!jWAzm%MD+KHWlgYB71{F8EOhBZusZI81IcSpAU{vwCFAj>Aom8qM#6Qk~4mvXhAks(xnrZ`?iezR8 zJtw+VWRf6sVy`0VN$(VME$G z2>M8u|L3an7i+bjgkQD1Z*$4R+fI`nFyTEtqV~;$=(CKxXfblB4n4k*Cc@;1&k|N*a~`1P zY(+xE%AM~Xd2uZSB z6`uG=ggxA@#ko6Oqg+~|aj|ybFG%nj$CUPAv+A%j`JdKGEM}Qy;54aOKO%sZvo$>~n$557 zfEIPd+Gy)8VY#6--d3C-u1$JO@B$Fmh5h(?<=dHT%5wSW8&9%*sY%X(OO703 z%U~n-bE27TR}Cz)dxZo+FGP@|>9{2ua+{UQpy4Yz)+NkIq$>Mx(~W)t^RA_a6&+X; zP54FVHF@%WcQF_CW?A)POUqsR1jQ_2k}kRay??uyFS~ z-ReUewwfd770LbIO^X&m^z_HdXevZ%xsZF;JZDX3Z``W1Y)bciJ6w3#-ejP7eMaVo+{)B?cfa6@3dEorr^U&BzKo4YL5oW(HxshLHwmGM;`H5b=dRMt*kCCP4!f| ze4YEu)WqZV`clRozX@3#T?5osIe%R!=%9>e)$MgN%y!zDp~){{yR~q9q)>13osVXnJ7?!wpN;=pUu(Fj5_rDZlHQZdVgQ6poGlRTf zPlYR-#N#-beep!I;}q`3!xE-4i5Kkq-aJuh@ep~UkcRh8B5dk0Ach zDeFa9OA`06t)s2`i#0#zl8)Duu;%d;7?!51IZ-gU8EZkC2I@uT#Tf{ncqD zY-fWc-&Ua5R*<_wAi8uZBf8O8)R9d^W8&?KBbkK(3Nv83yvG;ON}`y(gfTXx>+6mt zgRlD)6{BX1i5X4p9Ebq)?d5jXmRQzGK~C(d)qv@@ zKE-hQTS(fdu4|V#mw-dp3(}X*BZYg{TNS9*ke*m9H_CR;XaAh|Ty^+|)ufjY*an+% z0K_*TZn$Gv`*&GnN?JQwl6C}YBt7MX-$Q(+)bDN~AW==fz+B^k-JFqVXlzavG(LG%nvkPDU4xoxAu`YZ^><5OCeg! zSOUu>Zqg>x+YT06^U-`35g{Cv4M#1}S~TdpZ*4|m7TqF+la3B>r-M@K#esAXYMwSk z+ZJmc5x){{5p|*7Q*+kRvt%)k#xkQrUmwg+wvdi9v5DgDdZ(jn`9ftj(-_Mkl5EiP zkjLI{I=XjBu?@V~Wb(^o9XJpXh-tnl!E8j>wi2AbQ8poiwjC4^WF7Nfy%E>Jw^{y$ zJTL z^h5@D?N-c{Mx!jAS{8#z12bqA`@Ugmnt#grgVVT!($v5UzLm z#l}lwBAKGNkUbCxJ?HpWv9`M(+sJzZD7kvat1QFfz8y_t_o}xKdBHk6?6AMu#Z9ky zvfWrjM#WNg89Qo5;1DrXlm;ERM>2TPm0_POcD8=v60mMx)WHK~h#}(#b5Qld)pn~| zO6|x@d%E9Y8$ZaI^Is;RiUP!QdyIS5HBQS5hIeCEm|dW*0+YwlG|$6BmzdmLurt@? z>+8~-pM_o2o}}=C3}YFhAuA4U$z!&5!VlRE`gd9CfupR;3FQUyjTRto#dNV~AVd!s zdu4e%(sH|d-1xaf_ti^NrtqZv&HGvpg~9DcBVTJv;867aJmk7Y=E z7v;STPS3(2t7l#Dpn5z+O>zoc0?{{AkPBPTV~F79kgRJ^pVQ&q=XT1Cu_r2oTz)ZQ zXXNAhTA2vJZ}dhcsT3#8EF3pQH-Z2~@MER=wfwlGY{6?d(N3M^xK>UMz)jNgg`P%O zyfH7UdJfKJKn02Nn;jGbSC2Dkha8Hxb3shkvlpOQn&}sxIZm@?IwZl8wRizZnTW9F zsnPd3tWHbh?}5RRD!sR!J%e2%*4-+|c_NjLAP@xzoRjnun_tjC~MWdJ3&2T zZI}*#+QyBGP;D3V6vm65s$LdzX!3n-%t1_3=$_ z4;ZyQXA=&Og3k_g~Iz(uG&f zoT=UMVV{I#{&E-07FHmo=G3P61lt2Pq0b>+t<9WzoPJ5Nc;nCfx`VPAc{E)3u>w3% zxE8x{sb>Gp6&gTLD5{9N4|Q@mOm3fkB4VQ_k|>4Y0Gl)jk?o?i4YE`q@*QA78h>YP zba>J7540D%i5ij7Q=^&2ox*cOM$eZ`plZVN|5+)$q1YoTL$64X+u>z(~uHT+f3-vV@u6;;^>*=6OZyWk+|YzBRcfxwLDa%l?NtGf6Lh%J#3MG|3PZOfri(|o;PY~9;M9l_qDSZG(f{`?zYoJXBWhZU*k)d0=7*t-9WZkpo z_{!CBQU?xc-W&H2kT?=Tc>E|ki`xc>EGp75N+r3r8iDjxA=GtAABMLj4o3Mq2?rOI zChwFBj0Ab0ew@2G8a^B+gsNETQdZmiZJK8N` zYdT;{Oz(pOV|uxd#PjtklF(zOmde_!7rw(0k3L;0v;K04zP!dRwtD2o)m@&?2Yh^E zJlEe9qQ6e|S}sh>%XL#6o%CGN!Y$;kvrHcKVTTxXQOg^TUx>t2=x0;QWk*+U^!KmK*G_U zaPjFFn7l~*SI?7P2QJQ@&4ZpQR`S5|GU8`;hh$+=o_evk2DZVVq zDDgHLqtFhCL4G_!ri@utMH`@>Nbxl|R%^5XXMvDEr^zgD!8KnP_TnrWdwHfLGPEzM_Rbqi<+YXg#l zr~_{+SjItgWIc)mPZ(q?ni8BhTVkl10q1_GGtZ~9hd$ldSNX&bJu?niEAlQNKL4}E zUCZ_p>zN~4vpwqE6bQ!7$^*d)giQCu4{Qa#4zf^CE3~GCwxJ zLBpi_IKk3`C-^jUo?mn^)ZG2(dm>XH|53Oxk4K zG)auhezEFMe}1GLYYt$cw_2SWrJh;T<6T;-pRKKO^o_csu{&m^Mvvc8#Hj%&M7hyo zhhz+J(}XVyuLqO(fZNVW1WN~)(;b90i+^eY*e3I_NRp$D@UR1YxC;TGQGH-pjB8Uz z-K*c)A+m&nm?A*`^P&R>9et!&k;Hd4Zd&Nc#jSvEobZm-mQv$hP5JSAB%q5M*55lV zzmbT$Len_1%y*gTjvG^Kz@GA+7wPr-^aD`Sp&>)(RC%YJgn~Ok+A?E@cEYBm`IaSJ zCij;sX%Md6Ykd9w+lPUm!!*5XB4F@&XDD$g{Kl8U;lX~4|bQ&o&tCrx2J$~)j&Ipm2R*it zwHGJ2mX%}`KBs=N5Ckv~iA>t6S4P&KKbU;E{rO_!%IW6oxwd21PK#*Z32CAiS1RW| z$s!DtFVAmLlwFhJd~N@aGgNgr_W(@*I>E`zcphZaoc&Uf_dHzMEQ6+^-`ON-;3ooy zZvB8+Sf5#r5`nwyeK?GDou&mI#biF;0?syFNNEsX45zu~523uIR4)P))YNy6=* zCrp_-EU`|Suz{_yXf$9NeWSb&0z27}$z5hu(e`^ zRdj(k@C+-b>PgjV^su)M4YwqVfw-J;F_zg;ec*&CmCYD*r%}KQkp!tR&c$I#XiS;y zWL99~*-%L{pXHAJm^3<)eRmw@-LEqnUSvPd4ovbPBFU6CGttBgFaXaEaWi0m!q~S4 z@y#qXV1c4E%2FkCr$oUZO>H1GN3+R(e^kbr|2l_-lk8LvpdD9gYtUv&87w(vv0M5n z!()6xRwzaSOq&}TSphd~rIqCBWyhDSpj}wuSVKEfJ^C1*lV0^cm!%TTrzpl_7X+D0mJLQ*T+?W=ULRx&B$9RDqBh#F zTE;iNrM{r}k>1E^l(RyTZDqPJES%MR~2SEI}d;;wuUyaS{IuUB=- zKpo@;6pjRv5Pmo5>v zDfJOxAxb4Q(*P6MrUirnRiE-sE|9c5>#8f-jp?AGBS+F~s%3sA5E%xPnv(m1WlNG5(fE&w?cQRxqB=I~8UC(a!kbq-Q$?01_%fEC&K%nTD?7^P#U-Bx}+NOLf9XxMMhhQpT~77+>APfJdbXR~8bE{OvvJtpno#a{9uTL3OrR&K zN3lX18AlJfITglCExg1pNDo6pHz|qM)+eI`c=UIUpiTX*J)4$-c}#lsP+HB|XAe9m z70Y-Kp2H00&$9gh*!d}W&Gyu6Fm-{HxsH!sgGvG)HQ?hiodNrIcy`!@n$8K*P|mJJ zU>qe_6$=RXYH`g{HRq67F&oVLd7c7_;I+_x&F3r?S%(IJ(_!SwxMc{^S*Hh~QgEsR z?3oBvYBML~FHU!EW!=LLL^OhAU$Y9NJ4xpca-a`HDBs^EP13`Xlzz)(i_2_EWrwEM zEQP9E0w&ZYjeeF+#Gvxzcmb<>d)=~f`0!3HkQlO@mUZL?KKZ!+I_iM^z#90^&p<@d zh3rr4Q6>*wv1{7#>+o1y;aa&`>BYE5L19_8=)U}Mjc;ex7CnkE+Aw6p;AcUsnQ*2l z92tnA=Y~@BLtV4jN(OAS&63Ydyr2%0lqQ3>a7+iREmNtXpr#PfdM2eyX($!LCI?)0ToPq!SHq9{-Rg9C5<036V5#%!)~ z?xR9S-C{HlnVy4bHmFasb{}X$3j!2tOjh23mROscmoXd5y<@MO26!=dEt|;Q8rQa? zSf-_jT|?Etb4eVd=G-_2E|__GGz;HN2*$5*eCnOxSu`ykE0BY@YK??&mTgI4r`I8O z%h|d2+IDJv-CkjND!SFkL)ZDiRl8UV|1@?YGg*joyJ*_(M&Y!0{QfND$*RU} zY~^oBhd6^>jpH1HeW?LL@W8h>8_5mZ^j0guYLzNb2d=EL>C$+;TO=vdloRQyBsaNg zp+p1mROq==fdwG+-^n;DLb0-3@Cm$B=czBkA`)On1oL1Mnj08|XleqyeD<&+S4IsQ zis3O{7u(<#03nO#6h0*GFnZ>cYJ>s}dq&Dotpr1P$-uAI?=Cmp#y0!1&1{qh_s#zN z3c-|b^~+ES~2DX8-78XHf&XW?`717E3?apZ7F2wRDnyHg(k#~TUu~=V7oei2sjk!J8fngI?dVAB*-Q5%YNfS zg}|w29fR@O894LCPG0(_GvvxidbYIwa;nnkcOKL@K$}=HiEevme^@r-WVWu~&Fbiz z5Tdh@)=~EzXyExF(_ru_26G#)fXzEJ#X+;2*_{uoz{-?SLpd2&Ci2god5v=;WgUbN z-A@&os8&MsuP;gcAd0ev1486`mK!z9xDYRzlJ{T0C5`9w#DV{_$9+L5UM^)!&zjjp?Q^sWXt`sq^4E@uxH!a4bdI; zL*NCzC<+tZV``tOBR}&Nz`%Z!m<|9E3NP#Dm-#{A=k87EA=u@kpEZ?r!{D#ffN$YA z@N@*e$qv>j?rkLmd7^`Yg<>Phd)8Wj7`5?pDSdPxAQ%Ngh}q!veU}`yu)yln zMpp^wla{4XiC1-dzc9jcuY=OMC$vBMA;o?$&r>H~v08Dl1tb+n{N8;&Ke6EeJyQqG z8aZLP5&NkN&$ops3lNWQ{Oc<{wB>|Q0ZMsFV-bX;oRpVt@jQWRFoUELyr1~Q$3=~7 z*cu8qfhm#mFCgV`DzD||s`s`AJ24NOe$4bxuDNs4^+`^lV3&`sf0AL7PMdhGdF3qD zEZ^~qk;RMQ&^p>`t(pLGMYWDJ!AF>y;-g*d?HkxYHotWHzM;#T@|8EP0X8ZYVv?B$%ne}`9 z*XYxCHHBsGD;**f9yYUjPZ>U?o<3T8Hni!AEJ*H~nEc(9#zOt4dY4SPE4QPs+I-x0 zX_4*upngV1Q%%_f=9VC@{6Nl!EOO-%#QjX6W?rbi|BUO~>E_sYUS9%ffGxz4P+akO zz=DtpHD>W$b4lc&y{Y?pl^py{b=H%pI8M6QO0w1oo9{Vg+m21xV|6%=v{Kua`oFb^ zwVnRpg0ql)N&rL&zz+agT5-T7ABsyy1?}mtrcWHWMOq2o57;M(?ViRZ!bp=yc1*|+ zue%zlIRm(PVhuTA615*^Cs}5As6DhLDUjR5?c8JPT7!un@RC044|CqI5*fT z$N}~Tk1&dEuo5uUJ(&7se$y3xT-M3=k&jmqKdR-Zd?3d_rZHrv(X6@2uXI*`J zIw=Hx@oDo)!ze4JvL*9n2s7GbZA~z*-9%2;_ro+jeva=m`_c348D>WNgCA8onn=cT ztt;?U*sXYi4q{c1I4Rm48x;F2glRiNc4L-V^1YY9-q6F`*o8T$8Ie07emJ5m2U4Ck z+Ab<-aqONpr`;*Tpx3)O_pHT*2)Ll9@&L^ZRivjw^x^jOVeJNu=?v3{Pp71YPYO+Z zEyKCNWLPzM5I$&<0$nVD#*#RC<)F@IdC&-P1)mXjUcA<*p%QMC?)GBzR=kuv*g}(d zX(bj=IgAC%x7BH#o_Wulq6e42aC3-8$W2%qDfP=^Mz=5H;{Z6m#>)3@)qQHnb#B^7 zH~GWqU}oi;(A<#_Q=0WvJ<~V^!$fM*XGPXyB2Ai2+mj)BJ6)O=sp}SjnQBr)YkR7m zwJ?S0qwmmHJh;nKmy{>xK@mpf)-IT)P`S{FuDUh`CDaQZOD&DRCHl-PEMYd%8uNkIH^kQ*(BBrHF8tFML)*%e_# z6#W?Z{>=Ax^fn>d`Ch|d_-*RQM-zd;16~u>m|3EUQ{_Brdb(2zzLumH5keo0cFG~P zNE&C43hnB?DI)em3=CsFQ)P*$nVc}aa@Y!0Bi*OlxwfU43C{Q}?;N#|+339Mz$wMkQVxGz+O7rtS+rPQwRzxD`bcuc5r{T$hVB68RJvD<0Pm!b?YvUd5VuDh?Eag8;8m_AGqJ z^2O6gNqrwP@eW5a58sY0Dx>7SLDH8a_i>9uODe1v?Z9|FWIqF4!hVT(1w~?X)D+etYRb=Bn+?gfI)2 z(25V!!H|1EkEx{a>5D67vfs1wJZovutAc2fkN_reDkE&XJifKv6@Dy!+9XrJ-A}wc zni~t$TLL?Pgo+G;V~lSWT%QL?<))Yp;k9P$P4-HUKLsfw_MJS!b#+M>Xh5l3V&ndrA4|MAU4jUFa1)am_F@LQbS RCkXsA+`V_#qa8=W{~vYrMxg)z literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..7de3b2c --- /dev/null +++ b/public/index.html @@ -0,0 +1,1035 @@ + + + + + + + + + + + + + + + + + + + + + + + Monero Documentation - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Unofficial Monero Documentation

    +

    Work in Progress

    +

    Monerodocs attempts to organize basic technical knowledge on Monero in one place.

    +

    While technical explanations are out there, knowledge is scattered through reddit posts, git comments, stack exchange answers, chat logs and the source code. This makes it hard to find complete and up-to-date explanations on advanced topics.

    +

    The goal is to educate and onboard power users faster.

    +

    Please submit your feedback and corrections directly on github.

    +

    Find my contact details at qertoip.com.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/infrastructure/monero-pulse/index.html b/public/infrastructure/monero-pulse/index.html new file mode 100644 index 0000000..b16b319 --- /dev/null +++ b/public/infrastructure/monero-pulse/index.html @@ -0,0 +1,1208 @@ + + + + + + + + + + + + + + + + + + + + + + + MoneroPulse - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + + + + +
    +
    + + + + + + + +

    MoneroPulse

    +

    What is MoneroPulse?

    +

    MoneroPulse is infrastructure for emergency checkpointing the blockchain.

    +

    It aims to mitigate chain-splits resulting from consensus bugs (like this one from 2014).

    +

    Effectively, MoneroPulse operators can publish which fork they consider the valid one. Technically, the "checkpoint" they publish is a block hash and the block height.

    +

    By default, Monero full node will simply warn users when MoneroPulse checkpoint does not match the fork it is on. The error will be present in the log and on the console in red. Users are free to discard it. Ideally though, users should consult community on what is going on, and make educated decission on whether to follow the checkpoint-compatible fork or the default fork.

    +

    Users can also set auto-enforcing the checkpoints via --enforce-dns-checkpointing option to monerod. In case of mismatch, monerod will rollback the local blockchain by a few blocks. Eventually, the alternative ("fixed") fork will get heavier and the node will follow it, leaving the "invalid" fork behind. This option is recommended for unattended full nodes.

    +

    Summing up, MoneroPulse is emergency checkpointing mechanism. It is opt-in for the users.

    +

    MoneroPulse is DNS based

    +

    The ckeckpoints are stored as DNS TXT records for domains owned by MoneroPulse operators.

    +

    To get the idea you can access the checkpoints manually with any DNS client:

    +

    Try:

    +
    dig -t txt checkpoints.moneropulse.net +dnssec
    +
    +

    Result:

    +
    (cut)
    +
    +;; ANSWER SECTION:
    +checkpoints.moneropulse.net. 299 IN  TXT  "1288616:875ac1bc7aa6c5eedc5410abb9c694034f9e7f79dce4c60698baf37009cb6365"
    +checkpoints.moneropulse.net. 299 IN  TXT  "375000:c80c23e387585e12ffb6649d678e9ba328181797b9583a6d8911b77e25375737"
    +checkpoints.moneropulse.net. 299 IN  TXT  "325000:4260d56368267bc2a70dd58d73c5ecf23b4e4d96e63c29a868e4a679b0741c7f"
    +checkpoints.moneropulse.net. 299 IN  TXT  "233000:4f69bec2af6c0852412bdd10c19e6af10c8d738fe2618b5511a98efd03ab477e"
    +checkpoints.moneropulse.net. 299 IN  TXT  "450000:4d098b511ca97723e81737c448343cfd4e6dadb3d8a0e757c6e4d595e6e48357"
    +checkpoints.moneropulse.net. 299 IN  TXT  "250000:f59d31839bd909ec8830b4f7f66ff213f0bd006334c8523daee452725e5c7a79"
    +checkpoints.moneropulse.net. 299 IN  TXT  "550000:c2e80a636438bd9f7a7ab432a6ad297e35540d80ff5b868bca098124cad2ff8c"
    +checkpoints.moneropulse.net. 299 IN  TXT  "650000:1d567f2b491324375a825895c5e7b52857b38e4fed0e42c40909c2d52240b4e0"
    +checkpoints.moneropulse.net. 299 IN  TXT  "800000:2ced10aa85357ab6c14bb12b6b56d1dde28940820dda30911b73a5cc9a301760"
    +checkpoints.moneropulse.net. 299 IN  TXT  "850000:00e2b557dde9fd4a9e2e3dd7ddac962f5ca475eb1095bc50aa757fd1218ab0a5"
    +checkpoints.moneropulse.net. 299 IN  TXT  "900000:d9958d0e7dcf91a5a7b11de225927bf7efc6eb26240315ce12372be902cc1337"
    +checkpoints.moneropulse.net. 299 IN  TXT  "913193:5292d5d56f6ba4de33a58d9a34d263e2cb3c6fee0aed2286fd4ac7f36d53c85f"
    +checkpoints.moneropulse.net. 299 IN  TXT  "913269:f8302e6b8ba1c49aad9a854b8d6c79d8272c6239dcbba5a75ed0784c1d4f56a1"
    +checkpoints.moneropulse.net. 299 IN  TXT  "350000:74da79f6a136969abd6364bd3d37af273c408d6471e8ab598e80569b42415f86"
    +checkpoints.moneropulse.net. 299 IN  TXT  "400000:1b2b0e7a30e59691491529a3d506d1ba3d6052d0f6b52198b7330b28a6f1b6ac"
    +checkpoints.moneropulse.net. 299 IN  TXT  "500000:2428f0dbe49796be05ed81b347f53e1f7f44aed0abf641446ec2b94cae066b02"
    +checkpoints.moneropulse.net. 299 IN  TXT  "600000:f5828ebf7d7d1cb61762c4dfe3ccf4ecab2e1aad23e8113668d981713b7a54c5"
    +checkpoints.moneropulse.net. 299 IN  TXT  "700000:12be9b3d210b93f574d2526abb9c1ab2a881b479131fd0d4f7dac93875f503cd"
    +checkpoints.moneropulse.net. 299 IN  TXT  "300000:0c1cd46df6ccff90ec4ab493281f2583c344cd62216c427628990fe9db1bb8b6"
    +checkpoints.moneropulse.net. 299 IN  RRSIG  TXT 13 3 300 20180922151845 20180920131845 35273 moneropulse.net. 8CyqtsM2f9o6OHZYqtGPVf+8gcFM+eUyoMi29LlkcLtK1AXbZlKqCcdN NvdvB+4OzepmpTanSc+TbLWbz/sIzA==
    +
    +

    Please note the DNSSEC signature entry at the end.

    +

    The checkpoints are mirrored on several DNS servers:

    +

    Mainnet:

    +
    checkpoints.moneropulse.se
    +checkpoints.moneropulse.org
    +checkpoints.moneropulse.net
    +checkpoints.moneropulse.co
    +
    +

    Stagenet:

    +
    stagenetpoints.moneropulse.se
    +stagenetpoints.moneropulse.org
    +stagenetpoints.moneropulse.net
    +stagenetpoints.moneropulse.co
    +
    +

    Testnet:

    +
    testpoints.moneropulse.se
    +testpoints.moneropulse.org
    +testpoints.moneropulse.net
    +testpoints.moneropulse.co
    +
    +

    MoneroPulse as attack vector

    +

    It is worth noting that MoneroPulse does not produce blocks and cannot split the chain on its own. It only suggests the valid fork.

    +

    Should MoneroPulse got entirely compromised, attacker could stop all auto-enforcing nodes from advancing, by feeding them with the fake checkpoint. This is partially mitigated by DNSSEC and by operating multiple domains. Monero expects checkpoints are consistent across domains. Thus, compromising a single domain or registrar should not lead to any disruption.

    +

    MoneroPulse also increases the say of its operators in case of possible contentious hard forks. While well intended, this effectively centralizes more power in hands of core developers, or whomever is at the time running MoneroPulse infrastructure.

    +

    Who are MoneroPulse operators?

    +

    MoneroPulse is operated by selected core developers.

    +

    Fixing "WARNING: no two valid MoneroPulse DNS checkpoint records were received"

    +

    This means DNS server you are using does not ackonwledge the +dnssec flag necessary for securely query for checkpoints.

    +

    By default, your operating system will use DNS server provided by your Internet Service Provider.

    +

    To fix this warning, change your DNS server either system-wide in your network configuration, or specifically for monerod.

    +

    Many people find Google's or Cloudflare's DNS servers superior to those offered by their ISPs.

    +

    Using Google DNS:

    +
    DNS_PUBLIC=tcp://8.8.8.8 ./monerod
    +
    +

    Using Cloudflare DNS:

    +
    DNS_PUBLIC=tcp://1.1.1.1 ./monerod
    +
    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/infrastructure/networks/index.html b/public/infrastructure/networks/index.html new file mode 100644 index 0000000..561c121 --- /dev/null +++ b/public/infrastructure/networks/index.html @@ -0,0 +1,1152 @@ + + + + + + + + + + + + + + + + + + + + + + + Mainnet, Stagenet, Testnet - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Networks

    +

    Monero offers three separate networks and blockchains: mainnet, stagenet and testnet. Every blockchain has its own genesis block and is entirely seperate from others. Also, corresponding p2p networks are separate.

    +

    Mainnet

    +

    Mainnet is the "production" network and blockchain.

    +

    Mainnet is the only blockchain where XMR units have value.

    +

    Mainnet is what people mean by default.

    +

    Default TCP ports (listening):

    +
      +
    • 18080 - p2p network
    • +
    • 18081 - JSON-RPC server
    • +
    • 18082 - ZMQ server
    • +
    +

    Stagenet

    +

    Stagenet is what you need to learn Monero safely.

    +

    Stagenet is technically equivalent to mainnet, both in terms of features and consensus rules. Similar to mainnet, use the latest official Monero release to be compatible with stagenet.

    +

    To get started:

    + +

    Default TCP ports (listening):

    +
      +
    • 38080 - p2p network
    • +
    • 38081 - JSON-RPC server
    • +
    • 38082 - ZMQ server
    • +
    +

    Stagenet was introduced in March 2018 as part of Monero 0.12.0.0.

    +

    Testnet

    +

    As a normal user, use stagenet instead. Testnet is for developers.

    +

    Testnet is the "experimental" network and blockchain where things get released long before mainnet.

    +

    Testnet forks early and often. Most of the time you need to compile Monero from source to be compatible with testnet. Otherwise you will get stuck on the old not-forked version.

    +

    To get started:

    + +

    Default TCP ports (listening):

    +
      +
    • 28080 - p2p network
    • +
    • 28081 - JSON-RPC server
    • +
    • 28082 - ZMQ server
    • +
    +

    Private Testnet

    +

    You can also create your private version of the testnet.

    +

    Private testnet gives more flexibility to arange for specific situations for developers.

    +

    Check the private testnet guide.

    +

    Why stagenet and testnet coins have no value?

    +

    If mainnet and stagenet are technically equivalent then why only mainnet coins have value?

    +

    This is simply the convention community embraced. Value only comes from a shared believe that mainnet coins will be accepted by other people in the future.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/infrastructure/tor-onion-p2p-seed-nodes/index.html b/public/infrastructure/tor-onion-p2p-seed-nodes/index.html new file mode 100644 index 0000000..deaf80f --- /dev/null +++ b/public/infrastructure/tor-onion-p2p-seed-nodes/index.html @@ -0,0 +1,1188 @@ + + + + + + + + + + + + + + + + + + + + + + + Tor Onion Seed Nodes for Monero P2P Network - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + + + + +
    +
    + + + + + + + +

    Tor onion seed nodes for Monero network

    +

    When this is necessary?

    +

    This is only necessary if you run a full node and you want to propagate locally-originating transactions over Tor (using tx-proxy option, see monerod reference). This allows you to mask your IP (as transaction originator) against P2P network surveillence, on top of Monero's built-in Dandelion++.

    +

    What are P2P seed nodes?

    +

    Your monero daemon will discover other P2P nodes but it needs to start somewhere. These starting nodes are known as "seed nodes". For clearnet the seed nodes are hardcoded in the software so no configuration is needed.

    +

    For the Tor network there are no hardcoded seed nodes. You must specify them manually by using the add-peer option in monero.conf.

    +

    Config snippet

    +

    These were tested working as of 2020-01-11. They are ran by volunteers and are not guaranteed to work or be maintained. See below how you can quickly test them.

    +
    # monero.conf snippet
    +# ...
    +add-peer=moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18080
    +add-peer=monerozf6koypqrt.onion:18080
    +add-peer=zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083        # https://github.com/monero-project/monero/blob/master/src/p2p/net_node.inl
    +add-peer=rno75kjcw3ein6i446sqby2xkyqjarb75oq36ah6c2mribyklzhurpyd.onion:28083        # it is mainnet despite the weird port
    +add-peer=sqzrokz36lgkng2i2nlzgzns2ugcxqosflygsxbkybb4xn6gq3ouugqd.onion:18083        # very flaky, works 1 in 3 times
    +add-peer=blzchctiibfjfvtukctsydhquucz2oajnxnfc5hh4ix35gyqjhdnaqqd.onion:18083        # full node by author of monerodocs.org
    +# ...
    +
    +

    How to test onion seed nodes?

    +

    You need Tor daemon installed and running on your laptop. You will also need torsocks command line tool that either comes with Tor or needs to be installed separately.

    +

    Test using torsocks and telnet

    +

    You need tor, torsocks and telnet installed.

    +

    To test speficic onion:

    +
    torsocks telnet moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion 18080
    +
    +

    The expected output (domain resolution errors are fine):

    +
    1610372702 ERROR torsocks[11332]: Unable to resolve. Status reply: 4 (in socks5_recv_resolve_reply() at socks5.c:677)
    +Trying 127.42.42.0...
    +Connected to moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion.
    +Escape character is '^]'.
    +
    +

    Test using torsocks and proxychains

    +

    You need tor, torsocks and proxychains installed.

    +

    To test specific onion:

    +
    proxychains nmap -Pn -p 18080 moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion
    +
    +

    The expected output (example):

    +
    [proxychains] Strict chain  ...  127.0.0.1:9050  ...  moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18080  ...  OK
    +Nmap scan report for moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion (224.0.0.1)
    +Host is up (0.74s latency).
    +rDNS record for 224.0.0.1: all-systems.mcast.net
    +
    +PORT      STATE SERVICE
    +18080/tcp open  unknown
    +
    +

    Not enough onion seed nodes

    +

    The onion seed nodes are a scarce resource. Most nodes are only maintained temporarily by their authors.

    +

    You can greatly contribute to Monero P2P network performance and resillience by running onion-enabled monero full node.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/download-monero-binaries/index.html b/public/interacting/download-monero-binaries/index.html new file mode 100644 index 0000000..8709a4d --- /dev/null +++ b/public/interacting/download-monero-binaries/index.html @@ -0,0 +1,1078 @@ + + + + + + + + + + + + + + + + + + + + + + + Download Monero - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Download Monero

    +

    A single archive contains all you need to start using Monero (the full node and the wallet).

    +

    We recommend downloading Monero binaries directly from GitHub:

    + +

    GUI is a graphical desktop wallet.

    +

    CLI is a commandline desktop wallet.

    +

    If you need more guidance check download Monero section on Monero website.

    +

    It is critical to verify the signature of downloaded archive.

    +

    Which version to download?

    +

    Download the latest version matching your operating system and processor architecture.

    +

    The CLI version is released earlier and is suitable for server deployments.

    +

    The GUI version contains both CLI and GUI. It is preferable for end-users.

    +

    All versions contain a full node and a wallet.

    +

    Why prefer GitHub over getmonero.org?

    +

    Binaries appear earlier on GitHub.

    +

    On top of that, if you fail to properly verify the signature, GitHub is safer, simply because you don't need to trust a separate website to not be compromised. +Obviously, you should still carefully verify the signature for each release. Signature verification is always the primary line of defense.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/monero-blockchain-export-reference/index.html b/public/interacting/monero-blockchain-export-reference/index.html new file mode 100644 index 0000000..f08875e --- /dev/null +++ b/public/interacting/monero-blockchain-export-reference/index.html @@ -0,0 +1,1300 @@ + + + + + + + + + + + + + + + + + + + + + + + monero-blockchain-export - Reference - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    monero-blockchain-export - Reference

    +
    +

    Note

    +

    Nowadays, there is little usage for raw blockchain export / import. In the past the p2p blockchain download was much slower. Back than blockchain.raw file was used to speed up the process of bootstrapping a node.

    +
    +

    Overview

    +

    The tool dumps local blockchain to raw format, known as the blockchain.raw file.

    +

    This could be useful if you want to process blockchain efficiently with your custom tools, +as the raw format is probably easier to work with than Monero's custom lmdb database.

    +

    The tool works on your local copy of the blockchain. It does not require monerod running.

    +

    Syntax

    +

    ./monero-blockchain-export [options]

    +

    Example:

    +

    ./monero-blockchain-export --help

    +

    Running

    +

    Go to directory where you unpacked Monero.

    +

    ./monero-blockchain-export --stagenet --output-file=/tmp/blockchain.raw

    +

    Options

    +

    Help

    + + + + + + + + + + + + + +
    OptionDescription
    --helpEnlist available options.
    +

    Pick network

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    (missing)By default monero-blockchain-export assumes mainnet.
    --stagenetExport stagenet blockchain.
    --testnetExport testnet blockchain.
    +

    Logging

    +

    Specifying the log file path is not supported.

    + + + + + + + + + + + + + +
    OptionDescription
    --log-level0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0. These are general presets and do not directly map to severity levels. For example, even with minimal 0, you may see some most important INFO entries. Example:
    ./monero-blockchain-export --log-level=1
    +

    Input

    + + + + + + + + + + + + + + + + + +
    OptionDescription
    --data-dirFull path to data directory. This is where the blockchain, log files, and p2p network memory are stored. For defaults and details see data directory.
    --database, --db-typeThe default and only valid value is lmdb.
    +

    Output

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --output-fileSpecify output file path. The default is $DATA_DIR/export/blockchain.raw. Example:
    ./monero-blockchain-export --output-file=/tmp/blockchain.raw
    --blocksdatOutput in blocks.dat format.
    --block-stopOnly export up to this block number. By default do the full export (value 0).
    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/monero-blockchain-import-reference/index.html b/public/interacting/monero-blockchain-import-reference/index.html new file mode 100644 index 0000000..3faa138 --- /dev/null +++ b/public/interacting/monero-blockchain-import-reference/index.html @@ -0,0 +1,1352 @@ + + + + + + + + + + + + + + + + + + + + + + + monero-blockchain-import - Reference - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    monero-blockchain-import - Reference

    +
    +

    Note

    +

    Nowadays, there is little usage for raw blockchain export / import. In the past the p2p blockchain download was much slower. Back than blockchain.raw file was used to speed up download process of bootstrapping a node.

    +
    +

    Overview

    +

    The tool imports bootstrap file blockchain.raw to your full node.

    +

    This could be useful if you want to decouple download from verification for any reason (like testing performance in isolation). +In this case, you may download the blockchain.raw file from https://downloads.getmonero.org/blockchain.raw.

    +

    Ideally though, you should use your own trusted blockchain.raw file that you exported earlier.

    +

    Please note that importing blockchain.raw will not speed up the process over syncing up from p2p network. +This is because usual bottlenecks are disk IO and verification, not the download.

    +

    The tool works on your local files. It does not require monerod running.

    +

    Syntax

    +

    ./monero-blockchain-import [options]

    +

    Example:

    +

    ./monero-blockchain-import --help

    +

    Running

    +

    Go to directory where you unpacked Monero.

    +

    ./monero-blockchain-import --stagenet --output-file=/tmp/blockchain.raw

    +

    Options

    +

    Help

    + + + + + + + + + + + + + +
    OptionDescription
    --helpEnlist available options.
    +

    Pick network

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    (missing)By default monero-blockchain-import assumes the mainnet blockchain.
    --stagenetImport stagenet blockchain.
    --testnetImport testnet blockchain.
    +

    Logging

    +

    Specifying the log file path is not supported.

    + + + + + + + + + + + + + +
    OptionDescription
    --log-level0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0. These are general presets and do not directly map to severity levels. For example, even with minimal 0, you may see some most important INFO entries. Example:
    ./monero-blockchain-import --log-level=1
    +

    Input

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --input-fileFull path to raw blockchain file. The default is $DATA_DIR/export/blockchain.raw.
    --block-stopOnly import up to this block height. By default import all blocks (value 0).
    --pop-blocksDiscard specified number of blocks from the tip of the bootstrapped blockchain. By default don't discard anything (value 0).
    +

    Output

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --data-dirFull path to data directory. This is where the blockchain, log files, and p2p network memory are stored. For defaults and details see data directory.
    --count-blocksCount blocks in the bootstrap file and exit.
    --drop-hard-forkWhether to drop hard fork data. Off by default (0).
    --databaseThe only valid value seems to be lmdb (the default).
    +

    Performance

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --dangerous-unverified-importThe safe default is to run verification (value 0). You can enable --dangerous-unverified-import if you are importing from your own and trusted blockchain.raw (which we assume was already verified). The "dangerous" mode will greatly speed up the process.
    --batchWhether to save to disk on an ongoing basis (the default, value 1) or maybe do everything in RAM and save everything in the end (value 0). No batching is only effective in combination with no verification (--dangerous-unverified-import). See also --batch-size.
    --batch-sizeHow often to save to disk expressed in number of blocks. By default save every 5000 blocks (when verifying) or every 20000 blocks (when not verifying). Big batches are faster but require more RAM.
    --resumeResume from current height if output database already exists (the default, value 1). Changing to --resume=0 doesn't change much — existing blocks are skipped pretty quickly and the process is resumed anyway.
    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/monero-config-file/index.html b/public/interacting/monero-config-file/index.html new file mode 100644 index 0000000..13e5bd6 --- /dev/null +++ b/public/interacting/monero-config-file/index.html @@ -0,0 +1,1211 @@ + + + + + + + + + + + + + + + + + + + + + + + Monero Configuration File - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Monero Configuration File

    +

    Applicability

    +

    By default Monero looks for bitmonero.conf in Monero data directory.

    +

    To use a specific config file add --config-file option:

    +

    ./monerod --config-file=/etc/monerod.conf

    +

    The --config-file option is available for:

    +
      +
    • monerod
    • +
    • monero-wallet-cli
    • +
    • monero-wallet-rpc
    • +
    • monero-gen-trusted-multisig
    • +
    +

    Syntax

    +
      +
    • option-name=value
    • +
    • valueless-option-name=1 for options that don't expect value
    • +
    • # comment
    • +
    • whitespace is ignored
    • +
    +

    Reference

    +

    All configuration options are the same as command line options for the binary.

    + +

    Skip the -- from --option-name.

    +

    Example:

    +

    ./monerod --log-level=4 --stagenet

    +

    translates to:

    +
    log-level=4
    +stagenet=1     # use value "1" to enable the value-less options like --stagenet
    +
    +

    Examples

    +

    monerod.conf

    +

    This config is tailored for production server usage.

    +
    # /etc/monero/monerod.conf
    +
    +# Data directory (blockchain db and indices)
    +data-dir=/home/monero/.monero  # Remember to create the monero user first
    +
    +# Log file
    +log-file=/var/log/monero/monerod.log
    +max-log-file-size=0            # Prevent monerod from managing the log files; we want logrotate to take care of that
    +
    +# P2P full node
    +p2p-bind-ip=0.0.0.0            # Bind to all interfaces (the default)
    +p2p-bind-port=18080            # Bind to default port
    +
    +# RPC open node
    +rpc-bind-ip=0.0.0.0            # Bind to all interfaces
    +rpc-bind-port=18081            # Bind on default port
    +confirm-external-bind=1        # Open node (confirm)
    +restricted-rpc=1               # Prevent unsafe RPC calls
    +no-igd=1                       # Disable UPnP port mapping
    +
    +# Slow but reliable db writes
    +db-sync-mode=safe
    +
    +# Emergency checkpoints set by MoneroPulse operators will be enforced to workaround potential consensus bugs
    +# Check https://monerodocs.org/infrastructure/monero-pulse/ for explanation and trade-offs
    +enforce-dns-checkpointing=1
    +
    +out-peers=64              # This will enable much faster sync and tx awareness; the default 8 is suboptimal nowadays
    +in-peers=1024             # The default is unlimited; we prefer to put a cap on this
    +
    +limit-rate-up=1048576     # 1048576 kB/s == 1GB/s; a raise from default 2048 kB/s; contribute more to p2p network
    +limit-rate-down=1048576   # 1048576 kB/s == 1GB/s; a raise from default 8192 kB/s; allow for faster initial sync
    +
    +

    monero-wallet-cli.conf

    +

    This config is tailored for desktop usage on stagenet.

    +
    # $HOME/.bitmonero/stagenet/monero-wallet-cli.conf
    +
    +# Pick network
    +stagenet=1
    +
    +# Connect to a remote full node    
    +daemon-address=monero-stagenet.exan.tech:38081
    +untrusted-daemon=1
    +
    +# Log file
    +log-file=/tmp/monero-wallet-cli.log
    +
    +# wallet-file=/home/YOUR-USER/.bitmonero/stagenet/wallets/MoneroExampleStagenetWallet
    +
    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/monero-wallet-cli-reference/index.html b/public/interacting/monero-wallet-cli-reference/index.html new file mode 100644 index 0000000..ad091cc --- /dev/null +++ b/public/interacting/monero-wallet-cli-reference/index.html @@ -0,0 +1,2147 @@ + + + + + + + + + + + + + + + + + + + + + + + monero-wallet-cli - Reference - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    + +
    +
    + + +
    +
    + + + + + + + +

    monero-wallet-cli - Reference

    +
    +

    Note

    +

    Get yourself comfortable with a friendly Monero CLI wallet. +It is the most reliable and most complete wallet for Monero. +Use stagenet for learning.

    +
    +

    Overview

    +

    Command line wallet

    +

    The "official" command line wallet for Monero. Available for Linux, macOS and Windows.

    +

    Wallet uses your private keys to understand your total balance, +transactions history, and to facilitate creating transactions.

    +

    However, wallet does not store the blockchain and does not directly participate in the p2p network.

    +

    The CLI wallet is the most reliable and most feature complete wallet for Monero.

    +

    Depends on the full node

    +

    Wallet connects to a full node to scan the blockchain for your transaction outputs and to send your transactions out to the network.

    +

    The full node can be either local (same computer) or remote.

    +

    Normally, you run the full node on the same computer as wallet (or within your home network).

    +

    Connection happens over HTTP and uses this API.

    +

    Any transaction leaving the wallet is already blinded by all Monero privacy features. +This means plain text HTTP communication isn't an issue on its own even if you connect to a remote node.

    +

    However, connecting to a remote node has other nuanced trade-offs, which is a topic for a separate article.

    +

    Syntax

    +

    ./monero-wallet-cli [options] [command]

    +

    Example:

    +

    ./monero-wallet-cli --stagenet

    +

    Running

    +

    Go to directory where you unpacked Monero.

    +

    Run the full node and wait until it syncs up with the network (may take up to a few days):

    +

    ./monerod --stagenet

    +

    In a separate terminal window, run the wallet:

    +

    ./monero-wallet-cli --stagenet --generate-new-wallet MoneroExampleStagenetWallet

    +

    Options

    +

    Help and version

    + + + + + + + + + + + + + + + + + +
    OptionDescription
    --helpEnlist available options.
    --versionShow monero-wallet-cli version to stdout. Example:
    Monero 'Boron Butterfly' (v0.14.0.0-release)
    +

    Pick network

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    (missing)By default wallet assumes mainnet.
    --stagenetRun on stagenet. Remember to run your daemon with --stagenet as well.
    --testnetRun on testnet. Remember to run your daemon with --testnet as well.
    +

    Logging

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --log-file <arg>Full path to the log file.
    --log-level <arg>0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0. These are general presets and do not directly map to severity levels. For example, even with minimal 0, you may see some most important INFO entries.
    --max-log-file-size <arg>Soft limit in bytes for the log file (=104850000 by default, which is just under 100MB). Once log file grows past that limit, monero creates the next log file with a UTC timestamp postfix -YYYY-MM-DD-HH-MM-SS.

    In production deployments, you would probably prefer to use established solutions like logrotate instead. In that case, set --max-log-file-size 0 to prevent monero from managing the log files.
    --max-log-files <arg>Limit on the number of log files (=50 by default). The oldest log files are removed. In production deployments, you would probably prefer to use established solutions like logrotate instead.
    +

    Full node connection

    +

    Wallet depends on a full node for all non-local operations. The following options define how to connect to monerod:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --daemon-address <arg>Use monerod instance at <host>:<port>. Example:
    ./monero-wallet-cli --daemon-address monero-stagenet.exan.tech:38081 --stagenet
    --daemon-host <arg>Use monerod instance at host <arg> instead of localhost.
    --daemon-port <arg>Use monerod instance at port <arg> instead of 18081.
    --daemon-login <arg>Specify username[:password] for monerod RPC API. It is based on HTTP Basic Auth. Mind that connections are by default unencrypted. Authentication only makes sense if you establish a secure connection (maybe via Tor, or SSH tunneling, or reverse proxy w/ TLS).
    --trusted-daemonEnable commands and behaviors which rely on monerod instance being trusted. Default for localhost connection. The trust in this context concerns preserving your privacy. Only use this flag if you do control monerod. Trusted daemon allows for commands like rescan_spent, start_mining, import_key_images and behaviors like not warning about potential attack on transient problems with transaction sending.
    --untrusted-daemonDisable commands and behaviors which rely on monerod instance being trusted. Default for a non-localhost connections. See --trusted-daemon for more details.
    --do-not-relayThe newly created transaction will not be relayed to the Monero network. Instead it will be dumped to a file in a raw hexadecimal format. Useful if you want to push the transaction through a gateway like https://xmrchain.net/rawtx. This may be easier to use over Tor than Monero wallet.
    --allow-mismatched-daemon-versionAllow communicating with monerod that uses a different RPC version.
    +

    Create new wallet

    + + + + + + + + + + + + + + + + + +
    OptionDescription
    --generate-new-wallet <arg>Create a new Monero wallet and save it to <arg> file. You will be asked for a password. The password is used to encrypt the wallet file but it is unrelated to your master spend key or mnemonic seed. Generate a very strong password with your password manager (~256 bits of entropy). Example:

    ./monero-wallet-cli --stagenet --generate-new-wallet $HOME/.bitmonero/stagenet/wallets/MoneroExampleStagenetWallet
    --kdf-rounds <arg>Concerns encrypting the wallet file. The wallet file is encrypted with ChaCha stream cipher. The encryption key is derived from the user supplied password by hashing the password with CryptoNight. This option defines how many times the CryptoNight hashing will be applied. The default is 1 round of hashing.

    Note this is unrelated to spend key generation.

    The more rounds the longer you will wait to open the wallet or send transaction. But also the attacker will have it harder to brute force your wallet password.

    Note: You will have to remember and provide the same kdf-rounds on every wallet access!

    Recommendation: Do not change the default value. Instead generate a very strong wallet password with your password manager (256 bits of entropy).
    +

    Open existing wallet

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --wallet-file <arg>Open existing wallet. Example:

    ./monero-wallet-cli --stagenet --wallet-file $HOME/.bitmonero/stagenet/wallets/MoneroExampleStagenetWallet

    This is only for wallet files generated with monero-wallet-cli, monero-wallet-gui, or monero-wallet-rpc tools. If you have other type of wallet then see importing options.
    --password <arg>Provide wallet password as a parameter instead of interactively. Remember to escape/quote as needed.

    Not recommended because the password will remain in your command history and will also be visible in the process table. For automation prefer --password-file.

    The option also works in combination with --generate-new-wallet.
    --password-file <arg>Provide password as a file in stead of interactively. Trailing \n are discarded when reading the password file.

    Prefer this over --password if you automate wallet access. Make sure the password file is meaningfully separated from the wallet file. Otherwise it provides no security benefit.

    The option also works in combination with --generate-new-wallet.
    +

    Restore wallet

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --generate-from-device <arg>Restore/generate a special wallet to work with a hardware device like Ledger or Trezor and save it to <arg> file. Example:

    ./monero-wallet-cli --stagenet --generate-from-device MoneroExampleDeviceWallet --subaddress-lookahead 5:20

    This is a one-time action. Next time you simply open the wallet.

    By default the command expects Ledger hardware connected. For Trezor hardware add --hw-device Trezor (expected ~May 2019).

    It will take up to 25 minutes with default settings. This is because hardware devices are slow to pre-generate subaddresses. To mitigate use low --subaddress-lookahead 5:20.

    The local wallet will not have private spend key and will not be able to spend on its own. It serves as a user interface and a bridge for low-power hardware devices. Transaction signing with a private spend key always happens on the hardware device.

    See the complete guide to hardware wallet setup.
    --generate-from-view-key <arg>Restore a view-only version of the wallet to track incoming transactions and save it to <arg> file. The wallet is created based on a secret view key and standard address. The secret view key is meant to be pasted as hexadecimal.
    --generate-from-spend-key <arg>Restore a wallet from secret spend key and save it to <arg> file. The secret spend key is meant to be pasted as hexadecimal.
    --restore-deterministic-walletRestore a wallet from secret mnemonic seed. Use this to restore from your 25 words backup.

    You will be asked for a password to encrypt the wallet file (once restored). Note this is not a passphrase to mnemonic seed. Mnemonic seeds generated by Monero official wallets are naked.
    --restore-height <arg>Only scan for transactions later than specific blockchain height. The default is 0. Raising the value makes wallet restoration radically faster. The optimal value should match the day you originally created the wallet (but cannot be later). The mapping between the block height and date/time is available on block explorers like https://xmrchain.net. For instance, if you created the wallet in 2019+ use 1730000.
    +

    Multisig wallet

    + + + + + + + + + + + + + + + + + +
    OptionDescription
    --generate-from-multisig-keys <arg>Create a standard wallet from multisig keys. This is useful to combine all multisig secret keys back into the standard wallet (when you no longer need the multisig). The wallet will then have control of the funds. It only supports providing all secret keys even if the multisig scheme allowed for less (only N/N not N/M).
    --restore-multisig-walletRestore a multisig wallet from secret seed that was earlier exported with the seed interactive command. This only restores your part of the wallet. Other multisig participants will still be necessary to sign the transaction.
    +

    Config file

    + + + + + + + + + + + + + +
    OptionDescription
    --config-file <arg>Full path to the configuration file. Note this should be a separate config than monerod uses because these tools accept different set of options.
    +

    Performance

    + + + + + + + + + + + + + + + + + +
    OptionDescription
    --subaddress-lookahead <arg>Accepts m:n, by default 50:200. The first value is the number of accounts and the second value is the number of subaddresses per account.

    The wallet will not check for payments to subaddresses further than n away from the last received payment. This can happen if you generated unique subaddresses for n clients in a row but none of them paid.

    On the other hand the more subaddresses you set to look ahead, the longer it takes to create your wallet, because they must be pre-computed. This is normally not a concern, except for hardware wallets. On the Ledger the default value of 50:200 can take over 20 minutes (one time on wallet creation)!
    --max-concurrency <arg>Max number of threads to use for parallel jobs. The default value 0 uses the number of CPU threads.
    +

    Internationalization

    + + + + + + + + + + + + + + + + + +
    OptionDescription
    --mnemonic-language <arg>Language for mnemonic seed words. One of english, english_old, esperanto, french, german, italian, japanese, lojban, portuguese, russian, spanish.

    It might be a good idea to stick to default English which is by far the most popular and well tested. It also avoids potential non-ASCII characters pitfalls or bugs.
    --use-english-language-namesIf your display freezes, exit blind with ^C, then run again with --use-english-language-names. This can happen when Monero prompts for a language displaying language names in their natives alphabets.
    +

    Legacy

    +

    These options are either legacy or rarely useful.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --non-deterministicGenerate legacy non-deterministic wallet. The view key will not be derived from the spend key. You would also have to backup the .keys. To restore non-deterministic wallet (standard address) use --generate-from-keys. To restore fully you will need the .keys file.
    --generate-from-keys <arg>Restore legacy non-deterministic wallet by providing both spend and view keys and the standard address.
    --shared-ringdb-dir <arg>Set shared ring database path. No longer worthwhile.
    --create-address-fileHas no effect. The *.address.txt file is created regardless of this option.
    --electrum-seed <arg>Provide mnemonic seed as a commandline option for --restore-deterministic-wallet instead of interactively. This is not recommended b/c the seed will be saved in your command history and also visible in the process list.
    --generate-from-json <arg>You would run monero-wallet-rpc to use this option. It seems exposed in monero-wallet-cli by accident.
    --tx-notify <arg>You would run monero-wallet-rpc to use this option. It seems exposed in monero-wallet-cli by accident.
    +

    Defaults

    +

    Wallet files are created and seek in current directory. This is rarely what you want. Use --wallet-file and similar options to control this.

    +

    Log files are created in the same directory as monero-wallet-cli binary. Use --log-file to specify the location.

    +

    Commands

    +

    Commands are used interactively in the monero-wallet-cli prompt.

    +

    You can also run a one-off command by providing it as a commandline parameter. +This is rarely useful though. For automation prefer monero-wallet-rpc.

    +

    The CLI wallet has built-in help for individual commands - we will not attempt to reproduce that. +Instead we focus on grouping commands so you can quickly find what you are looking for. +Use help command_name to learn more.

    +

    Help and version

    +

    help - list all commands

    +

    help command_name - show help for individual command

    +

    version - show version of the monero-wallet-cli binary

    +

    Network status

    +

    status - show if synced up to the blockchain height

    +

    fee - show current fee-per-byte and full node's mempool (the backlog of transactions depending on the priority)

    +

    wallet_info - show wallet file path, standard address, type and network

    +

    Balance

    +

    account - total balance; list accounts with respective balances

    +

    balance detail - within the current account, list addresses with respective balances

    +

    refresh - force refresh the balance and transactions by pulling latest blocks from the full node; this is often useful because auto-refresh only kicks in once in 90 seconds

    +

    Manage accounts

    +

    account

    +

    account new

    +

    account switch

    +

    account label

    +

    Manage addresses

    +

    address all

    +

    address new

    +

    address label

    +

    View transactions

    +

    show_transfers - show all transactions on the current account; optionally provide a filter: in | out | pending | failed | pool | coinbase; optionally provide subaddress index for output selection

    +

    show_transfer <txid> - show details of specific transaction

    +

    incoming_transfers [available|unavailable] [verbose] [index=<N1>[,<N2>[,...]]] - show the incoming transactions, all or filtered by availability and address index within current account; this will only show confirmed transactions; you will not see transactions awaiting in the mempool

    +

    get_tx_note <txid> - get a string note for transaction id

    +

    Keys and Passwords

    +

    Secret mnemonic seed

    +

    seed - show raw mnemonic seed

    +

    encrypted_seed - create mnemonic seed encrypted with the passphrase; you will need to remember or store the passphrase separately; restoring will not be possible without the passphrase

    +

    Secret keys

    +

    spendkey - show secret spend key and public spend key

    +

    viewkey - show secret view key and public view key

    +

    Wallet password

    +

    password - change wallet password; this password is used to encrypt the local wallet files; it does not change secret keys or backups

    +

    Proofs

    +

    get_reserve_proof -> check_reserve_proof - prove the balance

    +

    get_spend_proof -> check_spend_proof - prove you made the payment

    +

    sign <file> -> verify <filename> <address> <signature> - prove ownership of the address; allows to verify the file was signed by the owner of specific Monero address

    +

    get_tx_proof -> check_tx_proof

    +

    Multisig

    +

    Setup

    +

    prepare_multisig

    +

    make_multisig

    +

    finalize_multisig

    +

    Update

    +

    export_multisig_info

    +

    import_multisig_info

    +

    Other

    +

    submit_multisig

    +

    exchange_multisig_keys

    +

    export_raw_multisig_tx

    +

    sign_multisig <filename>

    +

    Hardware wallet

    +

    hw_reconnect - attempts to reconnect HW wallet

    +

    Mining

    +

    start_mining

    +

    stop_mining

    +

    Advanced

    +

    Outputs

    +

    unspent_outputs - show a list of, and a histogram of unspent outputs (indivisible pieces of your total balance)

    +

    export_outputs <file> -> import_outputs <file> - helps with cold spending; export outputs from a view-wallet to the cold-wallet to make it aware of what had been sent to it

    +

    mark_output_spent <amount>/<offset> | <filename> [add]

    +

    mark_output_unspent <amount>/<offset>

    +

    is_output_spent <amount>/<offset>

    +

    Key images

    +

    export_key_images <file> -> import_key_images <file> - used to inform the view-only wallet about outgoing transactions so it can calculate the real balance; normally view-only wallets only learn about incoming transactions, not outgoing

    +

    Tx private key

    +

    These allow to learn and verify transaction's private key r. +This was useful to create a proof of payment +but got superseded by get_spend_proof.

    +

    get_tx_key <txid>

    +

    check_tx_key <txid> <txkey> <address>

    +

    set_tx_key <txid> <tx_key>

    +

    Debugging

    +

    rescan_spent - rescan the blockchain for spent outputs; sometimes, the wallet's idea of what outputs are spent and what outputs are not get out of sync with the blockchain. This can happen if you exit the wallet without saving after sending a tx, or if it crashes. This will look for the key images on the blockchain to make sure it's up to date.

    +

    Cosmetics

    +

    donate <amount> - donate <amount> to development team

    +

    address_book [(add ((<address> [pid <id>])|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)]

    +

    set_description [free text note] -> get_description - manage convenience description of the wallet (the information is local)

    +

    Legacy

    +

    save - this now happens automatically

    +

    save_bc - this now happens automatically

    +

    bc_height - show blockchain height (superseded with status)

    +

    sweep_unmixable - only relevant for very old wallets (<= 2016); send all unmixable outputs to yourself with ring_size 10

    +

    locked_sweep_all - see

    +

    rescan_bc - rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself

    +

    TODO: document remaining commands

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/monero-wallet-gui-reference/index.html b/public/interacting/monero-wallet-gui-reference/index.html new file mode 100644 index 0000000..882cc65 --- /dev/null +++ b/public/interacting/monero-wallet-gui-reference/index.html @@ -0,0 +1,1209 @@ + + + + + + + + + + + + + + + + + + + + + + + monero-wallet-gui - Reference - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    monero-wallet-gui - Reference

    +

    Overview

    +

    Desktop GUI wallet

    +

    The "official" desktop wallet for Monero. Available for Linux, macOS and Windows.

    +

    Wallet uses your private keys to understand your total balance, +transactions history, and to facilitate creating transactions.

    +

    However, wallet does not store the blockchain and does not directly participate in the p2p network.

    +

    Depends on the full node

    +

    Wallet connects to a full node to scan the blockchain for your transaction outputs and to send your transactions out to the network.

    +

    The full node can be either local (same computer) or remote.

    +

    Normally, you run the full node on the same computer as wallet (or within your home network).

    +

    Connection happens over HTTP and uses this API.

    +

    Any transaction leaving the wallet is already blinded by all Monero privacy features. +This means plain text HTTP communication isn't an issue on its own even if you connect to a remote node.

    +

    However, connecting to a remote node has other nuanced trade-offs, which is a topic for a separate article.

    +

    User guide PDF

    +

    A nice PDF guide is available in the catalog you unpacked Monero. Make sure to check it out!

    +

    The online living version is also available:
    +https://github.com/monero-ecosystem/monero-GUI-guide/blob/master/monero-GUI-guide.md

    +

    Syntax

    +

    ./monero-wallet-gui [options]

    +

    Example:

    +

    ./monero-wallet-gui --log-file=/dev/null

    +

    Running

    +

    Go to directory where you unpacked Monero.

    +

    Run the full node and wait until it syncs up with the network (may take up to a few days):

    +

    ./monerod

    +

    In a separate terminal window, run the wallet:

    +

    ./monero-wallet-gui

    +

    Options

    +

    There are very few options because everything is set up via a GUI.

    + + + + + + + + + + + + + + + + + +
    OptionDescription
    --helpEnlists available options.
    --log-fileFull path to the log file. Example (mind file permissions):
    ./monerod --log-file=/var/log/monero/mainnet/monerod.log
    +

    Defaults

    +

    The wallet is created in $HOME/Monero/wallets/. +You may want to change it to $HOME/.bitmonero/wallets/ to have all Monero related files in one place. +This is possible on wallet creation wizard in the GUI.

    +

    The log file is created directly in the home directory $HOME/monero-wallet-gui.log. +You may want to change with --log-file=$HOME/.bitmonero/monero-wallet-gui.log option.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/monero-wallet-rpc-reference/index.html b/public/interacting/monero-wallet-rpc-reference/index.html new file mode 100644 index 0000000..7232809 --- /dev/null +++ b/public/interacting/monero-wallet-rpc-reference/index.html @@ -0,0 +1,4263 @@ + + + + + + + + + + + + + + + + + + + + + + + monero-wallet-rpc - Reference - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    monero-wallet-rpc - Reference

    +

    Introduction

    +

    This is a list of the monero-wallet-rpc calls, their inputs and outputs, and examples of each. The program monero-wallet-rpc replaced the rpc interface that was in simplewallet and then monero-wallet-cli.

    +

    All monero-wallet-rpc methods use the same JSON RPC interface. For example:

    +
    IP=127.0.0.1
    +PORT=18082
    +METHOD="make_integrated_address"
    +PARAMS="{\"payment_id\":\"1234567890123456789012345678900012345678901234567890123456789000\"}"
    +curl \
    +    -X POST http://$IP:$PORT/json_rpc \
    +    -d '{"jsonrpc":"2.0","id":"0","method":"'$METHOD'","params":'"$PARAMS"'}' \
    +    -H 'Content-Type: application/json'
    +
    +

    If the monero-wallet-rpc was executed with the --rpc-login argument as username:password, then follow this example:

    +
    IP=127.0.0.1
    +PORT=18082
    +METHOD="make_integrated_address"
    +PARAMS="{\"payment_id\":\"1234567890123456789012345678900012345678901234567890123456789000\"}"
    +curl \
    +    -u username:password --digest \
    +    -X POST http://$IP:$PORT/json_rpc \
    +    -d '{"jsonrpc":"2.0","id":"0","method":"'$METHOD'","params":'"$PARAMS"'}' \
    +    -H 'Content-Type: application/json'
    +
    +

    Note: "atomic units" refer to the smallest fraction of 1 XMR according to the monerod implementation. 1 XMR = 1e12 atomic units.

    +

    Index of JSON RPC Methods:

    + +

    JSON RPC Methods:

    +

    add_address_book

    +

    Add an entry to the address book.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • address - string;
    • +
    • payment_id - (optional) string, defaults to "0000000000000000000000000000000000000000000000000000000000000000";
    • +
    • description - (optional) string, defaults to "";
    • +
    +

    Outputs:

    +
      +
    • index - unsigned int; The index of the address book entry.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"add_address_book","params":{"address":"78P16M3XmFRGcWFCcsgt1WcTntA1jzcq31seQX1Eg92j8VQ99NPivmdKam4J5CKNAD7KuNWcq5xUPgoWczChzdba5WLwQ4j","description":"Third account"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "index": 1
    +  }
    +}
    +
    +

    change_wallet_password

    +

    Change a wallet password.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • old_password - string; (Optional) Current wallet password, if defined.
    • +
    • new_password - string; (Optional) New wallet password, if not blank.
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"change_wallet_password","params":{"old_password":"theCurrentSecretPassPhrase","new_password":"theNewSecretPassPhrase"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    check_reserve_proof

    +

    Proves a wallet has a disposable reserve using a signature.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • address - string; Public address of the wallet.
    • +
    • message - string; (Optional) Should be the same message used in get_reserve_proof.
    • +
    • signature - string; reserve signature to confirm.
    • +
    +

    Outputs:

    +
      +
    • good - boolean; States if the inputs proves the reserve.
    • +
    +

    In the example below, the reserve has been proven:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_reserve_proof","params":{"address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","signature":"ReserveProofV11BZ23sBt9sZJeGccf84mzyAmNCP3KzYbE1111112VKmH111118NfCYJQjZ6c46gT2kXgcHCaSSZeL8sRdzqjqx7i1e7FQfQGu2o113UYFVdwzHQi3iENDPa76Kn1BvywbKz3bMkXdZkBEEhBSF4kjjGaiMJ1ucKb6wvMVC4A8sA4nZEdL2Mk3wBucJCYTZwKqA8i1M113kqakDkG25FrjiDqdQTCYz2wDBmfKxF3eQiV5FWzZ6HmAyxnqTWUiMWukP9A3Edy3ZXqjP1b23dhz7Mbj39bBxe3ZeDNu9HnTSqYvHNRyqCkeUMJpHyQweqjGUJ1DSfFYr33J1E7MkhMnEi1o7trqWjVix32XLetYfePG73yvHbS24837L7Q64i5n1LSpd9yMiQZ3Dyaysi5y6jPx7TpAvnSqBFtuCciKoNzaXoA3dqt9cuVFZTXzdXKqdt3cXcVJMNxY8RvKPVQHhUur94Lpo1nSpxf7BN5a5rHrbZFqoZszsZmiWikYPkLX72XUdw6NWjLrTBxSy7KuPYH86c6udPEXLo2xgN6XHMBMBJzt8FqqK7EcpNUBkuHm2AtpGkf9CABY3oSjDQoRF5n4vNLd3qUaxNsG4XJ12L9gJ7GrK273BxkfEA8fDdxPrb1gpespbgEnCTuZHqj1A"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "good": true,
    +    "spent": 0,
    +    "total": 100000000000
    +  }
    +}
    +
    +

    In the example below, all wallet reserve has been proven:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_reserve_proof","params":{"address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","message":"I have 10 at least","signature":"...signature..."}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "good": true,
    +    "spent": 0,
    +    "total": 164113855714662789
    +  }
    +}
    +
    +

    In the example below, the wrong message is used, avoiding the reserve to be proved:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_spend_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","message":"wrong message","signature":"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "good": false
    +  }
    +}
    +
    +

    check_spend_proof

    +

    Prove a spend using a signature. Unlike proving a transaction, it does not requires the destination public address.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • txid - string; transaction id.
    • +
    • message - string; (Optional) Should be the same message used in get_spend_proof.
    • +
    • signature - string; spend signature to confirm.
    • +
    +

    Outputs:

    +
      +
    • good - boolean; States if the inputs proves the spend.
    • +
    +

    In the example below, the spend has been proven:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_spend_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","message":"this is my transaction","signature":"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "good": true
    +  }
    +}
    +
    +

    In the example below, the wrong message is used, avoiding the spend to be proved:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_spend_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","message":"wrong message","signature":"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "good": false
    +  }
    +}
    +
    +

    check_tx_key

    +

    Check a transaction in the blockchain with its secret key.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • txid - string; transaction id.
    • +
    • tx_key - string; transaction secret key.
    • +
    • address - string; destination public address of the transaction.
    • +
    +

    Outputs:

    +
      +
    • confirmations - unsigned int; Number of block mined after the one with the transaction.
    • +
    • in_pool - boolean; States if the transaction is still in pool or has been added to a block.
    • +
    • received - unsigned int; Amount of the transaction.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_tx_key","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","tx_key":"feba662cf8fb6d0d0da18fc9b70ab28e01cc76311278fdd7fe7ab16360762b06","address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "confirmations": 0,
    +    "in_pool": false,
    +    "received": 1000000000000
    +  }
    +}
    +
    +

    check_tx_proof

    +

    Prove a transaction by checking its signature.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • txid - string; transaction id.
    • +
    • address - string; destination public address of the transaction.
    • +
    • message - string; (Optional) Should be the same message used in get_tx_proof.
    • +
    • signature - string; transaction signature to confirm.
    • +
    +

    Outputs:

    +
      +
    • confirmations - unsigned int; Number of block mined after the one with the transaction.
    • +
    • good - boolean; States if the inputs proves the transaction.
    • +
    • in_pool - boolean; States if the transaction is still in pool or has been added to a block.
    • +
    • received - unsigned int; Amount of the transaction.
    • +
    +

    In the example below, the transaction has been proven:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_tx_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o","message":"this is my transaction","signature":"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "confirmations": 482,
    +    "good": true,
    +    "in_pool": false,
    +    "received": 1000000000000
    +  }
    +}
    +
    +

    In the example below, the wrong message is used, avoiding the transaction to be proved:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"check_tx_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o","message":"wrong message","signature":"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "confirmations": 0,
    +    "good": false,
    +    "in_pool": false,
    +    "received": 0
    +  }
    +}
    +
    +

    close_wallet

    +

    Close the currently opened wallet, after trying to save it.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"close_wallet"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    create_account

    +

    Create a new account with an optional label.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • label - string; (Optional) Label for the account.
    • +
    +

    Outputs:

    +
      +
    • account_index - unsigned int; Index of the new account.
    • +
    • address - string; Address for this account. Base58 representation of the public keys.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_account","params":{"label":"Secondary account"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "account_index": 1,
    +    "address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp"
    +  }
    +}
    +
    +

    create_address

    +

    Create a new address for an account. Optionally, label the new address.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • account_index - unsigned int; Create a new address for this account.
    • +
    • label - string; (Optional) Label for the new address.
    • +
    +

    Outputs:

    +
      +
    • address - string; Newly created address. Base58 representation of the public keys.
    • +
    • address_index - unsigned int; Index of the new address under the input account.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_address","params":{"account_index":0,"label":"new-sub"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "address": "7BG5jr9QS5sGMdpbBrZEwVLZjSKJGJBsXdZLt8wiXyhhLjy7x2LZxsrAnHTgD8oG46ZtLjUGic2pWc96GFkGNPQQDA3Dt7Q",
    +    "address_index": 5
    +  }
    +}
    +
    +

    create_wallet

    +

    Create a new wallet. You need to have set the argument "–wallet-dir" when launching monero-wallet-rpc to make this work.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • filename - string; Wallet file name.
    • +
    • password - string; (Optional) password to protect the wallet.
    • +
    • language - string; Language for your wallets' seed.
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_wallet","params":{"filename":"mytestwallet","password":"mytestpassword","language":"English"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    delete_address_book

    +

    Delete an entry from the address book.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • index - unsigned int; The index of the address book entry.
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"delete_address_book","params":{"index":1}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    export_key_images

    +

    Export a signed set of key images.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs:

    +
      +
    • signed_key_images - array of signed key images:
        +
      • key_image - string;
      • +
      • signature - string;
      • +
      +
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"export_key_images"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "signed_key_images": [{
    +      "key_image": "cd35239b72a35e26a57ed17400c0b66944a55de9d5bda0f21190fed17f8ea876",
    +      "signature": "c9d736869355da2538ab4af188279f84138c958edbae3c5caf388a63cd8e780b8c5a1aed850bd79657df659422c463608ea4e0c730ba9b662c906ae933816d00"
    +    },{
    +      "key_image": "65158a8ee5a3b32009b85a307d85b375175870e560e08de313531c7dbbe6fc19",
    +      "signature": "c96e40d09dfc45cfc5ed0b76bfd7ca793469588bb0cf2b4d7b45ef23d40fd4036057b397828062e31700dc0c2da364f50cd142295a8405b9fe97418b4b745d0c"
    +    },...]
    +  }
    +}
    +
    +

    export_multisig_info

    +

    Export multisig info for other participants.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs:

    +
      +
    • info - string; Multisig info in hex format for other participants.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"export_multisig_info"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "info": "4d6f6e65726f206d756c7469736967206578706f72740105cf6442b09b75f5eca9d846771fe1a879c9a97ab0553ffbcec64b1148eb7832b51e7898d7944c41cee000415c5a98f4f80dc0efdae379a98805bb6eacae743446f6f421cd03e129eb5b27d6e3b73eb6929201507c1ae706c1a9ecd26ac8601932415b0b6f49cbbfd712e47d01262c59980a8f9a8be776f2bf585f1477a6df63d6364614d941ecfdcb6e958a390eb9aa7c87f056673d73bc7c5f0ab1f74a682e902e48a3322c0413bb7f6fd67404f13fb8e313f70a0ce568c853206751a334ef490068d3c8ca0e"
    +  }
    +}
    +
    +

    export_outputs

    +

    Export all outputs in hex format.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs:

    +
      +
    • outputs_data_hex - string; wallet outputs in hex format.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"export_outputs"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "outputs_data_hex": "...outputs..."
    +  }
    +}
    +
    +

    finalize_multisig

    +

    Turn this wallet into a multisig wallet, extra step for N-1/N wallets.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • multisig_info - array of string; List of multisig string from peers.
    • +
    • password - string; Wallet password
    • +
    +

    Outputs:

    +
      +
    • address - string; multisig wallet address.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"finalize_multisig","params":{"multisig_info":["MultisigxV1JNC6Ja2oBt5Sqea9LN2YEF7WYZCpHqr2EKvPG89Trf3X4E8RWkLaGRf29fJ3stU471MELKxwufNYeigP7LoE4tn2McPr4SbL9q15xNvZT5uwC9YRr7UwjXqSZHmTWN9PBuZEKVAQ4HPPyQciSCdNjgwsuFRBzrskMdMUwNMgKst1debYfm37i6PSzDoS2tk4kYTYj83kkAdR7kdshet1axQPd6HQ","MultisigxV1Unma7Ko4zdd8Ps3Af4oZwtj2JdWKzwNfP6s2G9ZvXhMoSscwn5g7PyCfcBc1V4ffRHY3Kxqq6VocSCUTncpVeUskMcPr4SbL9q15xNvZT5uwC9YRr7UwjXqSZHmTWN9PBuZE1LTpWxLoC3vPMSrqVVcjnmL9LYfdCZz3fECjNZbCEDq3PHDiUuY5jurQTcNoGhDTio5WM9xaAdim9YByiS5KyqF4"]}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "address": "5B9gZUTDuHTcGGuY3nL3t8K2tDnEHeRVHSBQgLZUTQxtFYVLnho5JJjWJyFp5YZgZRQ44RiviJi1sPHgLVMbckRsDqDx1gV"
    +  }
    +}
    +
    +

    get_account_tags

    +

    Get a list of user-defined account tags.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs:

    +
      +
    • account_tags - array of account tag information:
        +
      • tag - string; Filter tag.
      • +
      • label - string; Label for the tag.
      • +
      • accounts - array of int; List of tagged account indices.
      • +
      +
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_account_tags","params":""}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "account_tags": [{
    +      "accounts": [0],
    +      "label": "Test tag",
    +      "tag": "myTag"
    +    }]
    +  }
    +}
    +
    +

    get_accounts

    +

    Get all accounts for a wallet. Optionally filter accounts by tag.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • tag - string; (Optional) Tag for filtering accounts.
    • +
    +

    Outputs:

    +
      +
    • subaddress_accounts - array of subaddress account information:
        +
      • account_index - unsigned int; Index of the account.
      • +
      • balance - unsigned int; Balance of the account (locked or unlocked).
      • +
      • base_address - string; Base64 representation of the first subaddress in the account.
      • +
      • label - string; (Optional) Label of the account.
      • +
      • tag - string; (Optional) Tag for filtering accounts.
      • +
      • unlocked_balance - unsigned int; Unlocked balance for the account.
      • +
      +
    • +
    • total_balance - unsigned int; Total balance of the selected accounts (locked or unlocked).
    • +
    • total_unlocked_balance - unsigned int; Total unlocked balance of the selected accounts.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_accounts","params":{"tag":"myTag"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "subaddress_accounts": [{
    +      "account_index": 0,
    +      "balance": 157663195572433688,
    +      "base_address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
    +      "label": "Primary account",
    +      "tag": "myTag",
    +      "unlocked_balance": 157443303037455077
    +    },{
    +      "account_index": 1,
    +      "balance": 0,
    +      "base_address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp",
    +      "label": "Secondary account",
    +      "tag": "myTag",
    +      "unlocked_balance": 0
    +    }],
    +    "total_balance": 157663195572433688,
    +    "total_unlocked_balance": 157443303037455077
    +  }
    +}
    +
    +

    get_address

    +

    Return the wallet's addresses for an account. Optionally filter for specific set of subaddresses.

    +

    Alias: getaddress.

    +

    Inputs:

    +
      +
    • account_index - unsigned int; Return subaddresses for this account.
    • +
    • address_index - array of unsigned int; (Optional) List of subaddresses to return from an account.
    • +
    +

    Outputs:

    +
      +
    • address - string; The 95-character hex address string of the monero-wallet-rpc in session.
    • +
    • addresses array of addresses informations
        +
      • address string; The 95-character hex (sub)address string.
      • +
      • label string; Label of the (sub)address
      • +
      • address_index unsigned int; index of the subaddress
      • +
      • used boolean; states if the (sub)address has already received funds
      • +
      +
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_address","params":{"account_index":0,"address_index":[0,1,4]}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
    +    "addresses": [{
    +      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
    +      "address_index": 0,
    +      "label": "Primary account",
    +      "used": true
    +    },{
    +      "address": "7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o",
    +      "address_index": 1,
    +      "label": "",
    +      "used": true
    +    },{
    +      "address": "77xa6Dha7kzCQuvmd8iB5VYoMkdenwCNRU9khGhExXQ8KLL3z1N1ZATBD1sFPenyHWT9cm4fVFnCAUApY53peuoZFtwZiw5",
    +      "address_index": 4,
    +      "label": "test2",
    +      "used": true
    +    }]
    +  }
    +}
    +
    +

    get_address_book

    +

    Retrieves entries from the address book.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • entries - array of unsigned int; indices of the requested address book entries
    • +
    +

    Outputs:

    +
      +
    • entries - array of entries:
        +
      • address - string; Public address of the entry
      • +
      • description - string; Description of this address entry
      • +
      • index - unsigned int;
      • +
      • payment_id - string;
      • +
      +
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_address_book","params":{"entries":[0,1]}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "entries": [{
    +      "address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp",
    +      "description": "Second account",
    +      "index": 0,
    +      "payment_id": "0000000000000000000000000000000000000000000000000000000000000000"
    +    },{
    +      "address": "78P16M3XmFRGcWFCcsgt1WcTntA1jzcq31seQX1Eg92j8VQ99NPivmdKam4J5CKNAD7KuNWcq5xUPgoWczChzdba5WLwQ4j",
    +      "description": "Third account",
    +      "index": 1,
    +      "payment_id": "0000000000000000000000000000000000000000000000000000000000000000"
    +    }]
    +  }
    +}
    +
    +

    get_address_index

    +

    Get account and address indexes from a specific (sub)address

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • address - String; (sub)address to look for.
    • +
    +

    Outputs:

    +
      +
    • index - subaddress informations
        +
      • major unsigned int; Account index.
      • +
      • minor unsigned int; Address index.
      • +
      +
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_address_index","params":{"address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "index": {
    +      "major": 0,
    +      "minor": 1
    +    }
    +  }
    +}
    +
    +

    get_attribute

    +

    Get attribute value by name.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • key - string; attribute name
    • +
    +

    Outputs:

    +
      +
    • value - string; attribute value
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_attribute","params":{"key":"my_attribute"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "value": "my_value"
    +  }
    +}
    +
    +

    get_bulk_payments

    +

    Get a list of incoming payments using a given payment id, or a list of payments ids, from a given height. This method is the preferred method over get_paymentsbecause it has the same functionality but is more extendable. Either is fine for looking up transactions by a single payment ID.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • payment_ids - array of: string; Payment IDs used to find the payments (16 characters hex).
    • +
    • min_block_height - unsigned int; The block height at which to start looking for payments.
    • +
    +

    Outputs:

    +
      +
    • payments - list of:
        +
      • payment_id - string; Payment ID matching one of the input IDs.
      • +
      • tx_hash - string; Transaction hash used as the transaction ID.
      • +
      • amount - unsigned int; Amount for this payment.
      • +
      • block_height - unsigned int; Height of the block that first confirmed this payment.
      • +
      • unlock_time - unsigned int; Time (in block height) until this payment is safe to spend.
      • +
      • subaddr_index - subaddress index:
          +
        • major - unsigned int; Account index for the subaddress.
        • +
        • minor - unsigned int; Index of the subaddress in the account.
        • +
        +
      • +
      • address - string; Address receiving the payment; Base58 representation of the public keys.
      • +
      +
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_bulk_payments","params":{"payment_ids":["60900e5603bf96e3"],"min_block_height":"120000"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "payments": [{
    +      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
    +      "amount": 1000000000000,
    +      "block_height": 127606,
    +      "payment_id": "60900e5603bf96e3",
    +      "subaddr_index": {
    +        "major": 0,
    +        "minor": 0
    +      },
    +      "tx_hash": "3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f",
    +      "unlock_time": 0
    +    }]
    +  }
    +}
    +
    +

    get_height

    +

    Returns the wallet's current block height.

    +

    Alias: getheight.

    +

    Inputs: None.

    +

    Outputs:

    +
      +
    • height - unsigned int; The current monero-wallet-rpc's blockchain height. If the wallet has been offline for a long time, it may need to catch up with the daemon.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_height"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "height": 145545
    +  }
    +}
    +
    +

    get_languages

    +

    Get a list of available languages for your wallet's seed.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs:

    +
      +
    • languages - array of string; List of available languages
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_languages"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "languages": ["Deutsch","English","Español","Français","Italiano","Nederlands","Português","русский язык","日本語","简体中文 (中国)","Esperanto","Lojban"]
    +  }
    +}
    +
    +

    get_payments

    +

    Get a list of incoming payments using a given payment id.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • payment_id - string; Payment ID used to find the payments (16 characters hex).
    • +
    +

    Outputs:

    +
      +
    • payments - list of:
        +
      • payment_id - string; Payment ID matching the input parameter.
      • +
      • tx_hash - string; Transaction hash used as the transaction ID.
      • +
      • amount - unsigned int; Amount for this payment.
      • +
      • block_height - unsigned int; Height of the block that first confirmed this payment.
      • +
      • unlock_time - unsigned int; Time (in block height) until this payment is safe to spend.
      • +
      • subaddr_index - subaddress index:
          +
        • major - unsigned int; Account index for the subaddress.
        • +
        • minor - unsigned int; Index of the subaddress in the account.
        • +
        +
      • +
      • address - string; Address receiving the payment; Base58 representation of the public keys.
      • +
      +
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_payments","params":{"payment_id":"60900e5603bf96e3"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "payments": [{
    +      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
    +      "amount": 1000000000000,
    +      "block_height": 127606,
    +      "payment_id": "60900e5603bf96e3",
    +      "subaddr_index": {
    +        "major": 0,
    +        "minor": 0
    +      },
    +      "tx_hash": "3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f",
    +      "unlock_time": 0
    +    }]
    +  }
    +}
    +
    +

    get_reserve_proof

    +

    Generate a signature to prove of an available amount in a wallet.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • all - boolean; Proves all wallet balance to be disposable.
    • +
    • account_index - unsigned int; Specify the account from witch to prove reserve. (ignored if all is set to true)
    • +
    • amount - unsigned int; Amount (in atomic units) to prove the account has for reserve. (ignored if all is set to true)
    • +
    • message - string; (Optional) add a message to the signature to further authenticate the prooving process.
    • +
    +

    Outputs:

    +
      +
    • signature - string; reserve signature.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_reserve_proof","params":{"all":false,"account_index":0,"amount":100000000000}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "signature": "ReserveProofV11BZ23sBt9sZJeGccf84mzyAmNCP3KzYbE1111112VKmH111118NfCYJQjZ6c46gT2kXgcHCaSSZeL8sRdzqjqx7i1e7FQfQGu2o113UYFVdwzHQi3iENDPa76Kn1BvywbKz3bMkXdZkBEEhBSF4kjjGaiMJ1ucKb6wvMVC4A8sA4nZEdL2Mk3wBucJCYTZwKqA8i1M113kqakDkG25FrjiDqdQTCYz2wDBmfKxF3eQiV5FWzZ6HmAyxnqTWUiMWukP9A3Edy3ZXqjP1b23dhz7Mbj39bBxe3ZeDNu9HnTSqYvHNRyqCkeUMJpHyQweqjGUJ1DSfFYr33J1E7MkhMnEi1o7trqWjVix32XLetYfePG73yvHbS24837L7Q64i5n1LSpd9yMiQZ3Dyaysi5y6jPx7TpAvnSqBFtuCciKoNzaXoA3dqt9cuVFZTXzdXKqdt3cXcVJMNxY8RvKPVQHhUur94Lpo1nSpxf7BN5a5rHrbZFqoZszsZmiWikYPkLX72XUdw6NWjLrTBxSy7KuPYH86c6udPEXLo2xgN6XHMBMBJzt8FqqK7EcpNUBkuHm2AtpGkf9CABY3oSjDQoRF5n4vNLd3qUaxNsG4XJ12L9gJ7GrK273BxkfEA8fDdxPrb1gpespbgEnCTuZHqj1A"
    +  }
    +}
    +
    +

    get_spend_proof

    +

    Generate a signature to prove a spend. Unlike proving a transaction, it does not requires the destination public address.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • txid - string; transaction id.
    • +
    • message - string; (Optional) add a message to the signature to further authenticate the prooving process.
    • +
    +

    Outputs:

    +
      +
    • signature - string; spend signature.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_spend_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","message":"this is my transaction"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "signature": "SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB"
    +  }
    +}
    +
    +

    get_transfer_by_txid

    +

    Show information about a transfer to/from this address.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • txid - string; Transaction ID used to find the transfer.
    • +
    • account_index - unsigned int; (Optional) Index of the account to query for the transfer.
    • +
    +

    Outputs:

    +
      +
    • transfer - JSON object containing payment information:
        +
      • address - string; Address that transferred the funds. Base58 representation of the public keys.
      • +
      • amount - unsigned int; Amount of this transfer.
      • +
      • confirmations - unsigned int; Number of block mined since the block containing this transaction (or block height at which the transaction should be added to a block if not yet confirmed).
      • +
      • destinations - array of JSON objects containing transfer destinations:
          +
        • amount - unsigned int; Amount transferred to this destination.
        • +
        • address - string; Address for this destination. Base58 representation of the public keys.
        • +
        +
      • +
      • double_spend_seen - boolean; True if the key image(s) for the transfer have been seen before.
      • +
      • fee - unsigned int; Transaction fee for this transfer.
      • +
      • height - unsigned int; Height of the first block that confirmed this transfer.
      • +
      • note - string; Note about this transfer.
      • +
      • payment_id - string; Payment ID for this transfer.
      • +
      • subaddr_index - JSON object containing the major & minor subaddress index:
          +
        • major - unsigned int; Account index for the subaddress.
        • +
        • minor - unsigned int; Index of the subaddress under the account.
        • +
        +
      • +
      • suggested_confirmations_threshold - unsigned int; Estimation of the confirmations needed for the transaction to be included in a block.
      • +
      • timestamp - unsigned int; POSIX timestamp for the block that confirmed this transfer (or timestamp submission if not mined yet).
      • +
      • txid - string; Transaction ID of this transfer (same as input TXID).
      • +
      • type - string; Type of transfer, one of the following: "in", "out", "pending", "failed", "pool"
      • +
      • unlock_time - unsigned int; Number of blocks until transfer is safely spendable.
      • +
      +
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_transfer_by_txid","params":{"txid":"c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "transfer": {
    +      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
    +      "amount": 300000000000,
    +      "confirmations": 1,
    +      "destinations": [{
    +        "address": "7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o",
    +        "amount": 100000000000
    +      },{
    +        "address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp",
    +        "amount": 200000000000
    +      }],
    +      "double_spend_seen": false,
    +      "fee": 21650200000,
    +      "height": 153624,
    +      "note": "",
    +      "payment_id": "0000000000000000",
    +      "subaddr_index": {
    +        "major": 0,
    +        "minor": 0
    +      },
    +      "suggested_confirmations_threshold": 1,
    +      "timestamp": 1535918400,
    +      "txid": "c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a",
    +      "type": "out",
    +      "unlock_time": 0
    +    }
    +  }
    +}
    +
    +

    get_transfers

    +

    Returns a list of transfers.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • in - boolean; (Optional) Include incoming transfers.
    • +
    • out - boolean; (Optional) Include outgoing transfers.
    • +
    • pending - boolean; (Optional) Include pending transfers.
    • +
    • failed - boolean; (Optional) Include failed transfers.
    • +
    • pool - boolean; (Optional) Include transfers from the daemon's transaction pool.
    • +
    • filter_by_height - boolean; (Optional) Filter transfers by block height.
    • +
    • min_height - unsigned int; (Optional) Minimum block height to scan for transfers, if filtering by height is enabled.
    • +
    • max_height - unsigned int; (Opional) Maximum block height to scan for transfers, if filtering by height is enabled (defaults to max block height).
    • +
    • account_index - unsigned int; (Optional) Index of the account to query for transfers. (defaults to 0)
    • +
    • subaddr_indices - array of unsigned int; (Optional) List of subaddress indices to query for transfers. (defaults to 0)
    • +
    +

    Outputs:

    +
      +
    • in array of transfers:
        +
      • address - string; Public address of the transfer.
      • +
      • amount - unsigned int; Amount transferred.
      • +
      • confirmations - unsigned int; Number of block mined since the block containing this transaction (or block height at which the transaction should be added to a block if not yet confirmed).
      • +
      • double_spend_seen - boolean; True if the key image(s) for the transfer have been seen before.
      • +
      • fee - unsigned int; Transaction fee for this transfer.
      • +
      • height - unsigned int; Height of the first block that confirmed this transfer (0 if not mined yet).
      • +
      • note - string; Note about this transfer.
      • +
      • payment_id - string; Payment ID for this transfer.
      • +
      • subaddr_index - JSON object containing the major & minor subaddress index:
          +
        • major - unsigned int; Account index for the subaddress.
        • +
        • minor - unsigned int; Index of the subaddress under the account.
        • +
        +
      • +
      • suggested_confirmations_threshold - unsigned int; Estimation of the confirmations needed for the transaction to be included in a block.
      • +
      • timestamp - unsigned int; POSIX timestamp for when this transfer was first confirmed in a block (or timestamp submission if not mined yet).
      • +
      • txid - string; Transaction ID for this transfer.
      • +
      • type - string; Transfer type: "in"
      • +
      • unlock_time - unsigned int; Number of blocks until transfer is safely spendable.
      • +
      +
    • +
    • out array of transfers (see above).
    • +
    • pending array of transfers (see above).
    • +
    • failed array of transfers (see above).
    • +
    • pool array of transfers (see above).
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_transfers","params":{"in":true,"account_index":1}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "in": [{
    +      "address": "77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp",
    +      "amount": 200000000000,
    +      "confirmations": 1,
    +      "double_spend_seen": false,
    +      "fee": 21650200000,
    +      "height": 153624,
    +      "note": "",
    +      "payment_id": "0000000000000000",
    +      "subaddr_index": {
    +        "major": 1,
    +        "minor": 0
    +      },
    +      "suggested_confirmations_threshold": 1,
    +      "timestamp": 1535918400,
    +      "txid": "c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a",
    +      "type": "in",
    +      "unlock_time": 0
    +    }]
    +  }
    +}
    +
    +

    get_tx_key

    +

    Get transaction secret key from transaction id.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • txid - string; transaction id.
    • +
    +

    Outputs:

    +
      +
    • tx_key - string; transaction secret key.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_tx_key","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "tx_key": "feba662cf8fb6d0d0da18fc9b70ab28e01cc76311278fdd7fe7ab16360762b06"
    +  }
    +}
    +
    +

    get_tx_notes

    +

    Get string notes for transactions.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • txids - array of string; transaction ids
    • +
    +

    Outputs:

    +
      +
    • notes - array of string; notes for the transactions
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_tx_notes","params":{"txids":["3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f"]}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "notes": ["This is an example"]
    +  }
    +}
    +
    +

    get_tx_proof

    +

    Get transaction signature to prove it.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • txid - string; transaction id.
    • +
    • address - string; destination public address of the transaction.
    • +
    • message - string; (Optional) add a message to the signature to further authenticate the prooving process.
    • +
    +

    Outputs:

    +
      +
    • signature - string; transaction signature.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_tx_proof","params":{"txid":"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be","address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o","message":"this is my transaction"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "signature": "InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ"
    +  }
    +}
    +
    +

    get_version

    +

    Get RPC version Major & Minor integer-format, where Major is the first 16 bits and Minor the last 16 bits.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs:

    +
      +
    • version - unsigned int; RPC version, formatted with Major * 2^16 + Minor(Major encoded over the first 16 bits, and Minor over the last 16 bits).
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_version"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "version": 65539
    +  }
    +}
    +
    +

    import_key_images

    +

    Import signed key images list and verify their spent status.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • signed_key_images - array of signed key images:
        +
      • key_image - string;
      • +
      • signature - string;
      • +
      +
    • +
    +

    Outputs:

    +
      +
    • height - unsigned int;
    • +
    • spent - unsigned int; Amount (in atomic units) spent from those key images.
    • +
    • unspent - unsigned int; Amount (in atomic units) still available from those key images.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"import_key_images", "params":{"signed_key_images":[{"key_image":"cd35239b72a35e26a57ed17400c0b66944a55de9d5bda0f21190fed17f8ea876","signature":"c9d736869355da2538ab4af188279f84138c958edbae3c5caf388a63cd8e780b8c5a1aed850bd79657df659422c463608ea4e0c730ba9b662c906ae933816d00"},{"key_image":"65158a8ee5a3b32009b85a307d85b375175870e560e08de313531c7dbbe6fc19","signature":"c96e40d09dfc45cfc5ed0b76bfd7ca793469588bb0cf2b4d7b45ef23d40fd4036057b397828062e31700dc0c2da364f50cd142295a8405b9fe97418b4b745d0c"}]}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "height": 76428,
    +    "spent": 62708953408711,
    +    "unspent": 0
    +  }
    +}
    +
    +

    import_multisig_info

    +

    Import multisig info from other participants.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • info - array of string; List of multisig info in hex format from other participants.
    • +
    +

    Outputs:

    +
      +
    • n_outputs - unsigned int; Number of outputs signed with those multisig info.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"import_multisig_info","params":{"info":["...multisig_info..."]}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "n_outputs": 35
    +  }
    +}
    +
    +

    import_outputs

    +

    Import outputs in hex format.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • outputs_data_hex - string; wallet outputs in hex format.
    • +
    +

    Outputs:

    +
      +
    • num_imported - unsigned int; number of outputs imported.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"import_outputs","params":{"outputs_data_hex":"...outputs..."}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "num_imported": 6400
    +  }
    +}
    +
    +

    incoming_transfers

    +

    Return a list of incoming transfers to the wallet.

    +

    Inputs:

    +
      +
    • transfer_type - string; "all": all the transfers, "available": only transfers which are not yet spent, OR "unavailable": only transfers which are already spent.
    • +
    • account_index - unsigned int; (Optional) Return transfers for this account. (defaults to 0)
    • +
    • subaddr_indices - array of unsigned int; (Optional) Return transfers sent to these subaddresses.
    • +
    • verbose - boolean; (Optional) Enable verbose output, return key image if true.
    • +
    +

    Outputs:

    +
      +
    • transfers - list of:
        +
      • amount - unsigned int; Amount of this transfer.
      • +
      • global_index - unsigned int; Mostly internal use, can be ignored by most users.
      • +
      • key_image - string; Key image for the incoming transfer's unspent output (empty unless verbose is true).
      • +
      • spent - boolean; Indicates if this transfer has been spent.
      • +
      • subaddr_index - unsigned int; Subaddress index for incoming transfer.
      • +
      • tx_hash - string; Several incoming transfers may share the same hash if they were in the same transaction.
      • +
      • tx_size - unsigned int; Size of transaction in bytes.
      • +
      +
    • +
    +

    Example, get all transfers:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"incoming_transfers","params":{"transfer_type":"all","account_index":0,"subaddr_indices":[3],"verbose":true}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "transfers": [{
    +      "amount": 60000000000000,
    +      "global_index": 122405,
    +      "key_image": "768f5144777eb23477ab7acf83562581d690abaf98ca897c03a9d2b900eb479b",
    +      "spent": true,
    +      "subaddr_index": 3,
    +      "tx_hash": "f53401f21c6a43e44d5dd7a90eba5cf580012ad0e15d050059136f8a0da34f6b",
    +      "tx_size": 159
    +    },{
    +      "amount": 27126892247503,
    +      "global_index": 594994,
    +      "key_image": "7e561394806afd1be61980cc3431f6ef3569fa9151cd8d234f8ec13aa145695e",
    +      "spent": false,
    +      "subaddr_index": 3,
    +      "tx_hash": "106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b",
    +      "tx_size": 157
    +    },{
    +      "amount": 27169374733655,
    +      "global_index": 594997,
    +      "key_image": "e76c0a3bfeaae35e4173712f782eb34011198e26b990225b71aa787c8ba8a157",
    +      "spent": false,
    +      "subaddr_index": 3,
    +      "tx_hash": "0bd959b59117ee1254bd8e5aa8e77ec04ef744144a1ffb2d5c1eb9380a719621",
    +      "tx_size": 158
    +    }]
    +  }
    +}
    +
    +

    Example, get available transfers:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"incoming_transfers","params":{"transfer_type":"available","account_index":0,"subaddr_indices":[3],"verbose":true}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "transfers": [{
    +      "amount": 27126892247503,
    +      "global_index": 594994,
    +      "key_image": "7e561394806afd1be61980cc3431f6ef3569fa9151cd8d234f8ec13aa145695e",
    +      "spent": false,
    +      "subaddr_index": 3,
    +      "tx_hash": "106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b",
    +      "tx_size": 157
    +    },{
    +      "amount": 27169374733655,
    +      "global_index": 594997,
    +      "key_image": "e76c0a3bfeaae35e4173712f782eb34011198e26b990225b71aa787c8ba8a157",
    +      "spent": false,
    +      "subaddr_index": 3,
    +      "tx_hash": "0bd959b59117ee1254bd8e5aa8e77ec04ef744144a1ffb2d5c1eb9380a719621",
    +      "tx_size": 158
    +    }]
    +  }
    +}
    +
    +

    Example, get unavailable transfers:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"incoming_transfers","params":{"transfer_type":"unavailable","account_index":0,"subaddr_indices":[3],"verbose":true}}' -H 'Content-Type: application/json'
    +{
    +"id": "0",
    +"jsonrpc": "2.0",
    +"result": {
    +  "transfers": [{
    +    "amount": 60000000000000,
    +    "global_index": 122405,
    +    "key_image": "768f5144777eb23477ab7acf83562581d690abaf98ca897c03a9d2b900eb479b",
    +    "spent": true,
    +    "subaddr_index": 3,
    +    "tx_hash": "f53401f21c6a43e44d5dd7a90eba5cf580012ad0e15d050059136f8a0da34f6b",
    +    "tx_size": 159
    +  }]
    +}
    +}
    +
    +

    is_multisig

    +

    Check if a wallet is a multisig one.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs:

    +
      +
    • multisig - boolean; States if the wallet is multisig
    • +
    • ready - boolean;
    • +
    • threshold - unsigned int; Amount of signature needed to sign a transfer.
    • +
    • total - unsigned int; Total amount of signature in the multisig wallet.
    • +
    +

    Example for a non-multisig wallet:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"is_multisig"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "multisig": false,
    +    "ready": false,
    +    "threshold": 0,
    +    "total": 0
    +  }
    +}
    +
    +

    Example for a multisig wallet:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"is_multisig"}' -H 'Content-Type: application/json'                  {
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "multisig": true,
    +    "ready": true,
    +    "threshold": 2,
    +    "total": 2
    +  }
    +}
    +
    +

    label_account

    +

    Label an account.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • account_index - unsigned int; Apply label to account at this index.
    • +
    • label - string; Label for the account.
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"label_account","params":{"account_index":0,"label":"Primary account"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "account_tags": [{
    +      "accounts": [0,1],
    +      "label": "",
    +      "tag": "myTag"
    +    }]
    +  }
    +}
    +
    +

    label_address

    +

    Label an address.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • index - subaddress index; JSON Object containing the major & minor address index:
        +
      • major - unsigned int; Account index for the subaddress.
      • +
      • minor - unsigned int; Index of the subaddress in the account.
      • +
      +
    • +
    • label - string; Label for the address.
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"label_address","params":{"index":{"major":0,"minor":5},"label":"myLabel"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    make_integrated_address

    +

    Make an integrated address from the wallet address and a payment id.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • standard_address - string; (Optional, defaults to primary address) Destination public address.
    • +
    • payment_id - string; (Optional, defaults to a random ID) 16 characters hex encoded.
    • +
    +

    Outputs:

    +
      +
    • integrated_address - string
    • +
    • payment_id - string; hex encoded;
    • +
    +

    Example (Payment ID is empty, use a random ID):

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"make_integrated_address","params":{"standard_address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "integrated_address": "5F38Rw9HKeaLQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZXCkbHUXdPHyiUeRyokn",
    +    "payment_id": "420fa29b2d9a49f5"
    +  }
    +}
    +
    +

    make_multisig

    +

    Make a wallet multisig by importing peers multisig string.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • multisig_info - array of string; List of multisig string from peers.
    • +
    • threshold - unsigned int; Amount of signatures needed to sign a transfer. Must be less or equal than the amount of signature in multisig_info.
    • +
    • password - string; Wallet password
    • +
    +

    Outputs:

    +
      +
    • address - string; multisig wallet address.
    • +
    • multisig_info - string; Multisig string to share with peers to create the multisig wallet (extra step for N-1/N wallets).
    • +
    +

    Example for 2/2 Multisig Wallet:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"make_multisig","params":{"multisig_info":["MultisigV1K4tGGe8QirZdHgTYoBZMumSug97fdDyM3Z63M3ZY5VXvAdoZvx16HJzPCP4Rp2ABMKUqLD2a74ugMdBfrVpKt4BwD8qCL5aZLrsYWoHiA7JJwDESuhsC3eF8QC9UMvxLXEMsMVh16o98GnKRYz1HCKXrAEWfcrCHyz3bLW1Pdggyowop"],"threshold":2}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "address": "55SoZTKH7D39drxfgT62k8T4adVFjmDLUXnbzEKYf1MoYwnmTNKKaqGfxm4sqeKCHXQ5up7PVxrkoeRzXu83d8xYURouMod",
    +    "multisig_info": ""
    +  }
    +}
    +
    +

    Example for 2/3 Multisig Wallet:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"make_multisig","params":{"multisig_info":["MultisigV1MTVm4DZAdJw1PyVutpSy8Q4WisZBCFRAaZY7hhQnMwr5AZ4swzThyaSiVVQM5FHj1JQi3zPKhQ4k81BZkPSEaFjwRJtbfqfJcVvCqRnmBVcWVxhnihX5s8fZWBCjKrzT3CS95spG4dzNzJSUcjheAkLzCpVmSzGtgwMhAS3Vuz9Pas24","MultisigV1TEx58ycKCd6ADCfxF8hALpcdSRAkhZTi1bu4Rs6FdRC98EdB1LY7TAkMxasM55khFgcxrSXivaSr5FCMyJGHmojm1eE4HpGWPeZKv6cgCTThRzC4u6bkkSoFQdbzWN92yn1XEjuP2XQrGHk81mG2LMeyB51MWKJAVF99Pg9mX2BpmYFj"],"threshold":2}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "address": "51sLpF8fWaK1111111111111111111111111111111111ABVbHNf1JFWJyFp5YZgZRQ44RiviJi1sPHgLVMbckRsDkTRgKS",
    +    "multisig_info": "MultisigxV18jCaYAQQvzCMUJaAWMCaAbAoHpAD6WPmYDmLtBtazD654E8RWkLaGRf29fJ3stU471MELKxwufNYeigP7LoE4tn2Sscwn5g7PyCfcBc1V4ffRHY3Kxqq6VocSCUTncpVeUskaDKuTAWtdB9VTBGW7iG1cd7Zm1dYgur3CiemkGjRUAj9bL3xTEuyaKGYSDhtpFZFp99HQX57EawhiRHk3qq4hjWX"
    +  }
    +}
    +
    +

    make_uri

    +

    Create a payment URI using the official URI spec.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • address - string; Wallet address
    • +
    • amount - unsigned int; (optional) the integer amount to receive, in atomicunits
    • +
    • payment_id - string; (optional) 16 or 64 character hexadecimal payment id
    • +
    • recipient_name - string; (optional) name of the payment recipient
    • +
    • tx_description - string; (optional) Description of the reason for the tx
    • +
    +

    Outputs:

    +
      +
    • uri - string; This contains all the payment input information as a properly formatted payment URI
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"make_uri","params":{"address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","amount":10,"payment_id":"420fa29b2d9a49f5","tx_description":"Testing out the make_uri function.","recipient_name":"el00ruobuob Stagenet wallet"}}'  -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "uri": "monero:55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt?tx_payment_id=420fa29b2d9a49f5&tx_amount=0.000000000010&recipient_name=el00ruobuob%20Stagenet%20wallet&tx_description=Testing%20out%20the%20make_uri%20function."
    +  }
    +}
    +
    +

    open_wallet

    +

    Open a wallet. You need to have set the argument "–wallet-dir" when launching monero-wallet-rpc to make this work.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • filename - string; wallet name stored in –wallet-dir.
    • +
    • password - string; (Optional) only needed if the wallet has a password defined.
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"open_wallet","params":{"filename":"mytestwallet","password":"mytestpassword"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    parse_uri

    +

    Parse a payment URI to get payment information.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • uri - string; This contains all the payment input information as a properly formatted payment URI
    • +
    +

    Outputs:

    +
      +
    • uri - JSON object containing payment information:
        +
      • address - string; Wallet address
      • +
      • amount - unsigned int; Decimal amount to receive, in coin units (0 if not provided)
      • +
      • payment_id - string; 16 or 64 character hexadecimal payment id (empty if not provided)
      • +
      • recipient_name - string; Name of the payment recipient (empty if not provided)
      • +
      • tx_description - string; Description of the reason for the tx (empty if not provided)
      • +
      +
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"parse_uri","params":{"uri":"monero:55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt?tx_payment_id=420fa29b2d9a49f5&tx_amount=0.000000000010&recipient_name=el00ruobuob%20Stagenet%20wallet&tx_description=Testing%20out%20the%20make_uri%20function."}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "uri": {
    +      "address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt",
    +      "amount": 10,
    +      "payment_id": "420fa29b2d9a49f5",
    +      "recipient_name": "el00ruobuob Stagenet wallet",
    +      "tx_description": "Testing out the make_uri function."
    +    }
    +  }
    +}
    +
    +

    prepare_multisig

    +

    Prepare a wallet for multisig by generating a multisig string to share with peers.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs:

    +
      +
    • multisig_info - string; Multisig string to share with peers to create the multisig wallet.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"prepare_multisig"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "multisig_info": "MultisigV1BFdxQ653cQHB8wsj9WJQd2VdnjxK89g5M94dKPBNw22reJnyJYKrz6rJeXdjFwJ3Mz6n4qNQLd6eqUZKLiNzJFi3UPNVcTjtkG2aeSys9sYkvYYKMZ7chCxvoEXVgm74KKUcUu4V8xveCBFadFuZs8shnxBWHbcwFr5AziLr2mE7KHJT"
    +  }
    +}
    +
    +

    query_key

    +

    Return the spend or view private key.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • key_type - string; Which key to retrieve: "mnemonic" - the mnemonic seed (older wallets do not have one) OR "view_key" - the view key
    • +
    +

    Outputs:

    +
      +
    • key - string; The view key will be hex encoded, while the mnemonic will be a string of words.
    • +
    +

    Example (Query view key):

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"query_key","params":{"key_type":"view_key"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "key": "0a1a38f6d246e894600a3e27238a064bf5e8d91801df47a17107596b1378e501"
    +  }
    +}
    +
    +

    Example (Query mnemonic key):

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"query_key","params":{"key_type":"mnemonic"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "key": "vocal either anvil films dolphin zeal bacon cuisine quote syndrome rejoices envy okay pancakes tulips lair greater petals organs enmity dedicated oust thwart tomorrow tomorrow"
    +  }
    +}
    +
    +

    refresh

    +

    Refresh a wallet after openning.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • start_height - unsigned int; (Optional) The block height from which to start refreshing.
    • +
    +

    Outputs:

    +
      +
    • blocks_fetched - unsigned int; Number of new blocks scanned.
    • +
    • received_money - boolean; States if transactions to the wallet have been found in the blocks.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"refresh","params":{"start_height":100000}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "blocks_fetched": 24,
    +    "received_money": true
    +  }
    +}
    +
    +

    relay_tx

    +

    Relay a transaction previously created with "do_not_relay":true.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • hex - string; transaction metadata returned from a transfer method with get_tx_metadata set to true.
    • +
    +

    Outputs:

    +
      +
    • tx_hash - String for the publically searchable transaction hash.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"relay_tx","params":{"hex":"...tx_metadata..."}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "tx_hash": "1c42dcc5672bb09bccf33fb1e9ab4a498af59a6dbd33b3d0cfb289b9e0e25fa5"
    +  }
    +}
    +
    +

    rescan_blockchain

    +

    Rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself.
    +This includes destination addresses, tx secret keys, tx notes, etc.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"rescan_blockchain"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    rescan_spent

    +

    Rescan the blockchain for spent outputs.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"rescan_spent"}' -H 'Content-Type: application/json'
    +
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    set_account_tag_description

    +

    Set description for an account tag.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • tag - string; Set a description for this tag.
    • +
    • description - string; Description for the tag.
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"set_account_tag_description","params":{"tag":"myTag","description":"Test tag"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    set_attribute

    +

    Set arbitrary attribute.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • key - string; attribute name
    • +
    • value - string; attribute value
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"set_attribute","params":{"key":"my_attribute","value":"my_value"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    set_tx_notes

    +

    Set arbitrary string notes for transactions.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • txids - array of string; transaction ids
    • +
    • notes - array of string; notes for the transactions
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"set_tx_notes","params":{"txids":["3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f"],"notes":["This is an example"]}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    sign

    +

    Sign a string.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • data - string; Anything you need to sign.
    • +
    +

    Outputs:

    +
      +
    • signature - string; Signature generated against the "data" and the account public address.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sign","params":{"data":"This is sample data to be signed"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "signature": "SigV14K6G151gycjiGxjQ74tKX6A2LwwghvuHjcDeuRFQio5LS6Gb27BNxjYQY1dPuUvXkEbGQUkiHSVLPj4nJAHRrrw3"
    +  }
    +}
    +
    +

    sign_multisig

    +

    Sign a transaction in multisig.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • tx_data_hex - string; Multisig transaction in hex format, as returned by transfer under multisig_txset.
    • +
    +

    Outputs:

    +
      +
    • tx_data_hex - string; Multisig transaction in hex format.
    • +
    • tx_hash_list - array of string; List of transaction Hash.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sign_multisig","params":{"tx_data_hex":"...multisig_txset..."}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "tx_data_hex": "...multisig_txset...",
    +    "tx_hash_list": ["4996091b61c1be112c1097fd5e97d8ff8b28f0e5e62e1137a8c831bacf034f2d"]
    +  }
    +}
    +
    +

    sign_transfer

    +

    Sign a transaction created on a read-only wallet (in cold-signing process)

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • unsigned_txset - string. Set of unsigned tx returned by "transfer" or "transfer_split" methods.
    • +
    • export_raw - boolean; (Optional) If true, return the raw transaction data. (Defaults to false)
    • +
    +

    Outputs:

    +
      +
    • signed_txset - string. Set of signed tx to be used for submitting transfer.
    • +
    • tx_hash_list - array of: string. The tx hashes of every transaction.
    • +
    • tx_raw_list - array of: string. The tx raw data of every transaction.
    • +
    +

    In the example below, we first generate an unsigned_txset on a read only wallet before signing it:

    +

    Generate unsigned_txset using the above "transfer" method on read-only wallet:

    +
    curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"destinations":[{"amount":1000000000000,"address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"}],"account_index":0,"subaddr_indices":[0],"priority":0,"ring_size":7,"do_not_relay":true,"get_tx_hex":true}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "amount": 1000000000000,
    +    "fee": 15202740000,
    +    "multisig_txset": "",
    +    "tx_blob": "...long_hex...",
    +    "tx_hash": "c648ba0a049e5ce4ec21361dbf6e4b21eac0f828eea9090215de86c76b31d0a4",
    +    "tx_key": "",
    +    "tx_metadata": "",
    +    "unsigned_txset": "...long_hex..."
    +  }
    +}
    +
    +

    Sign tx using the previously generated unsigned_txset

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sign_transfer","params":{"unsigned_txset":...long_hex..."}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "signed_txset": "...long_hex...",
    +    "tx_hash_list": ["ff2e2d49fbfb1c9a55754f786576e171c8bf21b463a74438df604b7fa6cebc6d"]
    +  }
    +}
    +
    +

    split_integrated_address

    +

    Retrieve the standard address and payment id corresponding to an integrated address.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • integrated_address - string
    • +
    +

    Outputs:

    +
      +
    • is_subaddress - boolean; States if the address is a subaddress
    • +
    • payment - string; hex encoded
    • +
    • standard_address - string
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"split_integrated_address","params":{"integrated_address": "5F38Rw9HKeaLQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZXCkbHUXdPHyiUeRyokn"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "is_subaddress": false,
    +    "payment_id": "420fa29b2d9a49f5",
    +    "standard_address": "55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt"
    +  }
    +}
    +
    +

    start_mining

    +

    Start mining in the Monero daemon.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • threads_count - unsigned int; Number of threads created for mining.
    • +
    • do_background_mining - boolean; Allow to start the miner in smart miningmode.
    • +
    • ignore_battery - boolean; Ignore battery status (for smart mining only)
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"start_mining","params":{"threads_count":1,"do_background_mining":true,"ignore_battery":false}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    stop_mining

    +

    Stop mining in the Monero daemon.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"stop_mining"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    stop_wallet

    +

    Stops the wallet, storing the current state.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"stop_wallet"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    store

    +

    Save the wallet file.

    +

    Alias: None.

    +

    Inputs: None.

    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"store"}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    submit_multisig

    +

    Submit a signed multisig transaction.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • tx_data_hex - string; Multisig transaction in hex format, as returned by sign_multisig under tx_data_hex.
    • +
    +

    Outputs:

    +
      +
    • tx_hash_list - array of string; List of transaction Hash.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"submit_multisig","params":{"tx_data_hex":"...tx_data_hex..."}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "tx_hash_list": ["4996091b61c1be112c1097fd5e97d8ff8b28f0e5e62e1137a8c831bacf034f2d"]
    +  }
    +}
    +
    +

    submit_transfer

    +

    Submit a previously signed transaction on a read-only wallet (in cold-signing process).

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • tx_data_hex - string; Set of signed tx returned by "sign_transfer"
    • +
    +

    Outputs:

    +
      +
    • tx_hash_list - array of: string. The tx hashes of every transaction.
    • +
    +

    In the example below, we submit the transfer using the signed_txset generated above:

    +
    curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"submit_transfer","params":{"tx_data_hex":...long_hex..."}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "tx_hash_list": ["40fad7c828bb383ac02648732f7afce9adc520ba5629e1f5d9c03f584ac53d74"]
    +  }
    +}
    +
    +

    sweep_all

    +

    Send all unlocked balance to an address.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • address - string; Destination public address.
    • +
    • account_index - unsigned int; Sweep transactions from this account.
    • +
    • subaddr_indices - array of unsigned int; (Optional) Sweep from this set of subaddresses in the account.
    • +
    • priority - unsigned int; (Optional) Priority for sending the sweep transfer, partially determines fee.
    • +
    • mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing).
    • +
    • ring_size - unsigned int; Sets ringsize to n (mixin + 1).
    • +
    • unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock).
    • +
    • payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction.
    • +
    • get_tx_keys - boolean; (Optional) Return the transaction keys after sending.
    • +
    • below_amount - unsigned int; (Optional) Include outputs below this amount.
    • +
    • do_not_relay - boolean; (Optional) If true, do not relay this sweep transfer. (Defaults to false)
    • +
    • get_tx_hex - boolean; (Optional) return the transactions as hex encoded string. (Defaults to false)
    • +
    • get_tx_metadata - boolean; (Optional) return the transaction metadata as a string. (Defaults to false)
    • +
    +

    Outputs:

    +
      +
    • tx_hash_list - array of: string. The tx hashes of every transaction.
    • +
    • tx_key_list - array of: string. The transaction keys for every transaction.
    • +
    • amount_list - array of: integer. The amount transferred for every transaction.
    • +
    • fee_list - array of: integer. The amount of fees paid for every transaction.
    • +
    • tx_blob_list - array of: string. The tx as hex string for every transaction.
    • +
    • tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later.
    • +
    • multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig).
    • +
    • unsigned_txset - string. Set of unsigned tx for cold-signing purposes.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sweep_all","params":{"address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","subaddr_indices":[4],"ring_size":7,"unlock_time":0,"get_tx_keys":true}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "amount_list": [9985885770000],
    +    "fee_list": [14114230000],
    +    "multisig_txset": "",
    +    "tx_hash_list": ["ab4b6b65cc8cd8c9dd317d0b90d97582d68d0aa1637b0065b05b61f9a66ea5c5"],
    +    "tx_key_list": ["b9b4b39d3bb3062ddb85ec0266d4df39058f4c86077d99309f218ce4d76af607"],
    +    "unsigned_txset": ""
    +  }
    +}
    +
    +

    sweep_dust

    +

    Send all dust outputs back to the wallet's, to make them easier to spend (and mix).

    +

    Alias: sweep_unmixable.

    +

    Inputs:

    +
      +
    • get_tx_keys - boolean; (Optional) Return the transaction keys after sending.
    • +
    • do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the monero network. (Defaults to false)
    • +
    • get_tx_hex - boolean; (Optional) Return the transactions as hex string after sending. (Defaults to false)
    • +
    • get_tx_metadata - boolean; (Optional) Return list of transaction metadata needed to relay the transfer later. (Defaults to false)
    • +
    +

    Outputs:

    +
      +
    • tx_hash_list - array of: string. The tx hashes of every transaction.
    • +
    • tx_key_list - array of: string. The transaction keys for every transaction.
    • +
    • amount_list - array of: integer. The amount transferred for every transaction.
    • +
    • fee_list - array of: integer. The amount of fees paid for every transaction.
    • +
    • tx_blob_list - array of: string. The tx as hex string for every transaction.
    • +
    • tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later.
    • +
    • multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig).
    • +
    • unsigned_txset - string. Set of unsigned tx for cold-signing purposes.
    • +
    +

    Example (In this example, sweep_dust returns nothing because there are no funds to sweep):

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sweep_dust","params":{"get_tx_keys":true}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "multisig_txset": "",
    +    "unsigned_txset": ""
    +  }
    +}
    +
    +

    sweep_single

    +

    Send all of a specific unlocked output to an address.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • address - string; Destination public address.
    • +
    • account_index - unsigned int; Sweep transactions from this account.
    • +
    • subaddr_indices - array of unsigned int; (Optional) Sweep from this set of subaddresses in the account.
    • +
    • priority - unsigned int; (Optional) Priority for sending the sweep transfer, partially determines fee.
    • +
    • mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing).
    • +
    • ring_size - unsigned int; Sets ringsize to n (mixin + 1).
    • +
    • unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock).
    • +
    • payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction.
    • +
    • get_tx_keys - boolean; (Optional) Return the transaction keys after sending.
    • +
    • key_image - string; Key image of specific output to sweep.
    • +
    • below_amount - unsigned int; (Optional) Include outputs below this amount.
    • +
    • do_not_relay - boolean; (Optional) If true, do not relay this sweep transfer. (Defaults to false)
    • +
    • get_tx_hex - boolean; (Optional) return the transactions as hex encoded string. (Defaults to false)
    • +
    • get_tx_metadata - boolean; (Optional) return the transaction metadata as a string. (Defaults to false)
    • +
    +

    Outputs:

    +
      +
    • tx_hash_list - array of: string. The tx hashes of every transaction.
    • +
    • tx_key_list - array of: string. The transaction keys for every transaction.
    • +
    • amount_list - array of: integer. The amount transferred for every transaction.
    • +
    • fee_list - array of: integer. The amount of fees paid for every transaction.
    • +
    • tx_blob_list - array of: string. The tx as hex string for every transaction.
    • +
    • tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later.
    • +
    • multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig).
    • +
    • unsigned_txset - string. Set of unsigned tx for cold-signing purposes.
    • +
    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"sweep_single","params":{"address":"74Jsocx8xbpTBEjm3ncKE5LBQbiJouyCDaGhgSiebpvNDXZnTAbW2CmUR5SsBeae2pNk9WMVuz6jegkC4krUyqRjA6VjoLD","ring_size":7,"unlock_time":0,"key_image":"a7834459ef795d2efb6f665d2fd758c8d9288989d8d4c712a68f8023f7804a5e","get_tx_keys":true}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "amount": 27126892247503,
    +    "fee": 14111630000,
    +    "multisig_txset": "",
    +    "tx_blob": "",
    +    "tx_hash": "106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b",
    +    "tx_key": "",
    +    "tx_metadata": "",
    +    "unsigned_txset": ""
    +  }
    +}
    +
    +

    tag_accounts

    +

    Apply a filtering tag to a list of accounts.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • tag - string; Tag for the accounts.
    • +
    • accounts - array of unsigned int; Tag this list of accounts.
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"tag_accounts","params":{"tag":"myTag","accounts":[0,1]}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    transfer

    +

    Send monero to a number of recipients.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • destinations - array of destinations to receive XMR:
        +
      • amount - unsigned int; Amount to send to each destination, in atomic units.
      • +
      • address - string; Destination public address.
      • +
      +
    • +
    • account_index - unsigned int; (Optional) Transfer from this account index. (Defaults to 0)
    • +
    • subaddr_indices - array of unsigned int; (Optional) Transfer from this set of subaddresses. (Defaults to 0)
    • +
    • priority - unsigned int; Set a priority for the transaction. Accepted Values are: 0-3 for: default, unimportant, normal, elevated, priority.
    • +
    • mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing).
    • +
    • ring_size - unsigned int; Number of outputs to mix in the transaction (this output + N decoys from the blockchain).
    • +
    • unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock).
    • +
    • payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction.
    • +
    • get_tx_key - boolean; (Optional) Return the transaction key after sending.
    • +
    • do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the monero network. (Defaults to false)
    • +
    • get_tx_hex - boolean; Return the transaction as hex string after sending (Defaults to false)
    • +
    • get_tx_metadata - boolean; Return the metadata needed to relay the transaction. (Defaults to false)
    • +
    +

    Outputs:

    +
      +
    • amount - Amount transferred for the transaction.
    • +
    • fee - Integer value of the fee charged for the txn.
    • +
    • multisig_txset - Set of multisig transactions in the process of being signed (empty for non-multisig).
    • +
    • tx_blob - Raw transaction represented as hex string, if get_tx_hex is true.
    • +
    • tx_hash - String for the publically searchable transaction hash.
    • +
    • tx_key - String for the transaction key if get_tx_key is true, otherwise, blank string.
    • +
    • tx_metadata - Set of transaction metadata needed to relay this transfer later, if get_tx_metadata is true.
    • +
    • unsigned_txset - String. Set of unsigned tx for cold-signing purposes.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"destinations":[{"amount":100000000000,"address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"},{"amount":200000000000,"address":"75sNpRwUtekcJGejMuLSGA71QFuK1qcCVLZnYRTfQLgFU5nJ7xiAHtR5ihioS53KMe8pBhH61moraZHyLoG4G7fMER8xkNv"}],"account_index":0,"subaddr_indices":[0],"priority":0,"ring_size":7,"get_tx_key": true}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "amount": 300000000000,
    +    "fee": 86897600000,
    +    "multisig_txset": "",
    +    "tx_blob": "",
    +    "tx_hash": "7663438de4f72b25a0e395b770ea9ecf7108cd2f0c4b75be0b14a103d3362be9",
    +    "tx_key": "25c9d8ec20045c80c93d665c9d3684aab7335f8b2cd02e1ba2638485afd1c70e236c4bdd7a2f1cb511dbf466f13421bdf8df988b7b969c448ca6239d7251490e4bf1bbf9f6ffacffdcdc93b9d1648ec499eada4d6b4e02ce92d4a1c0452e5d009fbbbf15b549df8856205a4c7bda6338d82c823f911acd00cb75850b198c5803",
    +    "tx_metadata": "",
    +    "unsigned_txset": ""
    +  }
    +}
    +
    +

    transfer_split

    +

    Same as transfer, but can split into more than one tx if necessary.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • destinations - array of destinations to receive XMR:
        +
      • amount - unsigned int; Amount to send to each destination, in atomic units.
      • +
      • address - string; Destination public address.
      • +
      +
    • +
    • account_index - unsigned int; (Optional) Transfer from this account index. (Defaults to 0)
    • +
    • subaddr_indices - array of unsigned int; (Optional) Transfer from this set of subaddresses. (Defaults to 0)
    • +
    • mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing).
    • +
    • ring_size - unsigned int; Sets ringsize to n (mixin + 1).
    • +
    • unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock).
    • +
    • payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction.
    • +
    • get_tx_keys - boolean; (Optional) Return the transaction keys after sending.
    • +
    • priority - unsigned int; Set a priority for the transactions. Accepted Values are: 0-3 for: default, unimportant, normal, elevated, priority.
    • +
    • do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the monero network. (Defaults to false)
    • +
    • get_tx_hex - boolean; Return the transactions as hex string after sending
    • +
    • new_algorithm - boolean; True to use the new transaction construction algorithm, defaults to false.
    • +
    • get_tx_metadata - boolean; Return list of transaction metadata needed to relay the transfer later.
    • +
    +

    Outputs:

    +
      +
    • tx_hash_list - array of: string. The tx hashes of every transaction.
    • +
    • tx_key_list - array of: string. The transaction keys for every transaction.
    • +
    • amount_list - array of: integer. The amount transferred for every transaction.
    • +
    • fee_list - array of: integer. The amount of fees paid for every transaction.
    • +
    • tx_blob_list - array of: string. The tx as hex string for every transaction.
    • +
    • tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later.
    • +
    • multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig).
    • +
    • unsigned_txset - string. Set of unsigned tx for cold-signing purposes.
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer_split","params":{"destinations":[{"amount":1000000000000,"address":"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o"},{"amount":2000000000000,"address":"75sNpRwUtekcJGejMuLSGA71QFuK1qcCVLZnYRTfQLgFU5nJ7xiAHtR5ihioS53KMe8pBhH61moraZHyLoG4G7fMER8xkNv"}],"account_index":0,"subaddr_indices":[0],"priority":0,"ring_size":7,"get_tx_key": true}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "amount_list": [3000000000000],
    +    "fee_list": [85106400000],
    +    "multisig_txset": "",
    +    "tx_hash_list": ["c8d815f48f27d53fdaf198a74b292a91bfaf87529a9a9a9ee66079a890b3b58b"],
    +    "unsigned_txset": ""
    +  }
    +}
    +
    +

    untag_accounts

    +

    Remove filtering tag from a list of accounts.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • accounts - array of unsigned int; Remove tag from this list of accounts.
    • +
    +

    Outputs: None.

    +

    Example:

    +
    $ curl -X POST http://localhost:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"untag_accounts","params":{"accounts":[1]}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +  }
    +}
    +
    +

    verify

    +

    Verify a signature on a string.

    +

    Alias: None.

    +

    Inputs:

    +
      +
    • data - string; What should have been signed.
    • +
    • address - string; Public address of the wallet used to sign the data.
    • +
    • signature - string; signature generated by sign method.
    • +
    +

    Outputs:

    +
      +
    • good - boolean;
    • +
    +

    Example:

    +
    $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"verify","params":{"data":"This is sample data to be signed","address":"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt","signature":"SigV14K6G151gycjiGxjQ74tKX6A2LwwghvuHjcDeuRFQio5LS6Gb27BNxjYQY1dPuUvXkEbGQUkiHSVLPj4nJAHRrrw3"}}' -H 'Content-Type: application/json'
    +{
    +  "id": "0",
    +  "jsonrpc": "2.0",
    +  "result": {
    +    "good": true
    +  }
    +}
    +
    +

    Sources:

    +

    Reworked from GetMonero.org

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/monerod-reference/index.html b/public/interacting/monerod-reference/index.html new file mode 100644 index 0000000..b8889f2 --- /dev/null +++ b/public/interacting/monerod-reference/index.html @@ -0,0 +1,2309 @@ + + + + + + + + + + + + + + + + + + + + + + + monerod - Reference - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    monerod - Reference

    +

    Overview

    +

    Connects you to Monero network

    +

    The Monero daemon monerod keeps your computer synced up with the Monero network.

    +

    It downloads and validates the blockchain from the p2p network.

    +

    Not aware of your private keys

    +

    monerod is entirely decoupled from your wallet.

    +

    monerod does not access your private keys - it is not aware of your transactions and balance.

    +

    This allows you to run monerod on a separate computer or in the cloud.

    +

    In fact, you can connect to a remote monerod instance provided by a semi-trusted 3rd party. Such 3rd party will not be able to steal your funds. This is very handy for learning and experimentation.

    +

    However, there are privacy and reliability implications to using a remote, untrusted node. For any real business you should be running your own full node.

    +

    Syntax

    +

    ./monerod [options] [command]

    +

    Options define how the daemon should be working. Their names follow the --option-name pattern.

    +

    Commands give access to specific services provided by the daemon. Commands are executed against the running daemon. +Their names follow the command_name pattern.

    +

    Running

    +

    Go to directory where you unpacked Monero.

    +

    The stagenet is what your should be using for learning and experimentation.

    +
    ./monerod --stagenet --detach                # run as a daemon in background
    +tail -f ~/.bitmonero/stagenet/bitmonero.log  # watch the logs
    +./monerod --stagenet exit                    # ask daemon to exit gracefully
    +
    +

    The mainnnet is when you want to deal with the real XMR.

    +
    ./monerod --detach                           # run as a daemon in background
    +tail -f ~/.bitmonero/bitmonero.log           # watch the logs
    +./monerod exit                               # ask daemon to exit gracefully
    +
    +

    Options

    +

    Options define how the daemon should be working. Their names follow the --option-name pattern.

    +

    The following groups are only to make reference easier to follow. The daemon itself does not group options in any way.

    +

    Help and version

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --helpEnlist available options.
    --versionShow monerod version to stdout. Example output:
    Monero 'Oxygen Orion' (v0.17.1.8-release)
    --os-versionShow build timestamp and target operating system. Example output:
    OS: Linux #65-Ubuntu SMP Thu Dec 10 12:01:51 UTC 2020 5.4.0-59-generic.
    --check-updatesOne of: disabled | notify | download (=notify by default). Check for new versions of Monero and optionally download it. You should probably prefer your OS package manager to do the update, if possible. There is also unimplemented update option shown by the help system.
    +

    Pick network

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    (missing)By default monerod assumes mainnet.
    --stagenetRun on stagenet. Remember to run your wallet with --stagenet as well.
    --testnetRun on testnet. Remember to run your wallet with --testnet as well.
    +

    Logging

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --log-fileFull path to the log file. Example (mind file permissions):
    ./monerod --log-file=/var/log/monero/mainnet/monerod.log
    --log-level0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0. These are general presets and do not directly map to severity levels. For example, even with minimal 0, you may see some most important INFO entries. Temporarily changing to 1 allows for much better understanding of how the full node operates. Example:
    ./monerod --log-level=1
    --max-log-file-sizeSoft limit in bytes for the log file (=104850000 by default, which is just under 100MB). Once log file grows past that limit, monerod creates the next log file with a UTC timestamp postfix -YYYY-MM-DD-HH-MM-SS.

    In production deployments, you would probably prefer to use established solutions like logrotate instead. In that case, set --max-log-file-size=0 to prevent monerod from managing the log files.
    --max-log-filesLimit on the number of log files (=50 by default). The oldest log files are removed. In production deployments, you would probably prefer to use established solutions like logrotate instead.
    +

    Server

    +

    monerod defaults are adjusted for running it occasionally on the same computer as your Monero wallet.

    +

    The following options will be helpful if you intend to have an always running node — most likely on a remote server or your own separate PC.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --config-fileFull path to the configuration file. By default monerod looks for bitmonero.conf in Monero data directory.
    --data-dirFull path to data directory. This is where the blockchain, log files, and p2p network memory are stored. For defaults and details see data directory.
    --pidfileFull path to the PID file. Works only with --detach. Example:
    ./monerod --detach --pidfile=/run/monero/monerod.pid
    --detachGo to background (decouple from the terminal). This is useful for long-running / server scenarios. Typically, you will also want to manage monerod daemon with systemd or similar. By default monerod runs in a foreground.
    --non-interactiveDo not require tty in a foreground mode. Helpful when running in a container. By default monerod runs in a foreground and opens stdin for reading. This breaks containerization because no tty gets assigned and monerod process crashes. You can make it run in a background with --detach but this is inconvenient in a containerized environment because the canonical usage is that the container waits on the main process to exist (forking makes things more complicated).
    --no-zmqDisable ZMQ RPC server. You should use this option to limit attack surface and number of unnecessarily open ports (the ZMQ server is unfinished thing and you are unlikely to ever use it).
    --no-igdDisable UPnP port mapping on the router ("Internet Gateway Device"). Add this option to improve security if you are not behind a NAT (you can bind directly to public IP or you run through Tor).
    --max-txpool-weightSet maximum transactions pool size in bytes. By default 648000000 (~618MB). These are transactions pending for confirmations (not included in any block).
    --enforce-dns-checkpointingThe emergency checkpoints set by MoneroPulse operators will be enforced. It is probably a good idea to set enforcing for unattended nodes.

    If encountered block hash does not match corresponding checkpoint, the local blockchain will be rolled back a few blocks, effectively blocking following what MoneroPulse operators consider invalid fork. The log entry will be produced: ERROR Local blockchain failed to pass a checkpoint, rolling back! Eventually, the alternative ("fixed") fork will get heavier and the node will follow it, leaving the "invalid" fork behind.

    By default checkpointing only notifies about discrepancy by producing the following log entry: ERROR WARNING: local blockchain failed to pass a MoneroPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option.

    Reference: source code.
    --disable-dns-checkpointsThe MoneroPulse checkpoints set by core developers will be discarded. The checkpoints are apparently still fetched though.
    +

    P2P network

    +

    The following options define how your node participates in Monero peer-to-peer network. +This is for node-to-node communication. The following options do not affect wallet-to-node interface.

    +

    The node and peer words are used interchangeably.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --p2p-bind-ipIPv4 network interface to bind to for p2p network protocol. Default value 0.0.0.0 binds to all network interfaces. This is typically what you want.

    You must change this if you want to constrain binding, for example to force working through Tor via torsocks:
    DNS_PUBLIC=tcp://1.1.1.1 TORSOCKS_ALLOW_INBOUND=1 torsocks ./monerod --p2p-bind-ip 127.0.0.1  --no-igd  --hide-my-port
    --p2p-bind-portTCP port to listen for p2p network connections. Defaults to 18080 for mainnet, 28080 for testnet, and 38080 for stagenet. You normally wouldn't change that. This is helpful to run several nodes on your machine to simulate private Monero p2p network (likely using private Testnet). Example:
    ./monerod --p2p-bind-port=48080
    --p2p-external-portTCP port to listen for p2p network connections on your router. Relevant if you are behind a NAT and still want to accept incoming connections. You must then set this to relevant port on your router. This is to let monerod know what to advertise on the network. Default is 0.
    --p2p-use-ipv6Enable IPv6 for p2p (disabled by default).
    --p2p-bind-ipv6-addressIPv6 network interface to bind to for p2p network protocol. Default value :: binds to all network interfaces.
    --p2p-ignore-ipv4Ignore unsuccessful IPv4 bind for p2p. Useful if you only want to use IPv6.
    --igdSet UPnP port mapping on the router ("Internet Gateway Device"). One of: disabled | enabled | delayed (=delayed by default). Relevant if you are behind NAT and want to accept incoming P2P network connections. The delayed value means it will wait for incoming connections in hope UPnP may not be necessary. After a while w/o incoming connections found it will attempt to map ports with UPnP. If you know you need UPnP change it to enabled to fast track the process.
    --hide-my-portmonerod will still open and listen on the p2p port. However, it will not announce itself as a peer list candidate. Technically, it will return port 0 in a response to p2p handshake (node_data.my_port = 0 in get_local_node_data function). In effect nodes you connect to won't spread your IP to other nodes. To sum up, it is not really hiding, it is more like "do not advertise".
    --seed-nodeConnect to a node to retrieve other nodes' addresses, and disconnect. If not specified, monerod will use hardcoded seed nodes on the first run, and peers cached on disk on subsequent runs.
    --add-peerManually add node to local peer list, host:port. Syntax supports IP addresses, domain names, onion and i2p hosts.
    --add-priority-nodeSpecify list of nodes to connect to and then attempt to keep the connection open.

    To add multiple nodes use the option several times. Example:
    ./monerod --add-priority-node=178.128.192.138:18081 --add-priority-node=144.76.202.167:18081
    --add-exclusive-nodeSpecify list of nodes to connect to only. If this option is given the options --add-priority-node and --seed-node are ignored.

    To add multiple nodes use the option several times. Example:
    ./monerod --add-exclusive-node=178.128.192.138:18081 --add-exclusive-node=144.76.202.167:18081
    --out-peersSet max number of outgoing connections to other nodes. By default 12. Value -1 represents the code default.
    --in-peersSet max number of incoming connections (nodes actively connecting to you). By default unlimited. Value -1 represents the code default.
    --limit-rate-upSet outgoing data transfer limit [kB/s]. By default 2048 kB/s. Value -1 represents the code default.
    --limit-rate-downSet incoming data transfer limit [kB/s]. By default 8192 kB/s. Value -1 represents the code default.
    --limit-rateSet the same limit value for incoming and outgoing data transfer. By default (-1) the individual up/down default limits will be used. It is better to use --limit-rate-up and --limit-rate-down instead to avoid confusion.
    --offlineDo not listen for peers, nor connect to any. Useful for working with a local, archival blockchain.
    --allow-local-ipAllow adding local IP to peer list. Useful mostly for debug purposes when you may want to have multiple nodes on a single machine.
    +

    Tor/I2P

    +

    This is experimental. It may be best to start with this guide.

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --tx-proxySend out your local transactions through SOCKS5 proxy (Tor or I2P). Format:
    <network-type>,<socks-ip:port>[,max_connections][,disable_noise]

    Example:
    ./monerod --tx-proxy "tx-proxy=tor,127.0.0.1:9050,16"

    This was introduced to make publishing transactions over Tor easier (no need for torsocks) while allowing clearnet for blocks at the same time (while torsocks affected everything).

    Adding ,disable_noise disables Dandelion++ (will speed up tx broadcast but is otherwise not recommended).

    Note that forwarded transactions (those not originating from connected wallet) will still be relayed over clearnet.

    Requires multiple --add-peer to manually add onion-enabled p2p seed nodes - see Tor onion seed nodes for Monero P2P network. See this guide and commit.
    --anonymous-inboundAllow anonymous incoming connections to your onionized P2P interface. Format:
    <hidden-service-address>,<[bind-ip:]port>[,max_connections]

    Example:
    ./monerod --anonymous-inbound "rveahdfho7wo4b2m.onion:18083,127.0.0.1:18083,100".

    Obviously, you first need to setup the hidden service in your Tor config. See the guide.
    --pad-transactionsPad relayed transactions to next 1024 bytes to help defend against traffic volume analysis. This only makes sense if you are behind Tor or I2P. See commit.
    +

    Node RPC API

    +

    monerod node offers powerful API. It serves 3 purposes:

    +
      +
    • provides network data (stats, blocks, transactions, ...)
    • +
    • provides local node information (peer list, hash rate if mining, ...)
    • +
    • provides interface for wallets (send transactions, ...)
    • +
    +

    This API is typically referred to as "RPC" because it is mostly based on JSON/RPC standard.

    +

    The following options define how the API behaves.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --public-nodeAdvertise to other users they can use this node as a remote one for connecting their wallets. Requires --restricted-rpc, --rpc-bind-ip and --confirm-external-bind. Without --public-node the node can still be public (assuming other relevant options are set) but won't be advertised as such on the P2P network. This option will allow wallets to auto-discover public nodes (instead of requiring user to manually find one).
    --rpc-bind-ipIP to listen on. By default 127.0.0.1 because API gives full administrative capabilities over the node. Set it to 0.0.0.0 to listen on all interfaces - but only in connection with one of *-restricted-* options and --confirm-external-bind.
    --rpc-bind-portTCP port to listen on. By default 18081 (mainnet), 28081 (testnet), 38081 (stagenet).
    --rpc-bind-ipv6-addressIPv6 to listen on. By default ::1 (localhost). All remarks for --rpc-bind-ip are applicable here as well.
    --rpc-use-ipv6Enable IPv6 for RPC server (disabled by default).
    --rpc-ignore-ipv4Ignore unsuccessful IPv4 bind for RPC. Useful if you only want to use IPv6.
    --rpc-restricted-bind-ipIP to listen on with the limited version of API. The limited API can be made public to create an Open Node.
    --rpc-restricted-bind-portTCP port to listen on with the limited version of API. To be used in combination with `--rpc-restricted-bind-port.
    --confirm-external-bindConfirm you consciously set --rpc-bind-ip to non-localhost IP and you understand the consequences.
    --restricted-rpcRestrict API to view only commands and do not return privacy sensitive data. Note this does not make sense with --rpc-restricted-bind-port because you would end up with two restricted APIs.
    --rpc-sslEnable TLS on RPC connections. One of: enabled | disabled | autodetect (=autodetect by default). You should enable this if you connect a remote wallet.
    --rpc-ssl-private-keyPath to server's private key in PEM format. Generate it with monero-gen-ssl-cert tool. This is to facilitate server authentication to client.
    --rpc-ssl-certificatePath to server's certificate in PEM format. Generate it with monero-gen-ssl-cert tool. This is to facilitate server authentication to client.
    --rpc-ssl-allowed-fingerprintsList of certificate fingerprints to accept. This is a way to authenticate clients.
    --rpc-ssl-allow-any-certAllow any certificate of connecting client.
    --rpc-ssl-ca-certificatesPath to file containing concatenated PEM format certificate(s) to replace system CA(s).
    --rpc-ssl-allow-chainedAllow user chained certificates. This is only applicable if user has a "real" CA issued certificate.
    --rpc-loginSpecify username[:password] required to connect to API.
    --rpc-access-control-originsSpecify a comma separated list of origins to allow cross origin resource sharing. This is useful if you want to use monerod API directly from a web browser via JavaScript (say in a pure-fronted web appp scenario). With this option monerod will put proper HTTP CORS headers to its responses. You will also need to set --rpc-login if you use this option. Normally though, the API is used by backend app and this option isn't necessary.
    +

    Accepting Monero

    +

    These are network notifications offered by monerod. There are also wallet notifications like --tx-notify offered by monero-wallet-rpc here.

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --block-notify <arg>Run a program for each new block. The <arg> must be a full path. If the <arg> contains %s it will be replaced by the block hash. Example:
    ./monerod --block-notify="/usr/bin/echo %s"

    Block notifications are good for immediate reaction. However, you should always assume you will miss some block notifications and you should independently poll the API to cover this up.

    Mind blockchain reorganizations. Block notifications can revert to same and past heights. Small reorganizations are natural and happen every day.
    --block-rate-notify <arg>Run a program when the number of blocks received in the recent past deviates significantly from the expectation. The <arg> must be a full path. The <arg> can contain any of %t, %b, %e symbols to interpolate:

    %t: the number of minutes in the observation window

    %b: the number of blocks observed in that window

    %e: the ideal number of blocks expected in that window

    The option will let you know if the network hash rate drops by a lot. This may be indicative of a large section of the network miners moving off to mine a private chain, to be later released to the network. Note that if this event triggers, it is not incontrovertible proof that this is happening. It might just be chance. The longer the window (the %t parameter), and the larger the distance between actual and expected number of blocks, the more indicative it is of a possible chain reorg double-spend attack being prepared.

    Recommendation: unless you run economically significant Monero exchange or operation, do not act on this data. It is hard to calibrate and easy to misinterpret. If this is a real attack, it will target high-liquidity entities and not small merchants.
    --reorg-notify <arg>Run a program when reorganization happens (ie, at least one block is removed from the top of the blockchain). The <arg> must be a full path. The <arg> can contain any of %s, %h, %n symbols to interpolate:

    %s: the height at which the split occurs

    %h: the height of the new blockchain

    %d: the number of blocks discarded from the old chain

    %n: the number of blocks being added

    The option will let you know when a block is removed from the chain to be replaced by other blocks. This happens when a 51% attack occurs, but small reorgs also happen in the normal course of things. The %d parameter will be set to the number of blocks discarded from the old chain (so if this is higher than the number of confirmations you wait to act upon an incoming payment, that payment might have been cancelled). The %n parameter wil be set to the number of blocks in the new chain (so if this is higher than the number of confirmations you wait to act upon an incoming payment, any incoming payment in the first block will be automatically acted upon by your platform).

    Recommendation: unless you run economically significant Monero exchange or operation, you do not need to bother with this option. Simply account for reorganizations by requiring at least 10 confirmations before shipping valuable goods.
    +

    Performance

    +

    These are advanced options that allow you to optimize performance of your monerod node, sometimes at the expense of reliability.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --prune-blockchainPruning saves 2/3 of disk space w/o degrading functionality. For maximum effect this should be used already on the first sync. If you add this option later the past data will only be pruned logically w/o shrinking the file size and the gain will be delayed.

    If you already have unpruned blockchain, see the monero-blockchain-prune tool.

    The drawback is that you will contribute less to Monero P2P network in terms of helping new nodes to sync up (up to 1/8 of normal contribution). You will still be useful regarding relaying new transactions and blocks though.
    --sync-pruned-blocksAccept pruned blocks instead of pruning yourself. It should save network transfer when used with --prune-blockchain. See the commit and comments.
    --db-sync-modeSpecify sync option, using format:
    [safe|fast|fastest]:[sync|async]:[<nblocks_per_sync>[blocks]|<nbytes_per_sync>[bytes]]

    The default is fast:async:250000000bytes.

    The fast:async:* can corrupt blockchain database in case of a system crash. It should not corrupt if just monerod crashes. If you are concerned with system crashes use safe:sync.
    --max-concurrencyMax number of threads to use for parallel jobs. The default value 0 uses the number of CPU threads.
    --prep-blocks-threadsMax number of threads to use when computing block hashes (PoW) in groups. Defaults to 4. Decrease this if you don't want monerod hog your computer when syncing.
    --fast-block-syncSync up most of the way by using embedded, "known" block hashes. Pass 1 to turn on and 0 to turn off. This is on (1) by default. Normally, for every block the full node must calculate the block hash to verify miner's proof of work. Because the CryptoNight PoW used in Monero is very expensive (even for verification), monerod offers skipping these calculations for old blocks. In other words, it's a mechanism to trust monerod binary regarding old blocks' PoW validity, to sync up faster.
    --block-sync-sizeHow many blocks are processed in a single batch during chain synchronization. By default this is 20 blocks for newer history and 100 blocks for older history ("pre v4"). Default behavior is represented by value 0. Intuitively, the more resources you have, the bigger batch size you may want to try out. Example:
    ./monerod --block-sync-size=500
    --bootstrap-daemon-addressThe host:port of a "bootstrap" remote open node that the connected wallets can use while this node is still not fully synced. Example:
    ./monerod --bootstrap-daemon-address=opennode.xmr-tw.org:18089. The node will forward selected RPC calls to the bootstrap node. The wallet will handle this automatically and transparently. Obviously, such bootstraping phase has privacy implications similar to directly using a remote node.
    --bootstrap-daemon-loginSpecify username:password for the bootstrap daemon login (if required). This considers the RPC interface used by the wallet. Normally, open nodes do not require any credentials.
    --no-syncDo not sync up. Continue using bootstrap daemon instead (if set). See commit.
    +

    Mining

    +

    The following options configure solo mining using CPU with the standard software stack monerod. This is mostly useful for:

    +
      +
    • generating your stagenet or testnet coins
    • +
    • experimentation and learning
    • +
    • if you have super cheap access to vast CPU resources
    • +
    +

    Be advised though that real mining happens in pools and with high-end GPU-s instead of CPU-s.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --start-miningSpecify wallet address to mining for. This must be a standard address! It can be neither a subaddres nor integrated address.
    --mining-threadsSpecify mining threads count. By default ony one thread will be used. For best results, set it to number of your physical cores.
    --extra-messages-fileSpecify file for extra messages to include into coinbase transactions.
    --bg-mining-enableEnable unobtrusive mining. In this mode mining will use a small percentage of your system resources to never noticeably slow down your computer. This is intended to encourage people to mine to improve decentralization. That being said chances of finding a block are diminishingly small with solo CPU mining, and even lesser with its unobtrusive version. You can tweak the unobtrusivness / power trade-offs with the further --bg-* options below.
    --bg-mining-ignore-batteryIf true, assumes plugged in when unable to query system power status.
    --bg-mining-min-idle-intervalSpecify min lookback interval in seconds for determining idle state.
    --bg-mining-idle-thresholdSpecify minimum avg idle percentage over lookback interval.
    --bg-mining-miner-targetSpecify maximum percentage cpu use by miner(s).
    +

    Testing Monero itself

    +

    These options are useful for Monero project developers and testers. Normal users shouldn't be concerned with these.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --keep-alt-blocksKeep alternative blocks on restart. May help with researching reorgs etc. Commit. Research project by noncesense research lab.
    --test-drop-downloadFor net tests: in download, discard ALL blocks instead checking/saving them (very fast).
    --test-drop-download-heightLike test-drop-download but discards only after around certain height. By default 0.
    --regtestRun in a regression testing mode.
    --keep-fakechainDon't delete any existing database when in fakechain mode.
    --fixed-difficultyFixed difficulty used for testing. By default 0.
    --test-dbg-lock-sleepSleep time in ms, defaults to 0 (off), used to debug before/after locking mutex. Values 100 to 1000 are good for tests.
    --save-graphSave data for dr Monero.
    +

    Legacy

    +

    These options should no longer be necessary. They are still present in monerod for backwards compatibility.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    --ban-listSpecify ban list file, one IP address per line. This was introduced as an emergency measure to deal with large DDoS attacks on Monero p2p network in Dec 2020 / Jan 2021. Example:
    ./monerod --ban-list=block_tor.txt. Here is the popular block_tor.txt file.

    It is not recommended to statically ban any IP addresses unless you absolutely need to. Banning IPs often excludes the most vulnerable users who are forced to operate entirely behind Tor or other anonymity networks.
    --enable-dns-blocklistSimilar to --ban-list but instead of a static file uses dynamic IP blocklist available as DNS TXT entries. The DNS blocklist is centrally managed by Monero contributors. It is not recommended unless in emergency situations.
    --fluffy-blocksRelay compact blocks. Default. Compact block is just a header and a list of transaction IDs.
    --no-fluffy-blocksRelay classic full blocks. Classic block contains all transactions.
    --show-time-statsOfficial docs say "Show time-stats when processing blocks/txs and disk synchronization" but it does not seem to produce any output during usual blockchain synchronization.
    --zmq-rpc-bind-ipIP for ZMQ RPC server to listen on. By default 127.0.0.1. This is not yet widely used as ZMQ interface currently does not provide meaningful advantage over classic JSON-RPC interface.
    --zmq-rpc-bind-portPort for ZMQ RPC server to listen on. By default 18082 for mainnet, 38082 for stagenet, and 28082 for testnet.
    --zmq-pubAddress for ZMQ pub - tcp://ip:port or ipc://path
    --db-typeSpecify database type. The default and only available: lmdb.
    +

    Commands

    +

    Commands give access to specific services provided by the daemon. +Commands are executed against the running daemon. +Their names follow the command_name pattern.

    +

    The following groups are only to make reference easier to follow. +The daemon itself does not group commands in any way.

    +

    See running for example usage. +You can also type commands directly in the console of the running monerod (if not detached).

    +

    Help, version, status

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    help [<command>]Show help for <command>.
    versionShow version information. Example output:
    Monero 'Boron Butterfly' (v0.14.0.0-release)
    statusShow status. Example output:
    Height: 186754/186754 (100.0%) on stagenet, not mining, net hash 317 H/s, v9, up to date, 8(out)+0(in) connections, uptime 0d 3h 48m 47s
    +

    P2P network

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    print_plShow the full peer list.
    print_pl_statsShow the full peer list statistics (white vs gray peers). White peers are online and reachable. Grey peers are offline but your monerod remembers them from past sessions.
    print_cnShow connected peers with connection initiative (incoming/outgoing) and other stats.
    ban <IP> [<seconds>]Ban a given <IP> for a given amount of <seconds>. By default the ban is for 24h. Example:
    ./monerod ban 187.63.135.161.
    unban <IP>Unban a given <IP>.
    bansShow the currently banned IPs. Example output:
    187.63.135.161 banned for 86397 seconds.
    in_peers <max_number>Set the of incoming connections from other peers.
    out_peers <max_number>Set the of outgoing connections to other peers.
    limit [<kB/s>]Get or set the download and upload limit.
    limit_down [<kB/s>]Get or set the download limit.
    limit_up [<kB/s>]Get or set the upload limit.
    +

    Transaction pool

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    flush_txpool [<txid>]Flush specified transaction from transactions pool, or flush the whole transactions pool if was not provided.
    print_poolPrint the transaction pool using a verbose format.
    print_pool_shPrint the transaction pool using a short format.
    print_pool_statsPrint the transaction pool's statistics (number of transactions, memory size, fees, double spend attempts etc).
    +

    Transactions

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    print_coinbase_tx_sum <start_height> [<block_count>]Show a sum of all emitted coins and paid fees within specified range. Example:
    ./monerod print_coinbase_tx_sum 0 1000000000000
    print_tx <transaction_hash> [+hex] [+json]Show specified transaction as JSON and/or HEX.
    relay_tx <txid>Force relaying the transaction. Useful if you want to rebroadcast the transaction for any reason or if transaction was previously created with "do_not_relay":true.
    +

    Blockchain

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    print_heightShow local blockchain height.
    sync_infoShow blockchain sync progress and connected peers along with download / upload stats.
    print_bc <begin_height> [<end_height>]Show blocks in range <begin_height>..<end_height>. The information will include block id, height, timestamp, version, size, weight, number of non-coinbase transactions, difficulty, nonce, and reward.
    print_block <block_hash> | <block_height>Show detailed data of specified block.
    hard_fork_infoShow current consensus version and future hard fork block height, if any.
    is_key_image_spent <key_image>Check if specified key image is spent. Key image is a hash.
    +

    Manage daemon

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    exit, stop_daemonAsk daemon to exit gracefully. The exit and stop_daemon are identical (one is alias of the other).
    set_log <level>|<{+,-,}categories>Set the current log level/categories where <level> is a number 0-4.
    print_statusShow if daemon is running.
    update (check|download)Check if update is available and optionally download it. The hash is SHA-256. On linux use sha256sum to verify. Example output:
    Update available: v0.13.0.4: https://downloads.getmonero.org/cli/monero-linux-x64-v0.13.0.4.tar.bz2, hash 693e1a0210201f65138ace679d1ab1928aca06bb6e679c20d8b4d2d8717e50d6
    Update downloaded to: /opt/monero-v0.13.0.2/monero-linux-x64-v0.13.0.4.tar.bz2
    +

    Mining

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescription
    show_hrAsk monerod daemon to print current hash rate. Relevant only if monerod is mining.
    hide_hrAsk monerod daemon to stop printing current hash rate. Relevant only if monerod is mining.
    start_mining <addr> [<threads>] [do_background_mining] [ignore_battery]Ask moneroddaemon to start mining. Block reward will go to <addr>.
    stop_miningAsk monerod daemon to stop mining.
    +

    Testing Monero itself

    + + + + + + + + + + + + + + + + + +
    OptionDescription
    start_save_graphStart saving data for dr Monero.
    stop_save_graphStop saving data for dr Monero.
    +

    Legacy

    + + + + + + + + + + + + + + + + + +
    OptionDescription
    saveFlush blockchain data to disk. This is normally no longer necessary as monerod saves the blockchain automatically on exit.
    output_histogram [@<amount>] <min_count> [<max_count>]Show number of outputs for each amount denomination. This was only relevant in the pre-RingCT era. The old wallet used this to determine which outputs can be used for the requested mixin. With RingCT denominations are irrelevant as amounts are hidden. More info in these SA answers.
    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/overview/index.html b/public/interacting/overview/index.html new file mode 100644 index 0000000..84bb4bc --- /dev/null +++ b/public/interacting/overview/index.html @@ -0,0 +1,1302 @@ + + + + + + + + + + + + + + + + + + + + + + + Interacting with Monero - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Interacting with Monero

    +

    You can interact with Monero via desktop GUI, commandline interface, and programming API.

    +

    On top of that, Monero nodes interact with each other in a peer-to-peer network.

    +

    Installation directory overview

    +

    Once unpacked you will see several executable files. You will also find a nice PDF guide for the GUI wallet.

    +

    Monero project nicely decouples network node logic from wallet logic. +Wallet logic is offered through three independent user interfaces - the GUI, the CLI, and the HTTP API.

    +
    # cd monero-gui-v0.17.1.9
    +
    +# ---- guide to Monero GUI ----
    +
    +monero-gui-wallet-guide.pdf
    +
    +# ---- main executable files -----------
    +
    +monerod
    +monero-wallet-gui
    +
    +# ---- extra executable files -----------
    +
    +extras/monero-wallet-cli
    +extras/monero-wallet-rpc
    +
    +extras/monero-blockchain-prune
    +extras/monero-gen-trusted-multisig
    +extras/monero-gen-ssl-cert
    +
    +extras/monero-blockchain-export
    +extras/monero-blockchain-import
    +
    +# ---- don't bother with these ----------
    +
    +extras/monero-blockchain-stats
    +extras/monero-blockchain-mark-spent-outputs
    +extras/monero-blockchain-prune-known-spent-data
    +extras/monero-blockchain-usage
    +extras/monero-blockchain-ancestry
    +extras/monero-blockchain-depth
    +
    +

    Executables

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ExecutableDescription
    monerodThe full node daemon. Does not require a wallet.
    Documentation.
    monero-wallet-guiWallet logic and graphical user interface.
    Requires monerod running.
    monero-wallet-cliWallet logic and commandline user interface.
    Requires monerod running.
    monero-wallet-rpcWallet logic and HTTP API (JSON-RPC protocol).
    Requires monerod running.
    monero-blockchain-prunePrune existing local blockchain. This saves 2/3 of disk space (down to 31GB as of Jan 2021). This is preferable over monerod --prune-blockchain which only logically releases space inside the file while the file remains large. The monero-blockchain-prune creates a shrinked copy of the blockchain file. See tutorial1, tutorial2.
    monero-gen-ssl-certGenerate 4096 bit RSA private key and self signed TLS certificate for use with monerod RPC interface. Note, Monero daemon automatically generates TLS certificate on each restart. Manual generation with this tool is only useful if you want to pin TLS certificate fingerprint in your monero wallet. See the pull request.
    monero-gen-trusted-multisigTool to generate a set of multisig wallets.
    See chapter on multisignatures.
    monero-blockchain-exportTool to export blockchain to blockchain.raw file.
    monero-blockchain-importTool to import blockchain.raw - ideally your own trusted copy.
    +

    Executables - legacy

    +

    You most likely should not bother with these legacy or very specialized tools.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ExecutableDescription
    monero-blockchain-statsGenerate stats like tx/day, blocks/day, bytes/day based on your local blockchain.
    monero-blockchain-mark-spent-outputsAdvanced tool to mitigate potential privacy issues related to Monero forks. You normally shouldn't be concerned with that.
    See the commit and pull request.
    monero-blockchain-prune-known-spent-dataPrevious limited pruning tool to prune select "known spent" transaction outputs (from the before RCT era). Nowadays prefer monero-blockchain-prune. This only saves ~200 MB. See the commit.
    monero-blockchain-usageAdvanced tool to mitigate potential privacy issues related to Monero forks. You normally shouldn't be concerned with that.
    See the commit and the pull request.
    monero-blockchain-ancestryAdvanced research tool to learn ancestors of a transaction, block or chain. Irrelevant for normal users. See this pull request.
    monero-blockchain-depthAdvanced research tool to learn depth of a transaction, block or chain. Irrelevant for normal users. See this commit.
    +

    Interacting

    +

    There are quite a few ways you can interact with Monero software. +Perhaps the most surprising for newcomers is that monerod daemon accepts interactive keyboard commands while it is running.

    +

    Also, please note that HTTP API is split across monerod and monero-wallet-rpc. You need to run and call both daemons to explore the full API. +This follows the node-logic vs wallet-logic split mentioned earlier.

    +

    All wallet implementations depend on the monerod running.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Executablep2p networknode commands via keyboardnode HTTP APIwallet commands via keyboardwallet HTTP APIwallet via GUI
    monerod
    monero-wallet-cli
    monero-wallet-rpc
    monero-wallet-gui
    +

    Data directory

    +

    This is where the blockchain, log files, and p2p network memory are stored.

    +

    By default data directory is at:

    +
      +
    • $HOME/.bitmonero/ on Linux and macOS
    • +
    • C:\ProgramData\bitmonero\ on Windows
    • +
    +

    Please mind:

    +
      +
    • data directory is hidden as per OS convention
    • +
    • the bitmonero directory name is historical artefact from before Monero forked away from Bitmonero, about 2000 years Before Christ
    • +
    +

    Data directory contains:

    +
      +
    • lmdb/ - the blockchain database directory
    • +
    • p2pstate.bin - saved memory of discovered and rated peers
    • +
    • bitmonero.log - log file
    • +
    +

    It can also contain subdirectories for stagenet and testnet, mirroring the same structure:

    +
      +
    • stagenet/ - data directory for Stagenet
    • +
    • testnet/ - data directory for Testnet
    • +
    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/interacting/verify-monero-binaries/index.html b/public/interacting/verify-monero-binaries/index.html new file mode 100644 index 0000000..87c72ec --- /dev/null +++ b/public/interacting/verify-monero-binaries/index.html @@ -0,0 +1,1121 @@ + + + + + + + + + + + + + + + + + + + + + + + Verifying Monero Binaries Signature - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Verify Monero Binaries

    +

    Verification must be carried on before extracting the archive and before using Monero.

    +

    Instructions were tested on Linux. They should also work on macOS with slight modifications.

    +

    1. Import lead maintainer PGP key

    +

    This is a one time action. Skip this step for subsequent Monero releases.

    +

    Monero core developers sign a list of hashes of released binaries.

    +

    BinaryFate is Monero core developer who signs the releases. +His public key is available on GitHub in the project source code. +Import binaryFate's public key to your keyring:

    +

    curl https://raw.githubusercontent.com/monero-project/monero/master/utils/gpg_keys/binaryfate.asc | gpg --import

    +

    Trust binaryFate's public key (fingerprint must be exactly this):

    +
    gpg --edit-key '81AC591FE9C4B65C5806AFC3F0AF4D462A0BDF92'
    +trust
    +4
    +
    +
    +

    Danger

    +

    If key with this fingerprint was not found then remove imported key immediately (gpg --delete-keys ...). +That would mean the key changed (likely was compromised).

    +
    +

    2. Verify signature of hash list (hashes.txt)

    +

    The list of binaries and their hashes is published on getmonero.org and a few other places like release notes on r/monero. +Please note the publication channel does not matter as long as you properly verify the signature! u

    +

    To verify these are real hashes (not tampered with) run:

    +

    curl https://www.getmonero.org/downloads/hashes.txt | gpg --verify

    +

    The expected output should contain the line:

    +

    gpg: Good signature from "binaryFate <binaryfate@getmonero.org>"

    +

    3. Verify the hash

    +

    By this step we checked that published hashes were not tampered with.

    +

    The last step is to compare published hash with downloaded archive SHA-256 hash.

    +

    Download Monero if you didn't already (but do not unpack).

    +

    Replace the example file name with actual one:

    +
    file_name=monero-gui-linux-x64-v0.17.1.9.tar.bz2
    +
    +file_hash=`sha256sum $file_name | cut -c 1-64`
    +
    +curl https://www.getmonero.org/downloads/hashes.txt > /tmp/reference-hashes.txt
    +
    +# verify the signature (previous step is repeated here for completeness)
    +gpg --verify /tmp/reference-hashes.txt
    +
    +# grep must print the hash (output cannot be empty)
    +grep $file_hash /tmp/reference-hashes.txt
    +
    +
    +

    Danger

    +

    If the grep output is empty then double check everything because apparently the hashes don't match.

    +
    +

    If grep printed filename and hash then everything is alright!

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/multisignature/index.html b/public/multisignature/index.html new file mode 100644 index 0000000..e30fd8e --- /dev/null +++ b/public/multisignature/index.html @@ -0,0 +1,1216 @@ + + + + + + + + + + + + + + + + + + + + + + + Multisignature - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Multisignature

    +

    In cryptocurrencies, multisig feature allows to sign a transaction with more than one private key. Funds protected with multisig can only be spent by signing with M-of-N keys.

    +

    Example use cases:

    +
      +
    • shared account (1-of-2; both husband and wife individually have full access to their funds)
    • +
    • consensus account (2-of-2; both husband and wife must agree to spend their funds)
    • +
    • threshold account (2-of-3; an escrow service is involved as an independent 3rd party, to co-sign with either the seller, or with the buyer, if seller and buyer do not agree)
    • +
    • secure account (2-of-3; a single owner controlls all 3 keys but secures them via a different means to diversify risks)
    • +
    • arbitrary threshold account (M-of-N; some cryptocurrencies provide full flexibility on the number of signers)
    • +
    +

    Monero multisignature

    +

    Monero doesn't directly implement multisignatures (at least not in a classical sense). Monero emulates the feature by secret splitting.

    +

    Transactions are still signed with a single spend key. The spend key is a sum of all N private keys. The rationale for such design is to decouple multisig from ring signatures.

    +

    Let's consider the 2-of-3 scheme. We have 3 participants. Each participant is granted exactly 2 private keys in a way that pairs do not repeat between participants. This way any 2 participants together have all 3 private keys required to create the private spend key.

    +

    Multi-signing is a wallet-level feature. There is no way to learn from the blockchain which transactions were created using multiple signatures.

    +

    It is also worth noting in Monero there is no multisig addresses as such. Address structure does not care how the underlying private spend key got created.

    +

    After multisig wallet setup every participant ends up knowing the public address and private view key. This is necessary for participants to recognize and decipher transactions they are supposed to co-sign.

    +

    Multisig wallet setup

    +

    Multisig feature is only available via a command line wallet. You should be familiar with the CLI wallet before playing with multisig.

    +

    Let's consider a 2-of-3 scheme as it generalizes well.

    +

    0. Open your wallet

    +

    Access your (stagenet) wallet:

    +
    ./monerod --stagenet --daemon                     # Run your full node; make sure it is fully synced    
    +./monero-wallet-cli --stagenet --wallet-file=...  # Run your wallet; make sure you have some funds to play with    
    +
    +

    1. prepare_multisig

    +

    Every participant independently generates initialization data. This is not an address.

    +

    Every participant sends his initialization data manually to all other participants over secure channel.

    +

    2. make_multisig

    +

    Every participant applies initialization data from other participants. This results in a second round of initialization data. This is still not an address.

    +

    Every participants sends his second round of init data to all other participants over secure channel.

    +

    3. finalize_multisig

    +

    Every participant finalizes wallet creation by applying the second round of init data from all other participants. This finally results in a wallet public address and private view key to be known for all participants.

    +

    Please note actions are symmetric for all participants. Even though we considered a 2-of-3 scheme, every participant cooperates with everyone else. The secret splitting is performed internally by the wallet.

    +

    Secure sharing of initialization data between participants is manual. The wallet itself does not provide any secure communication channel. This is out of scope.

    +

    Receiving funds

    +

    Address built by multisig setup is like any other address.

    +

    You can generate integrated addresses and subaddresses based on it.

    +

    All participants are able to see incoming funds as they share the private view key.

    +

    With a CLI, use the following commands to see incoming payments:

    +
    address
    +refresh
    +show_transfers
    +
    +

    Spending funds

    +

    TODO

    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/overrides.css b/public/overrides.css new file mode 100644 index 0000000..6281bce --- /dev/null +++ b/public/overrides.css @@ -0,0 +1,10 @@ + +/* Make reference options non-wrapping */ +article .md-typeset__table td:nth-child(1) { + white-space: nowrap; +} + +/* Make reference tables occupying full width */ +article .md-typeset__table { + width: 100%; +} diff --git a/public/proof-of-work/cryptonight/index.html b/public/proof-of-work/cryptonight/index.html new file mode 100644 index 0000000..937d404 --- /dev/null +++ b/public/proof-of-work/cryptonight/index.html @@ -0,0 +1,1403 @@ + + + + + + + + + + + + + + + + + + + + + + + CryptoNight - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + + + + +
    +
    + + + + + + + +

    CryptoNight

    +
    +

    CryptoNight is a memory hard hash function

    +
    +

    Background

    +

    CryptoNight was originally designed around 2013 as part of the CryptoNote suite.

    +

    One design goal was to make it very friendly for the off-the-shelf CPU-s, by employing:

    +
      +
    • native AES encryption
    • +
    • fast 64 bit multipliers
    • +
    • scratchpad fitting exactly the size of the per-core L3 cache on Intel CPUs (about 2MB)
    • +
    +

    More ambitious design goal was to make it inefficiently computable on ASIC-s. +This goal has since failed, as it inevitably happens with "ASIC hard" algorithms. +Efficient CryptoNight ASIC was developed in 2017 by Bitmain.

    +

    Monero inherited CryptoNight as its proof of work in 2014. +Since then Monero slightly evolved the algorithm to intentionally break compatibility with released ASIC-s. +Currently Monero implements CryptoNight v2, a third iteration of original CryptoNight (v0, v1, v2).

    +

    The goal is to find small-enough hash

    +

    In hashing based PoW algorithms the goal is to find small-enough hash.

    +

    Hash is simply an integer (normally, a very large integer). +Most hashing functions result in 256-bit hashes (integers between 0 and 2^256). +This includes Bitcoin's double-SHA-256 and Monero's CryptoNight.

    +

    Miner randomly tweaks input data until the hash fits under specified threshold. +The threshold (also a large integer) is established collectively by the network as part of the consensus mechanism. +The PoW is only considered valid (solved) if hash fits under the threshold.

    +

    Because hash functions are one-way, it is not possible to analytically calculate input data that would result in a small-enough hash. +The solution must be brute-forced by tweaking the input data and recalculating the hash over and over again.

    +

    Miners have a few areas of flexibility regarding input data - most importantly they can iterate with the nonce value. +They also have a power over which transactions are included in the block and how they are put together in a merkle tree.

    +

    Cryptographic primitives

    +

    CryptoNight is based on:

    +
      +
    • AES encryption
    • +
    • 5 hashing functions, all of which were finalists in NIST SHA-3 competition:
        +
      • Keccak (the primary one)
      • +
      • BLAKE
      • +
      • Groestl
      • +
      • JH
      • +
      • Skein
      • +
      +
    • +
    +

    Input data

    +

    In Monero the input to hashing function is concatenation of:

    +
      +
    • serialized block header (around 46 bytes; subject to varint representation)
    • +
    • merkle tree root (32 bytes)
    • +
    • number of transactions included in the block (around 1-2 bytes; subject to varint representation)
    • +
    +

    See get_block_hashing_blob() function to dig further.

    +

    Algorithm

    +
    +

    Warning

    +

    The article attempts to give reader a high-level understanding of the CryptoNight algorithm. +For implementation details refer to CryptoNote Standard and Monero source code. +See references at the bottom.

    +
    +

    Overview

    +

    CryptoNight attempts to make memory access a bottleneck for performance ("memory hardness"). It has three steps:

    +
      +
    1. Initialize large area of memory with pseudo-random data. This memory is known as the scratchpad.
    2. +
    3. Perform numerous read/write operations at pseudo-random (but deterministic) addresses on the scratchpad.
    4. +
    5. Hash the entire scratchpad to produce the resulting value.
    6. +
    +

    Step 1: scratchpad initialization

    +

    Firstly, the input data is hashed with Keccak-1600. This results in 200 bytes of pseudorandom data (1600 bits == 200 bytes).

    +

    These 200 bytes become a seed to generate a larger, 2MB-wide buffer of pseudorandom data, +by applying AES-256 encryption.

    +

    The first 0..31 bytes of Keccak-1600 hash are used as AES key.

    +

    The encryption is performed on 128 bytes-long payloads until 2MB is ready. +The first payload are Keccak-1600 bytes 66..191. +The next payload is encryption result of the previous payload.

    +

    Each 128-byte payload is actually encrypted 10 times.

    +

    The details are a bit more nuanced, see "Scratchpad Initialization" in CryptoNote Standard.

    +

    Step 2: memory-hard loop

    +

    The second step is basically 524288 iterations of a simple stateful algorithm.

    +

    Each algorithm iteration reads from and writes back to the scratchpad, +at pseudorandom-but-deterministic locations.

    +

    Critically, next iteration depends on the state prepared by previous iterations. +It is not possible to directly calculate state of future iterations.

    +

    The specific operations include AES, XOR, 8byte_mul, 8byte_add - operations that are CPU-friendly (highly optimized on modern CPU-s).

    +

    The goal here is to make memory latency the bottleneck in attempt to close the gap between potential ASIC-s and general purpose CPU-s.

    +

    Step 3: hashing

    +

    The final step (simplifying) is to:

    +
      +
    • combine original Keccak-1600 output with the whole scratchpad
    • +
    • pick the hashing algorithm based on 2 low-order bits of the result
        +
      • 0=BLAKE-256
      • +
      • 1=Groestl-256
      • +
      • 2=JH-256
      • +
      • 3=Skein-256
      • +
      +
    • +
    • hash the result with selected function
    • +
    +

    The resulting 256-bit hash is the final output of CryptoNight algorithm.

    +

    Monero specific modifications

    +

    CryptoNight v0

    +

    This is how Monero community refers to original implementation of CryptoNight.

    +

    CryptoNight v1

    +

    See the source code diff.

    +

    CryptoNight v2

    +

    See the rationale and the source code diff.

    +

    CryptoNight v3 aka CryptoNightR

    +

    See the rationale and the source code diff.

    +

    Critique

    +
      +
    • CryptoNight hash is relatively expensive to verify. This poses a risk of DoS-ing nodes with incorrect proofs to process. See strong asymmetry requirement.
    • +
    • The hash function was designed from scratch with limited peer review. While CryptoNight is composed of proven and peer-reviewed primitives, combining secure primitives doesn't necessarily result in a secure cryptosystem.
    • +
    • CryptoNight ultimately failed to prevent ASIC-s.
    • +
    • Complexity of CryptoNight kills competition in ASIC manufacturing.
    • +
    +

    CryptoNight proof of work remains one of the most controversial aspect of Monero.

    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/proof-of-work/pow-in-cryptocurrencies/index.html b/public/proof-of-work/pow-in-cryptocurrencies/index.html new file mode 100644 index 0000000..f2fa9eb --- /dev/null +++ b/public/proof-of-work/pow-in-cryptocurrencies/index.html @@ -0,0 +1,1083 @@ + + + + + + + + + + + + + + + + + + + + + + + Proof of Work in Cryptocurrencies - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Proof of Work in Cryptocurrencies

    +
    +

    Proof of work is a Sybil protection mechanism

    +
    +

    PoW protects against Sybil attack

    +

    In decentralized cryptocurrencies untrusted actors confirm (blocks of) transactions.

    +

    If threshold voting was employed then the scheme would break immediately. +This is because nothing prevents a single actor from creating arbitrary number of pseudonyms and take over the voting. +In distributed systems this is known as Sybil attack.

    +

    Instead, cryptocurrencies employ proof of work. In the proof of work scheme, +it is not the number of actors that counts. It is the amount of committed +computational resources.

    +

    This, of course, is much harder to game. +To endanger the scheme, an attacker would have to actually control majority (>50%) of computational resources. +In practice, attacker would need this control over significant period of time.

    +

    PoW is a leader election mechanism

    +

    In distributed systems "leader election" is a process of establishing which node is responsible for (temporarily) coordinating the system.

    +

    In cryptocurrencies PoW is used to elect the node that "wins" the next block.

    +

    Using PoW for leader election was one of the key inventions introduced by Bitcoin.

    +

    Competing nodes (known as "miners") work on a solution to artificial problem. +Every now and then, someone randomly finds the solution. +Chances are linearly proportional to committed computing power.

    +

    The winner uses its solution to "underwrite" the block it assembled. Only blocks with valid solutions are accepted by the network.

    +

    The winner also gets a reward for its work. The reward is a specific amount of cryptocurrency created "out of thin air" and assigned to self. The winner also gets all fees coming from transactions included in the block.

    +

    The difficulty of the PoW problem is dynamically adjusted by the network, with the goal of finding blocks with a roughly constant rate (typically, every couple of minutes).

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/proof-of-work/random-x/index.html b/public/proof-of-work/random-x/index.html new file mode 100644 index 0000000..10e10d6 --- /dev/null +++ b/public/proof-of-work/random-x/index.html @@ -0,0 +1,1002 @@ + + + + + + + + + + + + + + + + + + + + + + + RandomX - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    RandomX

    +

    For general information about RandomX you can read this article.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/proof-of-work/what-is-pow/index.html b/public/proof-of-work/what-is-pow/index.html new file mode 100644 index 0000000..d1ef0d5 --- /dev/null +++ b/public/proof-of-work/what-is-pow/index.html @@ -0,0 +1,1107 @@ + + + + + + + + + + + + + + + + + + + + + + + Proof of Work - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    + +
    + + +
    +
    + + + + + + + +

    Proof of Work

    +
    +

    Proof of work is a way to legitimize untrusted party

    +
    +

    What exactly is proof of work?

    +

    Proof of work is a cryptographic proof that untrusted party committed significant computational resources to solve artificial problem.

    +

    Technically, the "proof" is simply a solution to the problem at hand.

    +

    It's all about legitimizing untrusted party

    +

    How an untrusted party on the Internet could earn any level of your trust?

    +

    It can prove its commitment by solving agreed computationally hard problem.

    +

    For example, by requiring untrusted party to perform a hard computation before you accept their connection, you limit connections only to "committed" parties.

    +

    In another example, you could require PoW to be attached to incoming e-mails to make spam prohibitively expensive.

    +

    Work must be otherwise useless

    +

    The work on and solution to "computationally hard problem" cannot be useful in any other way than to prove the commitment.

    +

    If the work is useful elsewhere then it doesn't prove commitment to you.

    +

    The problem must be artificial. Otherwise incentives are skewed and the whole scheme breaks.

    +

    Strong asymmetry

    +

    The requirement for proof of work scheme is strong asymmetry for work vs verification resources.

    +

    The work must be arbitrarily hard. At the same time proof verification must remain dirt cheap (in terms of computational resources).

    +

    Cheap verification is critical because at this stage we are dealing with potentially huge number of untrusted parties, +who could DoS the verifier by submitting invalid proofs. Such proofs should be trivial to discard.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/public-address/integrated-address/index.html b/public/public-address/integrated-address/index.html new file mode 100644 index 0000000..cb0af24 --- /dev/null +++ b/public/public-address/integrated-address/index.html @@ -0,0 +1,1151 @@ + + + + + + + + + + + + + + + + + + + + + + + Integrated Address - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Integrated Address

    +

    Integrated addresses are ideal for accepting Monero in an automated fashion - like in online stores and exchanges.

    +

    Monero integrated address embeds a payment ID. This allows you to learn for what you are being paid.

    +

    Please note these are Monero technical payment IDs and must not be confused with business identifiers like order number or invoice number.

    +

    The transaction to integrated address will not reveal the payment ID publicly. +Payment ID in a transaction will be encrypted with a shared secret (one-time random key known only to sender and recipient). +Only the recipient will be able to match the transaction against payment ID.

    +

    Monero integrated address obsoletes the former practice of using full 32-bytes payment ID in a transaction extra field (where it was not encrypted).

    +

    Data structure (src):

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    IndexSize in bytesDescription
    01identifies the network and address type; 19 - main chain; 54 - test chain
    132public spend key
    3332public view key
    658compact payment ID - 8 bytes randomly generated by the recipient; note that it does not need encryption in the address itself but it is hidden in a transaction paying to integrated address to prevent linking payment with the address by external observers
    734checksum (Keccak-f[1600] hash of the previous 73 bytes, trimmed to first 4 bytes)
    +

    It totals to 77 bytes. The bytes are then encoded (src) in Monero specific Base58 format, resulting in a 106 chars long string. Example integrated address:

    +

    4LL9oSLmtpccfufTMvppY6JwXNouMBzSkbLYfpAV5Usx3skxNgYeYTRj5UzqtReoS44qo9mtmXCqY45DJ852K5Jv2bYXZKKQePHES9khPK

    +

    Integrated addresses vs subaddresses

    +

    Both types allow you to learn for what you are being paid.

    +

    Individuals should prefer subaddresses to receive payments. This is to improve privacy in certain scenarios. See article on subaddresses for details.

    +

    Businesses accepting payments in an automated way should prefer integrated addresses. The rationale is as follows:

    +
      +
    • +

      Scenario where subaddresses improve privacy is not applicable to businesses b/c businesses have the same identity over time. Consequently, subaddresses provide no benefits over integrated addresses.

      +
    • +
    • +

      No private key is necessary to generate integrated address. This provides a strong security advantage because services that generate integrated addresses need no access to wallet. In contrast, to generate a subaddress, one needs a private view key.

      +
    • +
    • +

      No shared counter is necessary to generate integrated address. This allows individual services to independently generate integrated addresses w/o synchronizing on a common sequence. In contrast, subaddresses are generated sequentially, and so the sequence (the counter or index) is a coupling point between the wallet and all services that need to generate the address. Back to integrated addresses, note that embedded payment IDs are 64-bit. This means the space is large enough that one can simply generate them randomly and reliably assume uniqueness.

      +
    • +
    • +

      In very specific scenarios, preparation effort to monitor a very huge number of subaddresses, could became an issue. See this reddit thread for details.

      +
    • +
    +

    Caveats

    +

    There are some caveats:

    +
      +
    • +

      Single transaction cannot pay to multiple integrated addresses.

      +
    • +
    • +

      As individual running a wallet you should generally prefer subaddresses. However, if you happen to use integrated addresses, you should allow Monero software to generate integrated addresses for you (instead of forcing your own payment IDs).

      +
    • +
    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/public-address/main-address/index.html b/public/public-address/main-address/index.html new file mode 100644 index 0000000..6a64f15 --- /dev/null +++ b/public/public-address/main-address/index.html @@ -0,0 +1,936 @@ + + + + + + + + + + + + + + + + + + + + + + + Main address - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    + + + + + + + +

    Main address

    + + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/public-address/standard-address/index.html b/public/public-address/standard-address/index.html new file mode 100644 index 0000000..8396249 --- /dev/null +++ b/public/public-address/standard-address/index.html @@ -0,0 +1,1154 @@ + + + + + + + + + + + + + + + + + + + + + + + Standard Address - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Address

    +

    Monero public address is what you publish to get paid.

    +

    An address can be generated offline and for free. It boils down to generating a large random number representing your private spending key.

    +

    Publishing your Monero address does not endanger your privacy. That's because in Monero transactions go to stealth addresses which are decoupled from your public address.

    +

    There are a few types of public addresses in Monero:

    +
      +
    • Standard address - basic type of an address, also referred to as raw address
    • +
    • Subaddress - what you should be using by default
    • +
    • Integrated address - relevant for exchanges, merchants, and other businesses accepting Monero in a fully automated way
    • +
    +

    Standard address

    +

    Historically, raw address was the only available option. For that reason it is the most widely adopted and supported address type.

    +

    Its strength is simplicity. However, these days users should prefer receiving to subaddresses instead.

    +

    Technically, raw address is also a basis for creating subaddresses and integrated addresses.

    +

    Raw address is still useful for:

    +
      +
    • accepting block reward in a solo-mining scenario as other addresses are not supported
    • +
    • accepting from senders who batch payouts (like mining pools); in this scenario the sender is paying multiple parties using a single transaction; such transaction has multiple outputs; subaddresses do not work in this scenario
    • +
    • accepting from senders who use legacy wallets (can't send to subaddress)
    • +
    +

    Monero raw address is composed of two public keys:

    +
      +
    • public spend key
    • +
    • public view key
    • +
    +

    It also contains a checksum and a "network byte" which actually identifies both the network and the address type.

    +

    Data structure

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    IndexSize in bytesDescription
    01identifies the network and address type; 18 - main chain; 53 - test chain
    132public spend key
    3332public view key
    654checksum (Keccak-f[1600] hash of the previous 65 bytes, trimmed to first 4 bytes)
    +

    It totals to 69 bytes. The bytes are then encoded (src) in Monero specific Base58 format, resulting in a 95 chars long string. Example standard address:

    +

    4AdUndXHHZ6cfufTMvppY6JwXNouMBzSkbLYfpAV5Usx3skxNgYeYTRj5UzqtReoS44qo9mtmXCqY45DJ852K5Jv2684Rge

    +

    See the source code.

    +

    Generating

    +

    Standard address is derived from the root private key. TODO.

    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/public-address/subaddress/index.html b/public/public-address/subaddress/index.html new file mode 100644 index 0000000..91da361 --- /dev/null +++ b/public/public-address/subaddress/index.html @@ -0,0 +1,1339 @@ + + + + + + + + + + + + + + + + + + + + + + + Subaddress - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + + + + +
    +
    + + + + + + + +

    Subaddress

    +

    Subaddress is what you should be using by default to receive Monero.

    +

    Learn for what you are being paid

    +

    By providing a unique subaddress for each anticipated payment you will know for what you are being paid.

    +

    This use case overlaps with integrated addresses. Subaddresses are generally prefered for reasons outlined below.

    +

    Prevent payer from linking your payouts together

    +

    To prevent the payer from linking your payouts together simply generate a new subaddress for each payout. +This way specific service (like anonymous exchange) that sends you Monero won't (easilly) know it is you again receving Monero.

    +

    The exception to this is when a service (or group of colluding services) decides to actively attack you, one address at the time, with the so cold Janus attack, which risks them losing funds. If you need perfect unlinkability of your receivables, the only solution remains to use a separate seed (separate Monero wallet).

    +

    Also, note it won't help if you have an account with the service. Then your payouts are already linked in the service database, regardless of Monero.

    +

    Group funds into accounts

    +

    Accounts are a convenience wallet-level feature to group subaddresses under one label and balance.

    +

    You may want to organize your funds into accounts like "cash", "work", "trading", "mining", "donations", etc.

    +

    As accounts are only groupings of subaddresses, they themselves do not have an address.

    +

    Accounts are deterministically derived from the root private key along with subaddresses.

    +

    Accounts are similar to subaccounts in your classic bank account. There is a very important difference though. In Monero funds don't really sit on accounts or public addresses. Public addresses are conceptually a gateway or a routing mechanism. Funds sit on transactions' unspent outputs. Thus, a single transaction can - in principle - aggregate and spend outputs from multiple addresses (and by extension from multiple accounts). The CLI or GUI wallet may not directly support creating such transactions for simplicity.

    +

    In short, think of accounts as a soft grouping of your funds.

    +

    Why not multiple wallets?

    +

    The advantage over creating multiple wallets is that you only have a single seed to manage. +All subaddresses can be derived from the wallet seed.

    +

    Additionally, you conveniently manage your subaddresses within a single user interface.

    +

    Wallet level feature

    +

    Subaddresses and accounts are a wallet-level feature to construct and interpret transactions. They do not affect the consensus.

    +

    Data structure

    +

    Subaddress has a dedicated "network byte":

    + + + + + + + + + + + + + + + +
    IndexSize in bytesDescription
    01identifies the network and address type; 42 - mainnet; 36 - stagenet; 63 - testnet
    +

    Otherwise the data structure is the same as for the standard address.

    +

    Generating

    +

    Each subaddress conceptually has:

    +
      +
    • account index (also known as "major" index)
    • +
    • subaddress index within the account (also known as "minor" index)
    • +
    +

    The indexes are 0-based. By default wallets use account index 0.

    +

    The indexes are not directly included in the subaddress data structure. +Instead, they are used as input to generating subaddress keys.

    +

    Private view key

    +

    A per-subaddress scalar m is derived as follows:

    +
    m = Hs("SubAddr" || a || account_index || subaddress_index_within_account)
    +
    +

    Where:

    +
      +
    • Hs is a Keccak-256 hash function interpreted as integer and modulo l (maximum edwards25519 scalar)
    • +
    • || is a byte array concatenation operator
    • +
    • SubAddr is a 0-terminated fixed string (8 bytes total)
    • +
    • a is a private view key of the standard address (a 32 byte little endian unsigned integer)
    • +
    • account_index is index of an account (a 32 bit little endian unsigned integer)
    • +
    • subaddress_index_within_account is index of the subaddress within the account (a 32 bit little endian unsigned integer)
    • +
    +

    Deriving "sub view keys" from the main view key allows for creating a view only wallet that monitors the entire wallet including subaddresses.

    +

    Public spend key

    +

    The subaddress public spend key D is derived as follows:

    +
    D = B + m*G
    +
    +

    Where:

    +
      +
    • B is standard address public spend key
    • +
    • m is a per-subaddress scalar that is derived from the private spend key
    • +
    • G is the "base point"; this is simply a constant specific to edwards25519
    • +
    +

    Public view key

    +

    The subaddress public view key C is derived as follows:

    +
    C = a*D
    +
    +

    Where:

    +
      +
    • a is a private view key of the standard address
    • +
    • D is a public spend key of the subaddress
    • +
    +

    Special case for (0, 0)

    +

    The subaddress #0 on the account #0 is the standard address. +As standard address has different generation rules, this is simply implemented via an if statement.

    +

    Building the address string

    +

    The procedure is the same as for the standard address.

    +

    Caveats

    +
      +
    • It is not recommended to sweep all the balances of subaddress to standard address in a single transaction. That links the subaddresses together on the blockchain. However, this only concerns privacy against specific sender and the situation will never get worse than not using subaddresses in the first place. If you need to join funds while preserving maximum privacy do it with individual transactions (one per subaddress).
    • +
    • Convenience labels are not preserved when recreating from seed.
    • +
    +

    Reference

    + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/r/accepting-monero-comparison-matrix/index.html b/public/r/accepting-monero-comparison-matrix/index.html new file mode 100644 index 0000000..93840b5 --- /dev/null +++ b/public/r/accepting-monero-comparison-matrix/index.html @@ -0,0 +1,936 @@ + + + + + + + + + + + + + + + + + + + + + + + Accepting monero comparison matrix - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    + + + + + + + +

    Accepting monero comparison matrix

    + + + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/running-node/open-node-tor-onion/index.html b/public/running-node/open-node-tor-onion/index.html new file mode 100644 index 0000000..1641baa --- /dev/null +++ b/public/running-node/open-node-tor-onion/index.html @@ -0,0 +1,1486 @@ + + + + + + + + + + + + + + + + + + + + + + + Running Monero Open Node with Tor Onion Support - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + +

    Running Monero Open Node + Tor Onion

    +
    +

    Powerful setup

    +

    This is great contribution to Monero network and also a pretty sophisticated personal setup. If you are a beginner, you don't need this.

    +
    +
    +

    The end goal

    +

    You will publicly offer the following services, where xxx.yyy.zzz.vvv is your server IP address.

    +
      +
    • xxx.yyy.zzz.vvv:18080 - clearnet P2P service (for other nodes)
    • +
    • xxx.yyy.zzz.vvv:18081 - clearnet RPC service (for wallets)
    • +
    • yourlongv3onionaddress.onion:18083 - onion P2P service (for other onion nodes)
    • +
    • yourlongv3onionaddress.onion:18081 - onion RPC service (for wallets connecting over Tor)
    • +
    +

    Why different P2P ports for clearnet and onion? This is a monerod requirement.

    +
    +
    +

    Broadcasting bad transactions from your IP

    +

    As with any public data broadcast or relay service, "bad traffic" or in this case "bad transactions" may appear to originate from your server IP address from an outside observer perspective - even though they really originate from a remote wallet user. This is a potential risk you need to keep in mind.

    +
    +

    Why run this specific setup?

    +

    You will be able to connect your desktop and mobile Monero wallets to your own trusted Monero node, +in a secure and private way over Tor. Your node will be always ready w/o delays (always synced up, contrary to intermittently running node on a laptop).

    +

    Serving blocks and transactions in Monero P2P network helps new users to bootstrap and sync up their nodes. +It also strenghtens Monero P2P network against DDoS attacks and network partitioning.

    +

    Open wallet inteface (the "RPC") allows anyone to connect their wallets to Monero network through your node. +This is useful for beginner users who don't run their own nodes yet.

    +

    Tor onion for wallet interface is useful for wallet users connecting over Tor because it mitigates Tor exit nodes MiTM risks (which are very real). By connecting wallet to an onion service, no MiTM attack is realistic because within the Tor network connections are end-to-end TLS-ed.

    +

    Tor onion for P2P network is useful for other full node users as it allows them to broadcast transactions over Tor (using --tx-proxy option).

    +

    Assumptions

    +

    You understand basic Linux administration. You seek Monero specific guidance.

    +

    You have root access to a Linux server with 2GB+ RAM and 120GB+ SSD (or 50GB+ for the pruned node version). This is current for Jan 2021.

    +

    Some commands assume Ubuntu but you will easily translate them to your distribution.

    +

    Install Tor

    +

    Install Tor.

    +

    Modify /etc/tor/torrc as shown below.

    +

    Enable tor service with systemctl enable tor and restart it via systemctl restart tor

    +

    Verify the Tor is up systemctl status tor@default

    +

    A fresh onion address and corresponding key pair got created for you by the tor daemon in /var/lib/tor/monero/. You may want to backup these to secure control over your onion address. This happens on restart whenever you add new HiddenServiceDir to torrc config.

    +

    Monero daemon itself is not necessary at this point. The onion services (AKA hidden services) will just wait until localhost monerod shows up at specified ports 18081 and 18083.

    +

    /etc/tor/torrc

    +
    HiddenServiceDir /var/lib/tor/monero
    +HiddenServicePort 18081 127.0.0.1:18081    # interface for wallet ("RPC")
    +HiddenServicePort 18083 127.0.0.1:18083    # interface for P2P network
    +
    +
    How Tor onion services work?

    The tor daemon will simply pass over the traffic from virtual onion port to actual localhost port, where some service is listening (in our case, this will be monerod). A single onion address can offer multiple services at various virtual ports. We will use this to expose both P2P and RPC monerod services on a single onion. You could host any number of onion addresses at single server or IP address but we won't need that here.

    +
    +

    Install Monero

    +

    Create monero user and group useradd --system monero

    +

    Create monero binaries directory (empty for now) mkdir -p /opt/monero and chown -R monero:monero /opt/monero

    +

    Create monero data directory mkdir -p /srv/monero and chown -R monero:monero /srv/monero

    +

    Create monero log directory mkdir -p /var/log/monero and chown -R monero:monero /var/log/monero

    +

    Feel free to adjust above to your preferred conventions, just remember to adjust the paths accordingly.

    +

    Download and verify the file.

    +

    Extract tar -xf monero-linux-x64-v0.17.1.9.tar.bz2 (adjust filename).

    +

    Move binaries to /opt/monero/ with mv monero-x86_64-linux-gnu-v0.17.1.9/* /opt/monero/ then chown -R monero:monero /opt/monero

    +

    Create /etc/monero.conf as shown below and paste your values in placeholders.

    +

    Create /etc/systemd/system/monero.service as shown below.

    +

    Enable monero service with systemctl enable monero and restart it with systemctl restart monero

    +

    Verify it is up systemctl status monero

    +

    Verify it is working as intended tail -n100 /var/log/monero/monero.log

    +

    /etc/monero.conf

    +

    This is just an example configuration and it is by no means authoritative. Feel free to modify, see monerod reference.

    +

    Modify paths if you changed them.

    +

    Print your onion address with cat /var/lib/tor/monero/hostname and paste it to anonymous-inbound option.

    +
    # /etc/monero.conf
    +# 
    +# Configuration file for monerod. For all available options see the MoneroDocs:
    +# https://monerodocs.org/interacting/monerod-reference/
    +
    +# Data directory (blockchain db and indices)
    +data-dir=/srv/monero
    +
    +# Optional prunning
    +# prune-blockchain=1           # Pruning saves 2/3 of disk space w/o degrading functionality but contributes less to the network
    +# sync-pruned-blocks=1         # Allow downloading pruned blocks instead of prunning them yourself
    +
    +check-updates=disabled         # Do not check DNS TXT records for a new version
    +
    +# Log file
    +log-file=/var/log/monero/monero.log
    +log-level=0                    # Minimal logs, WILL NOT log peers or wallets connecting
    +max-log-file-size=2147483648   # Set to 2GB to mitigate log trimming by monerod; configure logrotate instead
    +
    +# P2P full node
    +p2p-bind-ip=0.0.0.0            # Bind to all interfaces (the default)
    +p2p-bind-port=18080            # Bind to default port
    +
    +# RPC open node
    +public-node=1                  # Advertise to other users they can use this node as a remote one for connecting their wallets
    +confirm-external-bind=1        # Open Node (confirm)
    +rpc-bind-ip=0.0.0.0            # Bind to all interfaces (the Open Node)
    +rpc-bind-port=18081            # Bind to default port (the Open Node)
    +restricted-rpc=1               # Obligatory for Open Node interface
    +no-igd=1                       # Disable UPnP port mapping
    +no-zmq=1                       # Disable ZMQ RPC server to decrease attack surface (it's not used)
    +
    +# RPC TLS
    +rpc-ssl=autodetect             # Use TLS if client wallet supports it (the default behavior); the certificate will be generated on the fly on every restart
    +
    +# Mempool size
    +max-txpool-weight=268435456    # Maximum unconfirmed transactions pool size in bytes (here 256MB, default ~618MB)
    +
    +# Slow but reliable db writes
    +db-sync-mode=safe
    +
    +out-peers=64              # This will enable much faster sync and tx awareness; the default 8 is suboptimal nowadays
    +in-peers=64               # The default is unlimited; we prefer to put a cap on this
    +
    +limit-rate-up=1048576     # 1048576 kB/s == 1GB/s; a raise from default 2048 kB/s; contribute more to p2p network
    +limit-rate-down=1048576   # 1048576 kB/s == 1GB/s; a raise from default 8192 kB/s; allow for faster initial sync
    +
    +# Tor: broadcast transactions originating from connected wallets over Tor (does not concern relayed transactions)
    +tx-proxy=tor,127.0.0.1:9050,16
    +
    +# Tor: add P2P seed nodes for the Tor network
    +add-peer=moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18080
    +add-peer=monerozf6koypqrt.onion:18080
    +add-peer=zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083        # https://github.com/monero-project/monero/blob/master/src/p2p/net_node.inl
    +add-peer=rno75kjcw3ein6i446sqby2xkyqjarb75oq36ah6c2mribyklzhurpyd.onion:28083        # it's mainnet despite the weird port, according to reddit
    +add-peer=sqzrokz36lgkng2i2nlzgzns2ugcxqosflygsxbkybb4xn6gq3ouugqd.onion:18083        # very flaky, works 1 in 3 times
    +
    +# Tor: tell monerod your onion address so it can be advertised on P2P network
    +anonymous-inbound=PASTE_YOUR_ONION_HOSTNAME:18083,127.0.0.1:18083,64
    +
    +# Tor: be forgiving to connecting wallets; suggested by http://xmrguide42y34onq.onion/remote_nodes
    +disable-rpc-ban=1
    +
    +

    /etc/.../monero.service

    +
    # /etc/systemd/system/monero.service
    +
    +[Unit]
    +Description=Monero Daemon
    +After=network.target
    +Wants=network.target
    +
    +[Service]
    +ExecStart=/opt/monero/monerod --detach --config-file /etc/monero.conf --pidfile /run/monero/monerod.pid
    +ExecStartPost=/bin/sleep 0.1
    +Type=forking
    +PIDFile=/run/monero/monerod.pid
    +
    +Restart=always
    +RestartSec=16
    +
    +User=monero
    +Group=monero
    +RuntimeDirectory=monero
    +
    +StandardOutput=journal
    +StandardError=journal
    +
    +[Install]
    +WantedBy=multi-user.target
    +
    +

    Open firewall ports

    +

    If you use a firewall (and you should), open 18080 and 18081 ports for incoming TCP connections. These are for the incoming clearnet connections, P2P and RPC respectively.

    +

    You do not need to open any ports for Tor. The onion services work with virtual ports. The tor daemon does not directly accept incoming connections and so it needs no open ports.

    +

    For example, for popular ufw firewall, that would be:

    +
    ufw allow 18080/tcp
    +ufw allow 18081/tcp
    +
    +

    To verify, use ufw status. The output should be similar to the following (the 22 being default SSH port, unrelated to Monero):

    +
    To                         Action      From
    +--                         ------      ----
    +22/tcp                     LIMIT       Anywhere                  
    +18080/tcp                  ALLOW       Anywhere                  
    +18081/tcp                  ALLOW       Anywhere                  
    +22/tcp (v6)                LIMIT       Anywhere (v6)             
    +18080/tcp (v6)             ALLOW       Anywhere (v6)             
    +18081/tcp (v6)             ALLOW       Anywhere (v6)   
    +
    +

    Testing

    +

    On server

    +

    List all services listening on ports and make sure it is what you expect:

    +

    sudo netstat -lntpu

    +

    The output should include these (in any order); obviously the PID values will differ.

    +
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    +...
    +tcp        0      0 0.0.0.0:18080           0.0.0.0:*               LISTEN      259255/monerod      
    +tcp        0      0 0.0.0.0:18081           0.0.0.0:*               LISTEN      259255/monerod      
    +tcp        0      0 127.0.0.1:18083         0.0.0.0:*               LISTEN      259255/monerod      
    +tcp        0      0 127.0.0.1:9050          0.0.0.0:*               LISTEN      258786/tor          
    +
    +

    On client machine

    +

    Finally, we want to test connections from your client machine.

    +

    Install tor and torsocks on your laptop, you will want them anyway for Monero wallet.

    +

    Just for testing, you will also need nmap and proxychains.

    +

    Test clearnet P2P connection:

    +

    nmap -Pn -p 18080 YOUR_IP_ADDRESS_HERE

    +

    Test clearnet RPC connection:

    +

    curl --digest -X POST http://YOUR_IP_ADDRESS_HERE:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_info"}' -H 'Content-Type: application/json'

    +

    Test onion P2P connection (skip if you don't have proxychains):

    +

    proxychains nmap -Pn -p 18083 YOUR_ONION_ADDRESS_HERE.onion

    +

    Test onion RPC connection:

    +

    torsocks curl --digest -X POST http://YOUR_ONION_ADDRESS_HERE.onion:18081/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_info"}' -H 'Content-Type: application/json'

    +

    Debugging

    +

    Tor:

    +
      +
    • Status: systemctl status tor@default
    • +
    • Logs: journalctl -xe --unit tor@default
    • +
    +

    Monero:

    +
      +
    • Status: systemctl status monero
    • +
    • Logs: tail -n100 /var/log/monero/monero.log
    • +
    • Logs more info: change log-level=0 to log-level=1 in monero.conf (remember to revert once solved)
    • +
    +

    Further improvements

    +

    Periodic restarts

    +

    It's likely worthwhile to add peridic auto-restarting to both tor and monerod every couple hours. Neither daemon is perfect; they can get stuck or leak memory in edge case situations, +like the recent attacks on Tor v3 or DDoS attacks on the Monero network. One possible way would be to use systemd timers.

    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/search/search_index.json b/public/search/search_index.json new file mode 100644 index 0000000..5549f2a --- /dev/null +++ b/public/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Unofficial Monero Documentation \u00b6 Work in Progress \u00b6 Monerodocs attempts to organize basic technical knowledge on Monero in one place. While technical explanations are out there, knowledge is scattered through reddit posts, git comments, stack exchange answers, chat logs and the source code. This makes it hard to find complete and up-to-date explanations on advanced topics. The goal is to educate and onboard power users faster. Please submit your feedback and corrections directly on github . Find my contact details at qertoip.com .","title":"Home"},{"location":"#unofficial-monero-documentation","text":"","title":"Unofficial Monero Documentation"},{"location":"#work-in-progress","text":"Monerodocs attempts to organize basic technical knowledge on Monero in one place. While technical explanations are out there, knowledge is scattered through reddit posts, git comments, stack exchange answers, chat logs and the source code. This makes it hard to find complete and up-to-date explanations on advanced topics. The goal is to educate and onboard power users faster. Please submit your feedback and corrections directly on github . Find my contact details at qertoip.com .","title":"Work in Progress"},{"location":"multisignature/","text":"Multisignature \u00b6 In cryptocurrencies, multisig feature allows to sign a transaction with more than one private key. Funds protected with multisig can only be spent by signing with M-of-N keys. Example use cases: shared account (1-of-2; both husband and wife individually have full access to their funds) consensus account (2-of-2; both husband and wife must agree to spend their funds) threshold account (2-of-3; an escrow service is involved as an independent 3rd party, to co-sign with either the seller, or with the buyer, if seller and buyer do not agree) secure account (2-of-3; a single owner controlls all 3 keys but secures them via a different means to diversify risks) arbitrary threshold account (M-of-N; some cryptocurrencies provide full flexibility on the number of signers) Monero multisignature \u00b6 Monero doesn't directly implement multisignatures (at least not in a classical sense). Monero emulates the feature by secret splitting. Transactions are still signed with a single spend key. The spend key is a sum of all N private keys. The rationale for such design is to decouple multisig from ring signatures. Let's consider the 2-of-3 scheme. We have 3 participants. Each participant is granted exactly 2 private keys in a way that pairs do not repeat between participants. This way any 2 participants together have all 3 private keys required to create the private spend key. Multi-signing is a wallet-level feature. There is no way to learn from the blockchain which transactions were created using multiple signatures. It is also worth noting in Monero there is no multisig addresses as such. Address structure does not care how the underlying private spend key got created. After multisig wallet setup every participant ends up knowing the public address and private view key. This is necessary for participants to recognize and decipher transactions they are supposed to co-sign. Multisig wallet setup \u00b6 Multisig feature is only available via a command line wallet. You should be familiar with the CLI wallet before playing with multisig. Let's consider a 2-of-3 scheme as it generalizes well. 0. Open your wallet \u00b6 Access your (stagenet) wallet: ./monerod --stagenet --daemon # Run your full node; make sure it is fully synced ./monero-wallet-cli --stagenet --wallet-file=... # Run your wallet; make sure you have some funds to play with 1. prepare_multisig \u00b6 Every participant independently generates initialization data . This is not an address. Every participant sends his initialization data manually to all other participants over secure channel. 2. make_multisig \u00b6 Every participant applies initialization data from other participants. This results in a second round of initialization data . This is still not an address. Every participants sends his second round of init data to all other participants over secure channel. 3. finalize_multisig \u00b6 Every participant finalizes wallet creation by applying the second round of init data from all other participants. This finally results in a wallet public address and private view key to be known for all participants. Please note actions are symmetric for all participants. Even though we considered a 2-of-3 scheme, every participant cooperates with everyone else. The secret splitting is performed internally by the wallet. Secure sharing of initialization data between participants is manual. The wallet itself does not provide any secure communication channel. This is out of scope. Receiving funds \u00b6 Address built by multisig setup is like any other address. You can generate integrated addresses and subaddresses based on it. All participants are able to see incoming funds as they share the private view key. With a CLI, use the following commands to see incoming payments: address refresh show_transfers Spending funds \u00b6 TODO Reference \u00b6 https://monero.stackexchange.com/questions/5646/how-to-use-monero-multisignature-wallets-2-2-2-3","title":"Multisignature"},{"location":"multisignature/#multisignature","text":"In cryptocurrencies, multisig feature allows to sign a transaction with more than one private key. Funds protected with multisig can only be spent by signing with M-of-N keys. Example use cases: shared account (1-of-2; both husband and wife individually have full access to their funds) consensus account (2-of-2; both husband and wife must agree to spend their funds) threshold account (2-of-3; an escrow service is involved as an independent 3rd party, to co-sign with either the seller, or with the buyer, if seller and buyer do not agree) secure account (2-of-3; a single owner controlls all 3 keys but secures them via a different means to diversify risks) arbitrary threshold account (M-of-N; some cryptocurrencies provide full flexibility on the number of signers)","title":"Multisignature"},{"location":"multisignature/#monero-multisignature","text":"Monero doesn't directly implement multisignatures (at least not in a classical sense). Monero emulates the feature by secret splitting. Transactions are still signed with a single spend key. The spend key is a sum of all N private keys. The rationale for such design is to decouple multisig from ring signatures. Let's consider the 2-of-3 scheme. We have 3 participants. Each participant is granted exactly 2 private keys in a way that pairs do not repeat between participants. This way any 2 participants together have all 3 private keys required to create the private spend key. Multi-signing is a wallet-level feature. There is no way to learn from the blockchain which transactions were created using multiple signatures. It is also worth noting in Monero there is no multisig addresses as such. Address structure does not care how the underlying private spend key got created. After multisig wallet setup every participant ends up knowing the public address and private view key. This is necessary for participants to recognize and decipher transactions they are supposed to co-sign.","title":"Monero multisignature"},{"location":"multisignature/#multisig-wallet-setup","text":"Multisig feature is only available via a command line wallet. You should be familiar with the CLI wallet before playing with multisig. Let's consider a 2-of-3 scheme as it generalizes well.","title":"Multisig wallet setup"},{"location":"multisignature/#0-open-your-wallet","text":"Access your (stagenet) wallet: ./monerod --stagenet --daemon # Run your full node; make sure it is fully synced ./monero-wallet-cli --stagenet --wallet-file=... # Run your wallet; make sure you have some funds to play with","title":"0. Open your wallet"},{"location":"multisignature/#1-prepare_multisig","text":"Every participant independently generates initialization data . This is not an address. Every participant sends his initialization data manually to all other participants over secure channel.","title":"1. prepare_multisig"},{"location":"multisignature/#2-make_multisig","text":"Every participant applies initialization data from other participants. This results in a second round of initialization data . This is still not an address. Every participants sends his second round of init data to all other participants over secure channel.","title":"2. make_multisig"},{"location":"multisignature/#3-finalize_multisig","text":"Every participant finalizes wallet creation by applying the second round of init data from all other participants. This finally results in a wallet public address and private view key to be known for all participants. Please note actions are symmetric for all participants. Even though we considered a 2-of-3 scheme, every participant cooperates with everyone else. The secret splitting is performed internally by the wallet. Secure sharing of initialization data between participants is manual. The wallet itself does not provide any secure communication channel. This is out of scope.","title":"3. finalize_multisig"},{"location":"multisignature/#receiving-funds","text":"Address built by multisig setup is like any other address. You can generate integrated addresses and subaddresses based on it. All participants are able to see incoming funds as they share the private view key. With a CLI, use the following commands to see incoming payments: address refresh show_transfers","title":"Receiving funds"},{"location":"multisignature/#spending-funds","text":"TODO","title":"Spending funds"},{"location":"multisignature/#reference","text":"https://monero.stackexchange.com/questions/5646/how-to-use-monero-multisignature-wallets-2-2-2-3","title":"Reference"},{"location":"technical-specs/","text":"Monero Technical Specs \u00b6 Live \u00b6 Monero blockchain is live since 18 April 2014 No premine, no instamine, no ICO, no token \u00b6 Monero had no premine or instamine Monero did not sell any token Monero had no presale of any kind Proof of Work \u00b6 CryptoNight v0 since block height 0 v1 since block height 1546000 (forked on 2018-04-06) v2 since block height 1685555 (forked on 2018-10-18) v3 since block height 1788000 (forked on 2019-03-09); \"CryptonightR\" RandomX v0 since block height 1978433 (forked on 2019-11-30) Difficulty retarget \u00b6 every block based on the last 720 blocks (24h), excluding 20% of the timestamp outliers Block time \u00b6 2 minutes may change in the future as long as emission curve is preserved Block reward \u00b6 smoothly decreasing and subject to penalties for blocks greater then median size of the last 100 blocks (M100) ~1.6 XMR as of June 2020; for the current reward check the coinbase transaction of the latest block Block size \u00b6 dynamic maximum of two times the median size of the last 100 blocks (2 * M100) ~50KB as of June 2020; check the latest block size Emission curve \u00b6 Main emission \u00b6 first, the main emission is about to produce ~18.132 million coins by the end of May 2022 as of June 2020 the emission is about 8 XMR per 10 minutes see charts and details Tail emission \u00b6 the tail emission kicks in once main emission is done it will produce 0.6 XMR per 2-minute block this translates to <1% inflation decreasing over time Max supply \u00b6 ~18.132 million XMR + 0.6 XMR per 2 minutes technically infinite but practically deflationary if accounted for lost coins Divisibility \u00b6 Monero is divisible up to 12 digits The smallest unit is called piconero and equals 1e-12 XMR, or 0.000000000001 XMR Sender privacy \u00b6 ring signatures the ring size is 11 (10 decoys) assurance: probabilistic / plausible deniability Recipient privacy \u00b6 stealth addresses assurance: strong Amount privacy \u00b6 ring confidential transactions assurance: strong IP address privacy \u00b6 For the full node ( monerod ): dandelion++ assurance: won't protect against ISP/VPN provider, won't protect against the very first remote node in Dandellion++ protocol for the full protection user must manually wrap monerod with Tor For the wallet ( monero-wallet-gui or monero-wallet-cli ): typically wallet runs on the same machine as full node so there is no risk if wallet connects to remote full node, there is no IP protection by default user must manually wrap wallet with Tor","title":"Technical specs"},{"location":"technical-specs/#monero-technical-specs","text":"","title":"Monero Technical Specs"},{"location":"technical-specs/#live","text":"Monero blockchain is live since 18 April 2014","title":"Live"},{"location":"technical-specs/#no-premine-no-instamine-no-ico-no-token","text":"Monero had no premine or instamine Monero did not sell any token Monero had no presale of any kind","title":"No premine, no instamine, no ICO, no token"},{"location":"technical-specs/#proof-of-work","text":"CryptoNight v0 since block height 0 v1 since block height 1546000 (forked on 2018-04-06) v2 since block height 1685555 (forked on 2018-10-18) v3 since block height 1788000 (forked on 2019-03-09); \"CryptonightR\" RandomX v0 since block height 1978433 (forked on 2019-11-30)","title":"Proof of Work"},{"location":"technical-specs/#difficulty-retarget","text":"every block based on the last 720 blocks (24h), excluding 20% of the timestamp outliers","title":"Difficulty retarget"},{"location":"technical-specs/#block-time","text":"2 minutes may change in the future as long as emission curve is preserved","title":"Block time"},{"location":"technical-specs/#block-reward","text":"smoothly decreasing and subject to penalties for blocks greater then median size of the last 100 blocks (M100) ~1.6 XMR as of June 2020; for the current reward check the coinbase transaction of the latest block","title":"Block reward"},{"location":"technical-specs/#block-size","text":"dynamic maximum of two times the median size of the last 100 blocks (2 * M100) ~50KB as of June 2020; check the latest block size","title":"Block size"},{"location":"technical-specs/#emission-curve","text":"","title":"Emission curve"},{"location":"technical-specs/#main-emission","text":"first, the main emission is about to produce ~18.132 million coins by the end of May 2022 as of June 2020 the emission is about 8 XMR per 10 minutes see charts and details","title":"Main emission"},{"location":"technical-specs/#tail-emission","text":"the tail emission kicks in once main emission is done it will produce 0.6 XMR per 2-minute block this translates to <1% inflation decreasing over time","title":"Tail emission"},{"location":"technical-specs/#max-supply","text":"~18.132 million XMR + 0.6 XMR per 2 minutes technically infinite but practically deflationary if accounted for lost coins","title":"Max supply"},{"location":"technical-specs/#divisibility","text":"Monero is divisible up to 12 digits The smallest unit is called piconero and equals 1e-12 XMR, or 0.000000000001 XMR","title":"Divisibility"},{"location":"technical-specs/#sender-privacy","text":"ring signatures the ring size is 11 (10 decoys) assurance: probabilistic / plausible deniability","title":"Sender privacy"},{"location":"technical-specs/#recipient-privacy","text":"stealth addresses assurance: strong","title":"Recipient privacy"},{"location":"technical-specs/#amount-privacy","text":"ring confidential transactions assurance: strong","title":"Amount privacy"},{"location":"technical-specs/#ip-address-privacy","text":"For the full node ( monerod ): dandelion++ assurance: won't protect against ISP/VPN provider, won't protect against the very first remote node in Dandellion++ protocol for the full protection user must manually wrap monerod with Tor For the wallet ( monero-wallet-gui or monero-wallet-cli ): typically wallet runs on the same machine as full node so there is no risk if wallet connects to remote full node, there is no IP protection by default user must manually wrap wallet with Tor","title":"IP address privacy"},{"location":"accepting-monero/overview/","text":"Accepting Monero for Businesses \u00b6 This is for businesses that want to accept Monero in an automated way, including: merchants service providers exchanges We prepared a comparison of available venues to accept Monero, as of 2019-01-28: Accepting Monero as a Business - Comparison Matrix","title":"Overview"},{"location":"accepting-monero/overview/#accepting-monero-for-businesses","text":"This is for businesses that want to accept Monero in an automated way, including: merchants service providers exchanges We prepared a comparison of available venues to accept Monero, as of 2019-01-28: Accepting Monero as a Business - Comparison Matrix","title":"Accepting Monero for Businesses"},{"location":"cryptography/base58/","text":"Base58 \u00b6 Base58 is a binary-to-text encoding scheme. It is similar to Base64 but has been modified to avoid both non-alphanumeric characters and letters which might look ambiguous when printed. The characters excluded in relation to Base64 are: IOl0+/ Base58 does not strictly specify the format. This results in some implementations being incompatible with others, for example with regard to alphabet order. For details, see Wikipedia . Base58 in Monero \u00b6 Monero has its own variant of Base58. In Monero the Base58 encoding is performed in 8-byte blocks, except the last block which is the remaining (8 or less) bytes . The 8-byte block converts to 11 or less Base58 characters. If the block converted to less then 11 characters, the output is padded with \"1\"s (0 in Base58). The final block is padded as well to whatever would be the maximum size of this number of bytes encoded in Base58. The advantage of Monero implementation is that output is of a fixed size which is not the case with plain Base58. The disadvantage is that default libraries won't work. For details, see reference C++ Base58 implementation and unofficial Python Base58 implementation.","title":"Base58"},{"location":"cryptography/base58/#base58","text":"Base58 is a binary-to-text encoding scheme. It is similar to Base64 but has been modified to avoid both non-alphanumeric characters and letters which might look ambiguous when printed. The characters excluded in relation to Base64 are: IOl0+/ Base58 does not strictly specify the format. This results in some implementations being incompatible with others, for example with regard to alphabet order. For details, see Wikipedia .","title":"Base58"},{"location":"cryptography/base58/#base58-in-monero","text":"Monero has its own variant of Base58. In Monero the Base58 encoding is performed in 8-byte blocks, except the last block which is the remaining (8 or less) bytes . The 8-byte block converts to 11 or less Base58 characters. If the block converted to less then 11 characters, the output is padded with \"1\"s (0 in Base58). The final block is padded as well to whatever would be the maximum size of this number of bytes encoded in Base58. The advantage of Monero implementation is that output is of a fixed size which is not the case with plain Base58. The disadvantage is that default libraries won't work. For details, see reference C++ Base58 implementation and unofficial Python Base58 implementation.","title":"Base58 in Monero"},{"location":"cryptography/introduction/","text":"Cryptography in Monero \u00b6 Monero uses a wide variety of cryptographic primitives for various use cases. Comparing to altcoins, Monero cryptography is considered conservative, sound and robust. Comparing to Bitcoin, Monero uses much more primitives, and some of them are more advanced, especially those related to privacy and Proof of Work. Some choices are deliberately non-standard (for better or worse) - oftentimes a legacy of the CryptoNote protocol.","title":"Introduction"},{"location":"cryptography/introduction/#cryptography-in-monero","text":"Monero uses a wide variety of cryptographic primitives for various use cases. Comparing to altcoins, Monero cryptography is considered conservative, sound and robust. Comparing to Bitcoin, Monero uses much more primitives, and some of them are more advanced, especially those related to privacy and Proof of Work. Some choices are deliberately non-standard (for better or worse) - oftentimes a legacy of the CryptoNote protocol.","title":"Cryptography in Monero"},{"location":"cryptography/keccak-256/","text":"Keccak-256 Hash Function \u00b6 Monero employs Keccak as a hashing function. In most context specifically Keccak-256 is used, providing 32-byte hashes. Keccak is the leading hashing function, designed by non-NSA designers. Keccak won NIST competition to become the official SHA3. Use Cases \u00b6 Monero does not employ Keccak for Proof-of-Work. Instead, Keccak is used for: random number generator block hashing transaction hashing stealth address private key image (for double spend protection) public address checksum RingCT multisig bulletproofs ...and likely a few other things. Keccak-256 vs SHA3-256 \u00b6 SHA3-256 is Keccak-256, except NIST changed padding. For that reason original Keccak-256 gives in a different hash value than NIST SHA3-256. Monero uses original Keccak-256. The NIST standard was only published on August 2015, while Monero went live on 18 April 2014. Reference \u00b6 Keccak source code used in Monero SHA3 on Wikipedia Keccak-256 vs SHA3-256 explained on Ethereum stackexchange Online tool to calculate Keccak-256 and SHA3-256","title":"Keccak-256"},{"location":"cryptography/keccak-256/#keccak-256-hash-function","text":"Monero employs Keccak as a hashing function. In most context specifically Keccak-256 is used, providing 32-byte hashes. Keccak is the leading hashing function, designed by non-NSA designers. Keccak won NIST competition to become the official SHA3.","title":"Keccak-256 Hash Function"},{"location":"cryptography/keccak-256/#use-cases","text":"Monero does not employ Keccak for Proof-of-Work. Instead, Keccak is used for: random number generator block hashing transaction hashing stealth address private key image (for double spend protection) public address checksum RingCT multisig bulletproofs ...and likely a few other things.","title":"Use Cases"},{"location":"cryptography/keccak-256/#keccak-256-vs-sha3-256","text":"SHA3-256 is Keccak-256, except NIST changed padding. For that reason original Keccak-256 gives in a different hash value than NIST SHA3-256. Monero uses original Keccak-256. The NIST standard was only published on August 2015, while Monero went live on 18 April 2014.","title":"Keccak-256 vs SHA3-256"},{"location":"cryptography/keccak-256/#reference","text":"Keccak source code used in Monero SHA3 on Wikipedia Keccak-256 vs SHA3-256 explained on Ethereum stackexchange Online tool to calculate Keccak-256 and SHA3-256","title":"Reference"},{"location":"cryptography/prng/","text":"Monero Pseudorandom Number Generator \u00b6 Monero uses PRNG based on the Keccak hashing function. Basically, output of the previous hashing round is input for the next one. The initial seed comes from entropy sources provided by operating system. On Linux and MacOS the seed comes from /dev/urandom . On Windows the WinAPI CryptGenRandom call is used for seeding. There is no reseeding. Caveats \u00b6 This concerns the reference C++ implementation of Monero. Please note there are many alternative implementations of private key generation, including JavaScript, Python, Android/Java. These should be researched case by case for correctness. In Monero source code you can also find libsodium based random bytes generator. It is part of the embedded library and apparently is not used in actual Monero code. Reference \u00b6 Source code StackExchange answer","title":"PRNG"},{"location":"cryptography/prng/#monero-pseudorandom-number-generator","text":"Monero uses PRNG based on the Keccak hashing function. Basically, output of the previous hashing round is input for the next one. The initial seed comes from entropy sources provided by operating system. On Linux and MacOS the seed comes from /dev/urandom . On Windows the WinAPI CryptGenRandom call is used for seeding. There is no reseeding.","title":"Monero Pseudorandom Number Generator"},{"location":"cryptography/prng/#caveats","text":"This concerns the reference C++ implementation of Monero. Please note there are many alternative implementations of private key generation, including JavaScript, Python, Android/Java. These should be researched case by case for correctness. In Monero source code you can also find libsodium based random bytes generator. It is part of the embedded library and apparently is not used in actual Monero code.","title":"Caveats"},{"location":"cryptography/prng/#reference","text":"Source code StackExchange answer","title":"Reference"},{"location":"cryptography/asymmetric/edwards25519/","text":"Edwards25519 Elliptic Curve \u00b6 Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. Note This article is only about the underlying curve. Public key derivation and signing algorithm will be treated separately. Monero employs edwards25519 elliptic curve as a basis for its key pair generation. The curve comes from the Ed25519 signature scheme. While Monero takes the curve unchanged, it does not exactly follow rest of the Ed25519. The edwards25519 curve is birationally equivalent to Curve25519 . Definition \u00b6 This is the standard edwards25519 curve definition, no Monero specific stuff here, except the naming convention. The convention comes from the CryptoNote whitepaper and is widely used in Monero literature. Curve equation \u00b6 \u2212x^2 + y^2 = 1 \u2212 (121665/121666) * x^2 * y^2 Note: curve is in two dimensions (nothing fancy, like all the curves is high school) curve is mirrored below y axis due to y^2 part of the equation (not a polynomial) Base point: G \u00b6 The base point is a specific point on the curve. It is used as a basis for further calculations. It is an arbitrary choice by the curve authors, just to standardize the scheme. Note that it is enough to specify the y value and the sign of the x value. That's because the specific x can be calculated from the curve equation. G = (x, 4/5) # take the point with the positive x # The hex representation of the base point 5866666666666666666666666666666666666666666666666666666666666666 Prime order of the base point: l \u00b6 In layment terms, the \"canvas\" where the curve is drawn is assumed to have a finite \"resolution\", so point coordinates must \"wrap around\" at some point. This is achieved by modulo the l value (lowercase L). In other words, the l defines the maximum scalar we can use. l = 2^252 + 27742317777372353535851937790883648493 # => 7237005577332262213973186563042994240857116359379907606001950938285454250989 The l is a prime number specified by the curve authors. In practice this is the private key's strength. Total number of points on the curve \u00b6 The total number of points on the curve is also a prime number: q = 2^255 - 19 In practice not all points are \"useful\" and so the private key strength is limited to l describe above. Implementation \u00b6 Monero uses (apparently modified) Ref10 implementation by Daniel J. Bernstein. Reference \u00b6 A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography RFC 8032 defining EdDSA Understanding Monero Cryptography - excellent writeup by Luigi StackOverflow answer Python implementation - not the reference one but easier to understand Encoding point to hex EdDSA on Wikipedia","title":"Edwards25519 curve"},{"location":"cryptography/asymmetric/edwards25519/#edwards25519-elliptic-curve","text":"Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. Note This article is only about the underlying curve. Public key derivation and signing algorithm will be treated separately. Monero employs edwards25519 elliptic curve as a basis for its key pair generation. The curve comes from the Ed25519 signature scheme. While Monero takes the curve unchanged, it does not exactly follow rest of the Ed25519. The edwards25519 curve is birationally equivalent to Curve25519 .","title":"Edwards25519 Elliptic Curve"},{"location":"cryptography/asymmetric/edwards25519/#definition","text":"This is the standard edwards25519 curve definition, no Monero specific stuff here, except the naming convention. The convention comes from the CryptoNote whitepaper and is widely used in Monero literature.","title":"Definition"},{"location":"cryptography/asymmetric/edwards25519/#curve-equation","text":"\u2212x^2 + y^2 = 1 \u2212 (121665/121666) * x^2 * y^2 Note: curve is in two dimensions (nothing fancy, like all the curves is high school) curve is mirrored below y axis due to y^2 part of the equation (not a polynomial)","title":"Curve equation"},{"location":"cryptography/asymmetric/edwards25519/#base-point-g","text":"The base point is a specific point on the curve. It is used as a basis for further calculations. It is an arbitrary choice by the curve authors, just to standardize the scheme. Note that it is enough to specify the y value and the sign of the x value. That's because the specific x can be calculated from the curve equation. G = (x, 4/5) # take the point with the positive x # The hex representation of the base point 5866666666666666666666666666666666666666666666666666666666666666","title":"Base point: G"},{"location":"cryptography/asymmetric/edwards25519/#prime-order-of-the-base-point-l","text":"In layment terms, the \"canvas\" where the curve is drawn is assumed to have a finite \"resolution\", so point coordinates must \"wrap around\" at some point. This is achieved by modulo the l value (lowercase L). In other words, the l defines the maximum scalar we can use. l = 2^252 + 27742317777372353535851937790883648493 # => 7237005577332262213973186563042994240857116359379907606001950938285454250989 The l is a prime number specified by the curve authors. In practice this is the private key's strength.","title":"Prime order of the base point: l"},{"location":"cryptography/asymmetric/edwards25519/#total-number-of-points-on-the-curve","text":"The total number of points on the curve is also a prime number: q = 2^255 - 19 In practice not all points are \"useful\" and so the private key strength is limited to l describe above.","title":"Total number of points on the curve"},{"location":"cryptography/asymmetric/edwards25519/#implementation","text":"Monero uses (apparently modified) Ref10 implementation by Daniel J. Bernstein.","title":"Implementation"},{"location":"cryptography/asymmetric/edwards25519/#reference","text":"A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography RFC 8032 defining EdDSA Understanding Monero Cryptography - excellent writeup by Luigi StackOverflow answer Python implementation - not the reference one but easier to understand Encoding point to hex EdDSA on Wikipedia","title":"Reference"},{"location":"cryptography/asymmetric/introduction/","text":"Asymmetric Cryptography in Monero \u00b6 Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. Before we get to Monero specific stuff, a little bit of context. We are talking asymmetric cryptography here. The \"asymmetric\" simply means the are two keys: the private key (used primarily for signing data and for decrypting data) the public key (used primarily for signature verification and encrypting data) This is in contrast to symmetric cryptography which uses a single key. This key is a secret shared among the parties. Historically, asymmetric cryptography was based on the problem of factorization of a very large integers back into prime numbers (which is practically impossible for large enough integers). Recently, asymmetric cryptography is based on a mathematical notion of elliptic curves. Edwards25519 is a specific, well researched and standardized elliptic curve used in Monero.","title":"Introduction"},{"location":"cryptography/asymmetric/introduction/#asymmetric-cryptography-in-monero","text":"Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. Before we get to Monero specific stuff, a little bit of context. We are talking asymmetric cryptography here. The \"asymmetric\" simply means the are two keys: the private key (used primarily for signing data and for decrypting data) the public key (used primarily for signature verification and encrypting data) This is in contrast to symmetric cryptography which uses a single key. This key is a secret shared among the parties. Historically, asymmetric cryptography was based on the problem of factorization of a very large integers back into prime numbers (which is practically impossible for large enough integers). Recently, asymmetric cryptography is based on a mathematical notion of elliptic curves. Edwards25519 is a specific, well researched and standardized elliptic curve used in Monero.","title":"Asymmetric Cryptography in Monero"},{"location":"cryptography/asymmetric/key-image/","text":"Monero Private Key Image \u00b6 Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. Private key image serves to detect double spending attempts. In Monero funds are always sent to a one-time public key P . Related one-time private key x is specific to unspent output. As output can be spent only once (in whole), the related private key can be used only once as well. Thus, specific private key image I being present on the blockchain means that related output was already spent, and subsequent attempts must not be allowed. This whole scheme is necessary because Monero uses Ring Signatures which make it impossible to know whom exactly signed the transaction. This is why a simple Bitcoin-like double spending check wouldn't work here. Definition \u00b6 I = x*Hp(P) Where: I - private key image (or \"key image\" for short) x - one-time private key used to unlock an unspent output P - one-time public key of an unspent output Hp() - hash function accepting an EC point as an argument The P comes from this: P = xG Where G is the edwards25519 base point. Substitute P with xG and we get: I = x*Hp(xG) The key image I is a one-way function of the private key x . Reference \u00b6 StackExchange answer Another SE answer Critical bug regarding key image verification that was once present in Monero","title":"Key image"},{"location":"cryptography/asymmetric/key-image/#monero-private-key-image","text":"Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. Private key image serves to detect double spending attempts. In Monero funds are always sent to a one-time public key P . Related one-time private key x is specific to unspent output. As output can be spent only once (in whole), the related private key can be used only once as well. Thus, specific private key image I being present on the blockchain means that related output was already spent, and subsequent attempts must not be allowed. This whole scheme is necessary because Monero uses Ring Signatures which make it impossible to know whom exactly signed the transaction. This is why a simple Bitcoin-like double spending check wouldn't work here.","title":"Monero Private Key Image"},{"location":"cryptography/asymmetric/key-image/#definition","text":"I = x*Hp(P) Where: I - private key image (or \"key image\" for short) x - one-time private key used to unlock an unspent output P - one-time public key of an unspent output Hp() - hash function accepting an EC point as an argument The P comes from this: P = xG Where G is the edwards25519 base point. Substitute P with xG and we get: I = x*Hp(xG) The key image I is a one-way function of the private key x .","title":"Definition"},{"location":"cryptography/asymmetric/key-image/#reference","text":"StackExchange answer Another SE answer Critical bug regarding key image verification that was once present in Monero","title":"Reference"},{"location":"cryptography/asymmetric/private-key/","text":"Private Keys in Monero \u00b6 Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. In Monero, the root private key is generated randomly . Other private keys are derived deterministically from the root private key. Private key must be kept secret. Private key is a large integer impossible to guess, like: 108555083659983933209597798445644913612440610624038028786991485007418559037440 Private key is 256 bits long. Private key is a scalar , meaning it is a single value. In equations scalars are represented by lowercase letters . Relation to Ed25519 \u00b6 Being simply a random integer, private key is not specific to any particular asymmetric cryptography scheme. In context of Monero EC cryptography the private key is a number the base point G is multiplied by. The result of the multiplication is the public key P (another point on the curve). Multiplication of a point by a number has a very special definition in EC cryptography. See this this guide for details. Key strength \u00b6 Before deriving the public key, private key is subject to modulo l , where l is the maximum scalar allowed by the edwards25519 curve . The l is on the order of 2^252, so the effective key strength is technically 252 bits, not 256 bits. This is standard for EC cryptography and is more of a cosmetic nuance than any concern. Encoding \u00b6 In user-facing contexts, the private key integer is: Taken modulo l to avoid malleability Put as array of 32 bytes in a little-endian direction (the first byte is the least significant) Converted to hexadecimal form, like: b3588a87056fb21dc4d052d59e83b54293882e646b543c29478e4cf45c28a402 Private spend key \u00b6 Private spend key is used to spend moneros. More specifically, it is used to build one-time private keys which allow to spend related outputs. Private view key \u00b6 Private view key is used to recognize your incoming transactions on the otherwise opaque blockchain. One-time private keys \u00b6 One-time private key like construct is used in stealth addresses .","title":"Private keys"},{"location":"cryptography/asymmetric/private-key/#private-keys-in-monero","text":"Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. In Monero, the root private key is generated randomly . Other private keys are derived deterministically from the root private key. Private key must be kept secret. Private key is a large integer impossible to guess, like: 108555083659983933209597798445644913612440610624038028786991485007418559037440 Private key is 256 bits long. Private key is a scalar , meaning it is a single value. In equations scalars are represented by lowercase letters .","title":"Private Keys in Monero"},{"location":"cryptography/asymmetric/private-key/#relation-to-ed25519","text":"Being simply a random integer, private key is not specific to any particular asymmetric cryptography scheme. In context of Monero EC cryptography the private key is a number the base point G is multiplied by. The result of the multiplication is the public key P (another point on the curve). Multiplication of a point by a number has a very special definition in EC cryptography. See this this guide for details.","title":"Relation to Ed25519"},{"location":"cryptography/asymmetric/private-key/#key-strength","text":"Before deriving the public key, private key is subject to modulo l , where l is the maximum scalar allowed by the edwards25519 curve . The l is on the order of 2^252, so the effective key strength is technically 252 bits, not 256 bits. This is standard for EC cryptography and is more of a cosmetic nuance than any concern.","title":"Key strength"},{"location":"cryptography/asymmetric/private-key/#encoding","text":"In user-facing contexts, the private key integer is: Taken modulo l to avoid malleability Put as array of 32 bytes in a little-endian direction (the first byte is the least significant) Converted to hexadecimal form, like: b3588a87056fb21dc4d052d59e83b54293882e646b543c29478e4cf45c28a402","title":"Encoding"},{"location":"cryptography/asymmetric/private-key/#private-spend-key","text":"Private spend key is used to spend moneros. More specifically, it is used to build one-time private keys which allow to spend related outputs.","title":"Private spend key"},{"location":"cryptography/asymmetric/private-key/#private-view-key","text":"Private view key is used to recognize your incoming transactions on the otherwise opaque blockchain.","title":"Private view key"},{"location":"cryptography/asymmetric/private-key/#one-time-private-keys","text":"One-time private key like construct is used in stealth addresses .","title":"One-time private keys"},{"location":"cryptography/asymmetric/public-key/","text":"Public Keys in Monero \u00b6 Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. Public key is deterministically derived from private key based on edwards25519 curve with a little Monero-specific twist. Public key is meant to be shared. Assuming correct implementation, it is not practically possible to recover private key from public key. Public key is a point (x,y) on the elliptic curve. In equations points are represented by uppercase letters . In user-facing contexts, public key is encoded in a little-endian hexadecimal form, like: 016a941812293cf9a86071060fb090ab38d67945e659968cb8cf30e1bc725683 Deriving public key \u00b6 Say: P is a public key x is a private key G is a \"base point\"; this is simply a constant specific to edwards25519 ; this point lies on the elliptic curve Then: P = xG The public key is simply the base point (G) multiplied by the private key (x). Multiplying the point is adding the point to itself a number of times. However, the addition is not a simple vector addition. It has a very specific definition nicely described in this article . What is important is that result of addition is always a point on the curve. For example, G + G is another point on the curve. Use cases \u00b6 Monero address is composed of public spend key and public view key. These keys are used to build stealth addresses to receive payments.","title":"Public keys"},{"location":"cryptography/asymmetric/public-key/#public-keys-in-monero","text":"Note Author is nowhere close to being a cryptographer. Be sceptical on accuracy. Public key is deterministically derived from private key based on edwards25519 curve with a little Monero-specific twist. Public key is meant to be shared. Assuming correct implementation, it is not practically possible to recover private key from public key. Public key is a point (x,y) on the elliptic curve. In equations points are represented by uppercase letters . In user-facing contexts, public key is encoded in a little-endian hexadecimal form, like: 016a941812293cf9a86071060fb090ab38d67945e659968cb8cf30e1bc725683","title":"Public Keys in Monero"},{"location":"cryptography/asymmetric/public-key/#deriving-public-key","text":"Say: P is a public key x is a private key G is a \"base point\"; this is simply a constant specific to edwards25519 ; this point lies on the elliptic curve Then: P = xG The public key is simply the base point (G) multiplied by the private key (x). Multiplying the point is adding the point to itself a number of times. However, the addition is not a simple vector addition. It has a very specific definition nicely described in this article . What is important is that result of addition is always a point on the curve. For example, G + G is another point on the curve.","title":"Deriving public key"},{"location":"cryptography/asymmetric/public-key/#use-cases","text":"Monero address is composed of public spend key and public view key. These keys are used to build stealth addresses to receive payments.","title":"Use cases"},{"location":"infrastructure/monero-pulse/","text":"MoneroPulse \u00b6 What is MoneroPulse? \u00b6 MoneroPulse is infrastructure for emergency checkpointing the blockchain. It aims to mitigate chain-splits resulting from consensus bugs (like this one from 2014 ). Effectively, MoneroPulse operators can publish which fork they consider the valid one. Technically, the \"checkpoint\" they publish is a block hash and the block height. By default, Monero full node will simply warn users when MoneroPulse checkpoint does not match the fork it is on. The error will be present in the log and on the console in red. Users are free to discard it. Ideally though, users should consult community on what is going on, and make educated decission on whether to follow the checkpoint-compatible fork or the default fork. Users can also set auto-enforcing the checkpoints via --enforce-dns-checkpointing option to monerod . In case of mismatch, monerod will rollback the local blockchain by a few blocks. Eventually, the alternative (\"fixed\") fork will get heavier and the node will follow it, leaving the \"invalid\" fork behind. This option is recommended for unattended full nodes. Summing up, MoneroPulse is emergency checkpointing mechanism. It is opt-in for the users. MoneroPulse is DNS based \u00b6 The ckeckpoints are stored as DNS TXT records for domains owned by MoneroPulse operators. To get the idea you can access the checkpoints manually with any DNS client: Try: dig -t txt checkpoints.moneropulse.net +dnssec Result: (cut) ;; ANSWER SECTION: checkpoints.moneropulse.net. 299 IN TXT \"1288616:875ac1bc7aa6c5eedc5410abb9c694034f9e7f79dce4c60698baf37009cb6365\" checkpoints.moneropulse.net. 299 IN TXT \"375000:c80c23e387585e12ffb6649d678e9ba328181797b9583a6d8911b77e25375737\" checkpoints.moneropulse.net. 299 IN TXT \"325000:4260d56368267bc2a70dd58d73c5ecf23b4e4d96e63c29a868e4a679b0741c7f\" checkpoints.moneropulse.net. 299 IN TXT \"233000:4f69bec2af6c0852412bdd10c19e6af10c8d738fe2618b5511a98efd03ab477e\" checkpoints.moneropulse.net. 299 IN TXT \"450000:4d098b511ca97723e81737c448343cfd4e6dadb3d8a0e757c6e4d595e6e48357\" checkpoints.moneropulse.net. 299 IN TXT \"250000:f59d31839bd909ec8830b4f7f66ff213f0bd006334c8523daee452725e5c7a79\" checkpoints.moneropulse.net. 299 IN TXT \"550000:c2e80a636438bd9f7a7ab432a6ad297e35540d80ff5b868bca098124cad2ff8c\" checkpoints.moneropulse.net. 299 IN TXT \"650000:1d567f2b491324375a825895c5e7b52857b38e4fed0e42c40909c2d52240b4e0\" checkpoints.moneropulse.net. 299 IN TXT \"800000:2ced10aa85357ab6c14bb12b6b56d1dde28940820dda30911b73a5cc9a301760\" checkpoints.moneropulse.net. 299 IN TXT \"850000:00e2b557dde9fd4a9e2e3dd7ddac962f5ca475eb1095bc50aa757fd1218ab0a5\" checkpoints.moneropulse.net. 299 IN TXT \"900000:d9958d0e7dcf91a5a7b11de225927bf7efc6eb26240315ce12372be902cc1337\" checkpoints.moneropulse.net. 299 IN TXT \"913193:5292d5d56f6ba4de33a58d9a34d263e2cb3c6fee0aed2286fd4ac7f36d53c85f\" checkpoints.moneropulse.net. 299 IN TXT \"913269:f8302e6b8ba1c49aad9a854b8d6c79d8272c6239dcbba5a75ed0784c1d4f56a1\" checkpoints.moneropulse.net. 299 IN TXT \"350000:74da79f6a136969abd6364bd3d37af273c408d6471e8ab598e80569b42415f86\" checkpoints.moneropulse.net. 299 IN TXT \"400000:1b2b0e7a30e59691491529a3d506d1ba3d6052d0f6b52198b7330b28a6f1b6ac\" checkpoints.moneropulse.net. 299 IN TXT \"500000:2428f0dbe49796be05ed81b347f53e1f7f44aed0abf641446ec2b94cae066b02\" checkpoints.moneropulse.net. 299 IN TXT \"600000:f5828ebf7d7d1cb61762c4dfe3ccf4ecab2e1aad23e8113668d981713b7a54c5\" checkpoints.moneropulse.net. 299 IN TXT \"700000:12be9b3d210b93f574d2526abb9c1ab2a881b479131fd0d4f7dac93875f503cd\" checkpoints.moneropulse.net. 299 IN TXT \"300000:0c1cd46df6ccff90ec4ab493281f2583c344cd62216c427628990fe9db1bb8b6\" checkpoints.moneropulse.net. 299 IN RRSIG TXT 13 3 300 20180922151845 20180920131845 35273 moneropulse.net. 8CyqtsM2f9o6OHZYqtGPVf+8gcFM+eUyoMi29LlkcLtK1AXbZlKqCcdN NvdvB+4OzepmpTanSc+TbLWbz/sIzA== Please note the DNSSEC signature entry at the end. The checkpoints are mirrored on several DNS servers: Mainnet: checkpoints.moneropulse.se checkpoints.moneropulse.org checkpoints.moneropulse.net checkpoints.moneropulse.co Stagenet: stagenetpoints.moneropulse.se stagenetpoints.moneropulse.org stagenetpoints.moneropulse.net stagenetpoints.moneropulse.co Testnet: testpoints.moneropulse.se testpoints.moneropulse.org testpoints.moneropulse.net testpoints.moneropulse.co MoneroPulse as attack vector \u00b6 It is worth noting that MoneroPulse does not produce blocks and cannot split the chain on its own. It only suggests the valid fork. Should MoneroPulse got entirely compromised, attacker could stop all auto-enforcing nodes from advancing, by feeding them with the fake checkpoint. This is partially mitigated by DNSSEC and by operating multiple domains. Monero expects checkpoints are consistent across domains. Thus, compromising a single domain or registrar should not lead to any disruption. MoneroPulse also increases the say of its operators in case of possible contentious hard forks. While well intended, this effectively centralizes more power in hands of core developers, or whomever is at the time running MoneroPulse infrastructure. Who are MoneroPulse operators? \u00b6 MoneroPulse is operated by selected core developers. Fixing \"WARNING: no two valid MoneroPulse DNS checkpoint records were received\" \u00b6 This means DNS server you are using does not ackonwledge the +dnssec flag necessary for securely query for checkpoints. By default, your operating system will use DNS server provided by your Internet Service Provider. To fix this warning, change your DNS server either system-wide in your network configuration, or specifically for monerod . Many people find Google's or Cloudflare's DNS servers superior to those offered by their ISPs. Using Google DNS: DNS_PUBLIC=tcp://8.8.8.8 ./monerod Using Cloudflare DNS: DNS_PUBLIC=tcp://1.1.1.1 ./monerod Reference \u00b6 StackExchange answer Reddit answer Monero source code","title":"MoneroPulse"},{"location":"infrastructure/monero-pulse/#moneropulse","text":"","title":"MoneroPulse"},{"location":"infrastructure/monero-pulse/#what-is-moneropulse","text":"MoneroPulse is infrastructure for emergency checkpointing the blockchain. It aims to mitigate chain-splits resulting from consensus bugs (like this one from 2014 ). Effectively, MoneroPulse operators can publish which fork they consider the valid one. Technically, the \"checkpoint\" they publish is a block hash and the block height. By default, Monero full node will simply warn users when MoneroPulse checkpoint does not match the fork it is on. The error will be present in the log and on the console in red. Users are free to discard it. Ideally though, users should consult community on what is going on, and make educated decission on whether to follow the checkpoint-compatible fork or the default fork. Users can also set auto-enforcing the checkpoints via --enforce-dns-checkpointing option to monerod . In case of mismatch, monerod will rollback the local blockchain by a few blocks. Eventually, the alternative (\"fixed\") fork will get heavier and the node will follow it, leaving the \"invalid\" fork behind. This option is recommended for unattended full nodes. Summing up, MoneroPulse is emergency checkpointing mechanism. It is opt-in for the users.","title":"What is MoneroPulse?"},{"location":"infrastructure/monero-pulse/#moneropulse-is-dns-based","text":"The ckeckpoints are stored as DNS TXT records for domains owned by MoneroPulse operators. To get the idea you can access the checkpoints manually with any DNS client: Try: dig -t txt checkpoints.moneropulse.net +dnssec Result: (cut) ;; ANSWER SECTION: checkpoints.moneropulse.net. 299 IN TXT \"1288616:875ac1bc7aa6c5eedc5410abb9c694034f9e7f79dce4c60698baf37009cb6365\" checkpoints.moneropulse.net. 299 IN TXT \"375000:c80c23e387585e12ffb6649d678e9ba328181797b9583a6d8911b77e25375737\" checkpoints.moneropulse.net. 299 IN TXT \"325000:4260d56368267bc2a70dd58d73c5ecf23b4e4d96e63c29a868e4a679b0741c7f\" checkpoints.moneropulse.net. 299 IN TXT \"233000:4f69bec2af6c0852412bdd10c19e6af10c8d738fe2618b5511a98efd03ab477e\" checkpoints.moneropulse.net. 299 IN TXT \"450000:4d098b511ca97723e81737c448343cfd4e6dadb3d8a0e757c6e4d595e6e48357\" checkpoints.moneropulse.net. 299 IN TXT \"250000:f59d31839bd909ec8830b4f7f66ff213f0bd006334c8523daee452725e5c7a79\" checkpoints.moneropulse.net. 299 IN TXT \"550000:c2e80a636438bd9f7a7ab432a6ad297e35540d80ff5b868bca098124cad2ff8c\" checkpoints.moneropulse.net. 299 IN TXT \"650000:1d567f2b491324375a825895c5e7b52857b38e4fed0e42c40909c2d52240b4e0\" checkpoints.moneropulse.net. 299 IN TXT \"800000:2ced10aa85357ab6c14bb12b6b56d1dde28940820dda30911b73a5cc9a301760\" checkpoints.moneropulse.net. 299 IN TXT \"850000:00e2b557dde9fd4a9e2e3dd7ddac962f5ca475eb1095bc50aa757fd1218ab0a5\" checkpoints.moneropulse.net. 299 IN TXT \"900000:d9958d0e7dcf91a5a7b11de225927bf7efc6eb26240315ce12372be902cc1337\" checkpoints.moneropulse.net. 299 IN TXT \"913193:5292d5d56f6ba4de33a58d9a34d263e2cb3c6fee0aed2286fd4ac7f36d53c85f\" checkpoints.moneropulse.net. 299 IN TXT \"913269:f8302e6b8ba1c49aad9a854b8d6c79d8272c6239dcbba5a75ed0784c1d4f56a1\" checkpoints.moneropulse.net. 299 IN TXT \"350000:74da79f6a136969abd6364bd3d37af273c408d6471e8ab598e80569b42415f86\" checkpoints.moneropulse.net. 299 IN TXT \"400000:1b2b0e7a30e59691491529a3d506d1ba3d6052d0f6b52198b7330b28a6f1b6ac\" checkpoints.moneropulse.net. 299 IN TXT \"500000:2428f0dbe49796be05ed81b347f53e1f7f44aed0abf641446ec2b94cae066b02\" checkpoints.moneropulse.net. 299 IN TXT \"600000:f5828ebf7d7d1cb61762c4dfe3ccf4ecab2e1aad23e8113668d981713b7a54c5\" checkpoints.moneropulse.net. 299 IN TXT \"700000:12be9b3d210b93f574d2526abb9c1ab2a881b479131fd0d4f7dac93875f503cd\" checkpoints.moneropulse.net. 299 IN TXT \"300000:0c1cd46df6ccff90ec4ab493281f2583c344cd62216c427628990fe9db1bb8b6\" checkpoints.moneropulse.net. 299 IN RRSIG TXT 13 3 300 20180922151845 20180920131845 35273 moneropulse.net. 8CyqtsM2f9o6OHZYqtGPVf+8gcFM+eUyoMi29LlkcLtK1AXbZlKqCcdN NvdvB+4OzepmpTanSc+TbLWbz/sIzA== Please note the DNSSEC signature entry at the end. The checkpoints are mirrored on several DNS servers: Mainnet: checkpoints.moneropulse.se checkpoints.moneropulse.org checkpoints.moneropulse.net checkpoints.moneropulse.co Stagenet: stagenetpoints.moneropulse.se stagenetpoints.moneropulse.org stagenetpoints.moneropulse.net stagenetpoints.moneropulse.co Testnet: testpoints.moneropulse.se testpoints.moneropulse.org testpoints.moneropulse.net testpoints.moneropulse.co","title":"MoneroPulse is DNS based"},{"location":"infrastructure/monero-pulse/#moneropulse-as-attack-vector","text":"It is worth noting that MoneroPulse does not produce blocks and cannot split the chain on its own. It only suggests the valid fork. Should MoneroPulse got entirely compromised, attacker could stop all auto-enforcing nodes from advancing, by feeding them with the fake checkpoint. This is partially mitigated by DNSSEC and by operating multiple domains. Monero expects checkpoints are consistent across domains. Thus, compromising a single domain or registrar should not lead to any disruption. MoneroPulse also increases the say of its operators in case of possible contentious hard forks. While well intended, this effectively centralizes more power in hands of core developers, or whomever is at the time running MoneroPulse infrastructure.","title":"MoneroPulse as attack vector"},{"location":"infrastructure/monero-pulse/#who-are-moneropulse-operators","text":"MoneroPulse is operated by selected core developers.","title":"Who are MoneroPulse operators?"},{"location":"infrastructure/monero-pulse/#fixing-warning-no-two-valid-moneropulse-dns-checkpoint-records-were-received","text":"This means DNS server you are using does not ackonwledge the +dnssec flag necessary for securely query for checkpoints. By default, your operating system will use DNS server provided by your Internet Service Provider. To fix this warning, change your DNS server either system-wide in your network configuration, or specifically for monerod . Many people find Google's or Cloudflare's DNS servers superior to those offered by their ISPs. Using Google DNS: DNS_PUBLIC=tcp://8.8.8.8 ./monerod Using Cloudflare DNS: DNS_PUBLIC=tcp://1.1.1.1 ./monerod","title":"Fixing \"WARNING: no two valid MoneroPulse DNS checkpoint records were received\""},{"location":"infrastructure/monero-pulse/#reference","text":"StackExchange answer Reddit answer Monero source code","title":"Reference"},{"location":"infrastructure/networks/","text":"Networks \u00b6 Monero offers three separate networks and blockchains: mainnet , stagenet and testnet . Every blockchain has its own genesis block and is entirely seperate from others. Also, corresponding p2p networks are separate. Mainnet \u00b6 Mainnet is the \"production\" network and blockchain. Mainnet is the only blockchain where XMR units have value. Mainnet is what people mean by default. Default TCP ports (listening): 18080 - p2p network 18081 - JSON-RPC server 18082 - ZMQ server Stagenet \u00b6 Stagenet is what you need to learn Monero safely. Stagenet is technically equivalent to mainnet, both in terms of features and consensus rules. Similar to mainnet, use the latest official Monero release to be compatible with stagenet. To get started: Connect your GUI or CLI to stagenet open node monero-stagenet.exan.tech:38081 Get free XMR from stagenet faucet 1 or stagenet faucet 2 Check the stagenet block explorer 1 or stagenet block explorer 2 Default TCP ports (listening): 38080 - p2p network 38081 - JSON-RPC server 38082 - ZMQ server Stagenet was introduced in March 2018 as part of Monero 0.12.0.0. Testnet \u00b6 As a normal user, use stagenet instead. Testnet is for developers. Testnet is the \"experimental\" network and blockchain where things get released long before mainnet. Testnet forks early and often. Most of the time you need to compile Monero from source to be compatible with testnet. Otherwise you will get stuck on the old not-forked version. To get started: Build Monero from source Connect your GUI or CLI to testnet open node monero-testnet.exan.tech:28081 Get free XMR from testnet faucet 1 or testnet faucet 2 Check the testnet block explorer 1 or testnet block explorer 2 Default TCP ports (listening): 28080 - p2p network 28081 - JSON-RPC server 28082 - ZMQ server Private Testnet \u00b6 You can also create your private version of the testnet. Private testnet gives more flexibility to arange for specific situations for developers. Check the private testnet guide . Why stagenet and testnet coins have no value? \u00b6 If mainnet and stagenet are technically equivalent then why only mainnet coins have value? This is simply the convention community embraced. Value only comes from a shared believe that mainnet coins will be accepted by other people in the future.","title":"Mainnet, stagenet, testnet"},{"location":"infrastructure/networks/#networks","text":"Monero offers three separate networks and blockchains: mainnet , stagenet and testnet . Every blockchain has its own genesis block and is entirely seperate from others. Also, corresponding p2p networks are separate.","title":"Networks"},{"location":"infrastructure/networks/#mainnet","text":"Mainnet is the \"production\" network and blockchain. Mainnet is the only blockchain where XMR units have value. Mainnet is what people mean by default. Default TCP ports (listening): 18080 - p2p network 18081 - JSON-RPC server 18082 - ZMQ server","title":"Mainnet"},{"location":"infrastructure/networks/#stagenet","text":"Stagenet is what you need to learn Monero safely. Stagenet is technically equivalent to mainnet, both in terms of features and consensus rules. Similar to mainnet, use the latest official Monero release to be compatible with stagenet. To get started: Connect your GUI or CLI to stagenet open node monero-stagenet.exan.tech:38081 Get free XMR from stagenet faucet 1 or stagenet faucet 2 Check the stagenet block explorer 1 or stagenet block explorer 2 Default TCP ports (listening): 38080 - p2p network 38081 - JSON-RPC server 38082 - ZMQ server Stagenet was introduced in March 2018 as part of Monero 0.12.0.0.","title":"Stagenet"},{"location":"infrastructure/networks/#testnet","text":"As a normal user, use stagenet instead. Testnet is for developers. Testnet is the \"experimental\" network and blockchain where things get released long before mainnet. Testnet forks early and often. Most of the time you need to compile Monero from source to be compatible with testnet. Otherwise you will get stuck on the old not-forked version. To get started: Build Monero from source Connect your GUI or CLI to testnet open node monero-testnet.exan.tech:28081 Get free XMR from testnet faucet 1 or testnet faucet 2 Check the testnet block explorer 1 or testnet block explorer 2 Default TCP ports (listening): 28080 - p2p network 28081 - JSON-RPC server 28082 - ZMQ server","title":"Testnet"},{"location":"infrastructure/networks/#private-testnet","text":"You can also create your private version of the testnet. Private testnet gives more flexibility to arange for specific situations for developers. Check the private testnet guide .","title":"Private Testnet"},{"location":"infrastructure/networks/#why-stagenet-and-testnet-coins-have-no-value","text":"If mainnet and stagenet are technically equivalent then why only mainnet coins have value? This is simply the convention community embraced. Value only comes from a shared believe that mainnet coins will be accepted by other people in the future.","title":"Why stagenet and testnet coins have no value?"},{"location":"infrastructure/tor-onion-p2p-seed-nodes/","text":"Tor onion seed nodes for Monero network \u00b6 When this is necessary? \u00b6 This is only necessary if you run a full node and you want to propagate locally-originating transactions over Tor (using tx-proxy option, see monerod reference ). This allows you to mask your IP (as transaction originator) against P2P network surveillence, on top of Monero's built-in Dandelion++. What are P2P seed nodes? \u00b6 Your monero daemon will discover other P2P nodes but it needs to start somewhere. These starting nodes are known as \"seed nodes\". For clearnet the seed nodes are hardcoded in the software so no configuration is needed. For the Tor network there are no hardcoded seed nodes. You must specify them manually by using the add-peer option in monero.conf . Config snippet \u00b6 These were tested working as of 2020-01-11. They are ran by volunteers and are not guaranteed to work or be maintained. See below how you can quickly test them. # monero.conf snippet # ... add-peer=moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18080 add-peer=monerozf6koypqrt.onion:18080 add-peer=zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083 # https://github.com/monero-project/monero/blob/master/src/p2p/net_node.inl add-peer=rno75kjcw3ein6i446sqby2xkyqjarb75oq36ah6c2mribyklzhurpyd.onion:28083 # it is mainnet despite the weird port add-peer=sqzrokz36lgkng2i2nlzgzns2ugcxqosflygsxbkybb4xn6gq3ouugqd.onion:18083 # very flaky, works 1 in 3 times add-peer=blzchctiibfjfvtukctsydhquucz2oajnxnfc5hh4ix35gyqjhdnaqqd.onion:18083 # full node by author of monerodocs.org # ... How to test onion seed nodes? \u00b6 You need Tor daemon installed and running on your laptop. You will also need torsocks command line tool that either comes with Tor or needs to be installed separately. Test using torsocks and telnet \u00b6 You need tor, torsocks and telnet installed. To test speficic onion: torsocks telnet moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion 18080 The expected output (domain resolution errors are fine): 1610372702 ERROR torsocks[11332]: Unable to resolve. Status reply: 4 (in socks5_recv_resolve_reply() at socks5.c:677) Trying 127.42.42.0... Connected to moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion. Escape character is '^]'. Test using torsocks and proxychains \u00b6 You need tor, torsocks and proxychains installed. To test specific onion: proxychains nmap -Pn -p 18080 moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion The expected output (example): [proxychains] Strict chain ... 127.0.0.1:9050 ... moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18080 ... OK Nmap scan report for moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion (224.0.0.1) Host is up (0.74s latency). rDNS record for 224.0.0.1: all-systems.mcast.net PORT STATE SERVICE 18080/tcp open unknown Not enough onion seed nodes \u00b6 The onion seed nodes are a scarce resource. Most nodes are only maintained temporarily by their authors. You can greatly contribute to Monero P2P network performance and resillience by running onion-enabled monero full node.","title":"Tor onion seed nodes"},{"location":"infrastructure/tor-onion-p2p-seed-nodes/#tor-onion-seed-nodes-for-monero-network","text":"","title":"Tor onion seed nodes for Monero network"},{"location":"infrastructure/tor-onion-p2p-seed-nodes/#when-this-is-necessary","text":"This is only necessary if you run a full node and you want to propagate locally-originating transactions over Tor (using tx-proxy option, see monerod reference ). This allows you to mask your IP (as transaction originator) against P2P network surveillence, on top of Monero's built-in Dandelion++.","title":"When this is necessary?"},{"location":"infrastructure/tor-onion-p2p-seed-nodes/#what-are-p2p-seed-nodes","text":"Your monero daemon will discover other P2P nodes but it needs to start somewhere. These starting nodes are known as \"seed nodes\". For clearnet the seed nodes are hardcoded in the software so no configuration is needed. For the Tor network there are no hardcoded seed nodes. You must specify them manually by using the add-peer option in monero.conf .","title":"What are P2P seed nodes?"},{"location":"infrastructure/tor-onion-p2p-seed-nodes/#config-snippet","text":"These were tested working as of 2020-01-11. They are ran by volunteers and are not guaranteed to work or be maintained. See below how you can quickly test them. # monero.conf snippet # ... add-peer=moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18080 add-peer=monerozf6koypqrt.onion:18080 add-peer=zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083 # https://github.com/monero-project/monero/blob/master/src/p2p/net_node.inl add-peer=rno75kjcw3ein6i446sqby2xkyqjarb75oq36ah6c2mribyklzhurpyd.onion:28083 # it is mainnet despite the weird port add-peer=sqzrokz36lgkng2i2nlzgzns2ugcxqosflygsxbkybb4xn6gq3ouugqd.onion:18083 # very flaky, works 1 in 3 times add-peer=blzchctiibfjfvtukctsydhquucz2oajnxnfc5hh4ix35gyqjhdnaqqd.onion:18083 # full node by author of monerodocs.org # ...","title":"Config snippet"},{"location":"infrastructure/tor-onion-p2p-seed-nodes/#how-to-test-onion-seed-nodes","text":"You need Tor daemon installed and running on your laptop. You will also need torsocks command line tool that either comes with Tor or needs to be installed separately.","title":"How to test onion seed nodes?"},{"location":"infrastructure/tor-onion-p2p-seed-nodes/#test-using-torsocks-and-telnet","text":"You need tor, torsocks and telnet installed. To test speficic onion: torsocks telnet moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion 18080 The expected output (domain resolution errors are fine): 1610372702 ERROR torsocks[11332]: Unable to resolve. Status reply: 4 (in socks5_recv_resolve_reply() at socks5.c:677) Trying 127.42.42.0... Connected to moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion. Escape character is '^]'.","title":"Test using torsocks and telnet"},{"location":"infrastructure/tor-onion-p2p-seed-nodes/#test-using-torsocks-and-proxychains","text":"You need tor, torsocks and proxychains installed. To test specific onion: proxychains nmap -Pn -p 18080 moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion The expected output (example): [proxychains] Strict chain ... 127.0.0.1:9050 ... moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18080 ... OK Nmap scan report for moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion (224.0.0.1) Host is up (0.74s latency). rDNS record for 224.0.0.1: all-systems.mcast.net PORT STATE SERVICE 18080/tcp open unknown","title":"Test using torsocks and proxychains"},{"location":"infrastructure/tor-onion-p2p-seed-nodes/#not-enough-onion-seed-nodes","text":"The onion seed nodes are a scarce resource. Most nodes are only maintained temporarily by their authors. You can greatly contribute to Monero P2P network performance and resillience by running onion-enabled monero full node.","title":"Not enough onion seed nodes"},{"location":"interacting/download-monero-binaries/","text":"Download Monero \u00b6 A single archive contains all you need to start using Monero (the full node and the wallet). We recommend downloading Monero binaries directly from GitHub: GUI + CLI: https://github.com/monero-project/monero-gui/releases CLI only: https://github.com/monero-project/monero/releases GUI is a graphical desktop wallet. CLI is a commandline desktop wallet. If you need more guidance check download Monero section on Monero website. It is critical to verify the signature of downloaded archive. Which version to download? \u00b6 Download the latest version matching your operating system and processor architecture. The CLI version is released earlier and is suitable for server deployments. The GUI version contains both CLI and GUI. It is preferable for end-users. All versions contain a full node and a wallet. Why prefer GitHub over getmonero.org? \u00b6 Binaries appear earlier on GitHub. On top of that, if you fail to properly verify the signature, GitHub is safer, simply because you don't need to trust a separate website to not be compromised. Obviously, you should still carefully verify the signature for each release. Signature verification is always the primary line of defense.","title":"Download"},{"location":"interacting/download-monero-binaries/#download-monero","text":"A single archive contains all you need to start using Monero (the full node and the wallet). We recommend downloading Monero binaries directly from GitHub: GUI + CLI: https://github.com/monero-project/monero-gui/releases CLI only: https://github.com/monero-project/monero/releases GUI is a graphical desktop wallet. CLI is a commandline desktop wallet. If you need more guidance check download Monero section on Monero website. It is critical to verify the signature of downloaded archive.","title":"Download Monero"},{"location":"interacting/download-monero-binaries/#which-version-to-download","text":"Download the latest version matching your operating system and processor architecture. The CLI version is released earlier and is suitable for server deployments. The GUI version contains both CLI and GUI. It is preferable for end-users. All versions contain a full node and a wallet.","title":"Which version to download?"},{"location":"interacting/download-monero-binaries/#why-prefer-github-over-getmoneroorg","text":"Binaries appear earlier on GitHub. On top of that, if you fail to properly verify the signature, GitHub is safer, simply because you don't need to trust a separate website to not be compromised. Obviously, you should still carefully verify the signature for each release. Signature verification is always the primary line of defense.","title":"Why prefer GitHub over getmonero.org?"},{"location":"interacting/monero-blockchain-export-reference/","text":"monero-blockchain-export - Reference \u00b6 Note Nowadays, there is little usage for raw blockchain export / import. In the past the p2p blockchain download was much slower. Back than blockchain.raw file was used to speed up the process of bootstrapping a node. Overview \u00b6 The tool dumps local blockchain to raw format, known as the blockchain.raw file. This could be useful if you want to process blockchain efficiently with your custom tools, as the raw format is probably easier to work with than Monero's custom lmdb database. The tool works on your local copy of the blockchain. It does not require monerod running. Syntax \u00b6 ./monero-blockchain-export [options] Example: ./monero-blockchain-export --help Running \u00b6 Go to directory where you unpacked Monero. ./monero-blockchain-export --stagenet --output-file=/tmp/blockchain.raw Options \u00b6 Help \u00b6 Option Description --help Enlist available options. Pick network \u00b6 Option Description (missing) By default monero-blockchain-export assumes mainnet . --stagenet Export stagenet blockchain. --testnet Export testnet blockchain. Logging \u00b6 Specifying the log file path is not supported. Option Description --log-level 0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0 . These are general presets and do not directly map to severity levels. For example, even with minimal 0 , you may see some most important INFO entries. Example: ./monero-blockchain-export --log-level=1 Input \u00b6 Option Description --data-dir Full path to data directory. This is where the blockchain, log files, and p2p network memory are stored. For defaults and details see data directory . --database , --db-type The default and only valid value is lmdb . Output \u00b6 Option Description --output-file Specify output file path. The default is $DATA_DIR/export/blockchain.raw . Example: ./monero-blockchain-export --output-file=/tmp/blockchain.raw --blocksdat Output in blocks.dat format. --block-stop Only export up to this block number. By default do the full export (value 0 ). Reference \u00b6 https://github.com/monero-project/monero/tree/master/src/blockchain_utilities","title":"monero-blockchain-export"},{"location":"interacting/monero-blockchain-export-reference/#monero-blockchain-export-reference","text":"Note Nowadays, there is little usage for raw blockchain export / import. In the past the p2p blockchain download was much slower. Back than blockchain.raw file was used to speed up the process of bootstrapping a node.","title":"monero-blockchain-export - Reference"},{"location":"interacting/monero-blockchain-export-reference/#overview","text":"The tool dumps local blockchain to raw format, known as the blockchain.raw file. This could be useful if you want to process blockchain efficiently with your custom tools, as the raw format is probably easier to work with than Monero's custom lmdb database. The tool works on your local copy of the blockchain. It does not require monerod running.","title":"Overview"},{"location":"interacting/monero-blockchain-export-reference/#syntax","text":"./monero-blockchain-export [options] Example: ./monero-blockchain-export --help","title":"Syntax"},{"location":"interacting/monero-blockchain-export-reference/#running","text":"Go to directory where you unpacked Monero. ./monero-blockchain-export --stagenet --output-file=/tmp/blockchain.raw","title":"Running"},{"location":"interacting/monero-blockchain-export-reference/#options","text":"","title":"Options"},{"location":"interacting/monero-blockchain-export-reference/#help","text":"Option Description --help Enlist available options.","title":"Help"},{"location":"interacting/monero-blockchain-export-reference/#pick-network","text":"Option Description (missing) By default monero-blockchain-export assumes mainnet . --stagenet Export stagenet blockchain. --testnet Export testnet blockchain.","title":"Pick network"},{"location":"interacting/monero-blockchain-export-reference/#logging","text":"Specifying the log file path is not supported. Option Description --log-level 0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0 . These are general presets and do not directly map to severity levels. For example, even with minimal 0 , you may see some most important INFO entries. Example: ./monero-blockchain-export --log-level=1","title":"Logging"},{"location":"interacting/monero-blockchain-export-reference/#input","text":"Option Description --data-dir Full path to data directory. This is where the blockchain, log files, and p2p network memory are stored. For defaults and details see data directory . --database , --db-type The default and only valid value is lmdb .","title":"Input"},{"location":"interacting/monero-blockchain-export-reference/#output","text":"Option Description --output-file Specify output file path. The default is $DATA_DIR/export/blockchain.raw . Example: ./monero-blockchain-export --output-file=/tmp/blockchain.raw --blocksdat Output in blocks.dat format. --block-stop Only export up to this block number. By default do the full export (value 0 ).","title":"Output"},{"location":"interacting/monero-blockchain-export-reference/#reference","text":"https://github.com/monero-project/monero/tree/master/src/blockchain_utilities","title":"Reference"},{"location":"interacting/monero-blockchain-import-reference/","text":"monero-blockchain-import - Reference \u00b6 Note Nowadays, there is little usage for raw blockchain export / import. In the past the p2p blockchain download was much slower. Back than blockchain.raw file was used to speed up download process of bootstrapping a node. Overview \u00b6 The tool imports bootstrap file blockchain.raw to your full node. This could be useful if you want to decouple download from verification for any reason (like testing performance in isolation). In this case, you may download the blockchain.raw file from https://downloads.getmonero.org/blockchain.raw . Ideally though, you should use your own trusted blockchain.raw file that you exported earlier. Please note that importing blockchain.raw will not speed up the process over syncing up from p2p network. This is because usual bottlenecks are disk IO and verification, not the download. The tool works on your local files. It does not require monerod running. Syntax \u00b6 ./monero-blockchain-import [options] Example: ./monero-blockchain-import --help Running \u00b6 Go to directory where you unpacked Monero. ./monero-blockchain-import --stagenet --output-file=/tmp/blockchain.raw Options \u00b6 Help \u00b6 Option Description --help Enlist available options. Pick network \u00b6 Option Description (missing) By default monero-blockchain-import assumes the mainnet blockchain. --stagenet Import stagenet blockchain. --testnet Import testnet blockchain. Logging \u00b6 Specifying the log file path is not supported. Option Description --log-level 0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0 . These are general presets and do not directly map to severity levels. For example, even with minimal 0 , you may see some most important INFO entries. Example: ./monero-blockchain-import --log-level=1 Input \u00b6 Option Description --input-file Full path to raw blockchain file. The default is $DATA_DIR/export/blockchain.raw . --block-stop Only import up to this block height. By default import all blocks (value 0 ). --pop-blocks Discard specified number of blocks from the tip of the bootstrapped blockchain. By default don't discard anything (value 0 ). Output \u00b6 Option Description --data-dir Full path to data directory. This is where the blockchain, log files, and p2p network memory are stored. For defaults and details see data directory . --count-blocks Count blocks in the bootstrap file and exit. --drop-hard-fork Whether to drop hard fork data. Off by default ( 0 ). --database The only valid value seems to be lmdb (the default). Performance \u00b6 Option Description --dangerous-unverified-import The safe default is to run verification (value 0 ). You can enable --dangerous-unverified-import if you are importing from your own and trusted blockchain.raw (which we assume was already verified). The \"dangerous\" mode will greatly speed up the process. --batch Whether to save to disk on an ongoing basis (the default, value 1 ) or maybe do everything in RAM and save everything in the end (value 0 ). No batching is only effective in combination with no verification ( --dangerous-unverified-import ). See also --batch-size . --batch-size How often to save to disk expressed in number of blocks. By default save every 5000 blocks (when verifying) or every 20000 blocks (when not verifying). Big batches are faster but require more RAM. --resume Resume from current height if output database already exists (the default, value 1 ). Changing to --resume=0 doesn't change much \u2014 existing blocks are skipped pretty quickly and the process is resumed anyway. Reference \u00b6 https://github.com/monero-project/monero/tree/master/src/blockchain_utilities","title":"monero-blockchain-import"},{"location":"interacting/monero-blockchain-import-reference/#monero-blockchain-import-reference","text":"Note Nowadays, there is little usage for raw blockchain export / import. In the past the p2p blockchain download was much slower. Back than blockchain.raw file was used to speed up download process of bootstrapping a node.","title":"monero-blockchain-import - Reference"},{"location":"interacting/monero-blockchain-import-reference/#overview","text":"The tool imports bootstrap file blockchain.raw to your full node. This could be useful if you want to decouple download from verification for any reason (like testing performance in isolation). In this case, you may download the blockchain.raw file from https://downloads.getmonero.org/blockchain.raw . Ideally though, you should use your own trusted blockchain.raw file that you exported earlier. Please note that importing blockchain.raw will not speed up the process over syncing up from p2p network. This is because usual bottlenecks are disk IO and verification, not the download. The tool works on your local files. It does not require monerod running.","title":"Overview"},{"location":"interacting/monero-blockchain-import-reference/#syntax","text":"./monero-blockchain-import [options] Example: ./monero-blockchain-import --help","title":"Syntax"},{"location":"interacting/monero-blockchain-import-reference/#running","text":"Go to directory where you unpacked Monero. ./monero-blockchain-import --stagenet --output-file=/tmp/blockchain.raw","title":"Running"},{"location":"interacting/monero-blockchain-import-reference/#options","text":"","title":"Options"},{"location":"interacting/monero-blockchain-import-reference/#help","text":"Option Description --help Enlist available options.","title":"Help"},{"location":"interacting/monero-blockchain-import-reference/#pick-network","text":"Option Description (missing) By default monero-blockchain-import assumes the mainnet blockchain. --stagenet Import stagenet blockchain. --testnet Import testnet blockchain.","title":"Pick network"},{"location":"interacting/monero-blockchain-import-reference/#logging","text":"Specifying the log file path is not supported. Option Description --log-level 0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0 . These are general presets and do not directly map to severity levels. For example, even with minimal 0 , you may see some most important INFO entries. Example: ./monero-blockchain-import --log-level=1","title":"Logging"},{"location":"interacting/monero-blockchain-import-reference/#input","text":"Option Description --input-file Full path to raw blockchain file. The default is $DATA_DIR/export/blockchain.raw . --block-stop Only import up to this block height. By default import all blocks (value 0 ). --pop-blocks Discard specified number of blocks from the tip of the bootstrapped blockchain. By default don't discard anything (value 0 ).","title":"Input"},{"location":"interacting/monero-blockchain-import-reference/#output","text":"Option Description --data-dir Full path to data directory. This is where the blockchain, log files, and p2p network memory are stored. For defaults and details see data directory . --count-blocks Count blocks in the bootstrap file and exit. --drop-hard-fork Whether to drop hard fork data. Off by default ( 0 ). --database The only valid value seems to be lmdb (the default).","title":"Output"},{"location":"interacting/monero-blockchain-import-reference/#performance","text":"Option Description --dangerous-unverified-import The safe default is to run verification (value 0 ). You can enable --dangerous-unverified-import if you are importing from your own and trusted blockchain.raw (which we assume was already verified). The \"dangerous\" mode will greatly speed up the process. --batch Whether to save to disk on an ongoing basis (the default, value 1 ) or maybe do everything in RAM and save everything in the end (value 0 ). No batching is only effective in combination with no verification ( --dangerous-unverified-import ). See also --batch-size . --batch-size How often to save to disk expressed in number of blocks. By default save every 5000 blocks (when verifying) or every 20000 blocks (when not verifying). Big batches are faster but require more RAM. --resume Resume from current height if output database already exists (the default, value 1 ). Changing to --resume=0 doesn't change much \u2014 existing blocks are skipped pretty quickly and the process is resumed anyway.","title":"Performance"},{"location":"interacting/monero-blockchain-import-reference/#reference","text":"https://github.com/monero-project/monero/tree/master/src/blockchain_utilities","title":"Reference"},{"location":"interacting/monero-config-file/","text":"Monero Configuration File \u00b6 Applicability \u00b6 By default Monero looks for bitmonero.conf in Monero data directory . To use a specific config file add --config-file option: ./monerod --config-file=/etc/monerod.conf The --config-file option is available for: monerod monero-wallet-cli monero-wallet-rpc monero-gen-trusted-multisig Syntax \u00b6 option-name=value valueless-option-name=1 for options that don't expect value # comment whitespace is ignored Reference \u00b6 All configuration options are the same as command line options for the binary. monerod reference monero-wallet-cli reference monero-wallet-rpc reference Skip the -- from --option-name . Example: ./monerod --log-level=4 --stagenet translates to: log-level=4 stagenet=1 # use value \"1\" to enable the value-less options like --stagenet Examples \u00b6 monerod.conf \u00b6 This config is tailored for production server usage. # /etc/monero/monerod.conf # Data directory (blockchain db and indices) data-dir=/home/monero/.monero # Remember to create the monero user first # Log file log-file=/var/log/monero/monerod.log max-log-file-size=0 # Prevent monerod from managing the log files; we want logrotate to take care of that # P2P full node p2p-bind-ip=0.0.0.0 # Bind to all interfaces (the default) p2p-bind-port=18080 # Bind to default port # RPC open node rpc-bind-ip=0.0.0.0 # Bind to all interfaces rpc-bind-port=18081 # Bind on default port confirm-external-bind=1 # Open node (confirm) restricted-rpc=1 # Prevent unsafe RPC calls no-igd=1 # Disable UPnP port mapping # Slow but reliable db writes db-sync-mode=safe # Emergency checkpoints set by MoneroPulse operators will be enforced to workaround potential consensus bugs # Check https://monerodocs.org/infrastructure/monero-pulse/ for explanation and trade-offs enforce-dns-checkpointing=1 out-peers=64 # This will enable much faster sync and tx awareness; the default 8 is suboptimal nowadays in-peers=1024 # The default is unlimited; we prefer to put a cap on this limit-rate-up=1048576 # 1048576 kB/s == 1GB/s; a raise from default 2048 kB/s; contribute more to p2p network limit-rate-down=1048576 # 1048576 kB/s == 1GB/s; a raise from default 8192 kB/s; allow for faster initial sync monero-wallet-cli.conf \u00b6 This config is tailored for desktop usage on stagenet . # $HOME/.bitmonero/stagenet/monero-wallet-cli.conf # Pick network stagenet=1 # Connect to a remote full node daemon-address=monero-stagenet.exan.tech:38081 untrusted-daemon=1 # Log file log-file=/tmp/monero-wallet-cli.log # wallet-file=/home/YOUR-USER/.bitmonero/stagenet/wallets/MoneroExampleStagenetWallet","title":"Config file"},{"location":"interacting/monero-config-file/#monero-configuration-file","text":"","title":"Monero Configuration File"},{"location":"interacting/monero-config-file/#applicability","text":"By default Monero looks for bitmonero.conf in Monero data directory . To use a specific config file add --config-file option: ./monerod --config-file=/etc/monerod.conf The --config-file option is available for: monerod monero-wallet-cli monero-wallet-rpc monero-gen-trusted-multisig","title":"Applicability"},{"location":"interacting/monero-config-file/#syntax","text":"option-name=value valueless-option-name=1 for options that don't expect value # comment whitespace is ignored","title":"Syntax"},{"location":"interacting/monero-config-file/#reference","text":"All configuration options are the same as command line options for the binary. monerod reference monero-wallet-cli reference monero-wallet-rpc reference Skip the -- from --option-name . Example: ./monerod --log-level=4 --stagenet translates to: log-level=4 stagenet=1 # use value \"1\" to enable the value-less options like --stagenet","title":"Reference"},{"location":"interacting/monero-config-file/#examples","text":"","title":"Examples"},{"location":"interacting/monero-config-file/#monerodconf","text":"This config is tailored for production server usage. # /etc/monero/monerod.conf # Data directory (blockchain db and indices) data-dir=/home/monero/.monero # Remember to create the monero user first # Log file log-file=/var/log/monero/monerod.log max-log-file-size=0 # Prevent monerod from managing the log files; we want logrotate to take care of that # P2P full node p2p-bind-ip=0.0.0.0 # Bind to all interfaces (the default) p2p-bind-port=18080 # Bind to default port # RPC open node rpc-bind-ip=0.0.0.0 # Bind to all interfaces rpc-bind-port=18081 # Bind on default port confirm-external-bind=1 # Open node (confirm) restricted-rpc=1 # Prevent unsafe RPC calls no-igd=1 # Disable UPnP port mapping # Slow but reliable db writes db-sync-mode=safe # Emergency checkpoints set by MoneroPulse operators will be enforced to workaround potential consensus bugs # Check https://monerodocs.org/infrastructure/monero-pulse/ for explanation and trade-offs enforce-dns-checkpointing=1 out-peers=64 # This will enable much faster sync and tx awareness; the default 8 is suboptimal nowadays in-peers=1024 # The default is unlimited; we prefer to put a cap on this limit-rate-up=1048576 # 1048576 kB/s == 1GB/s; a raise from default 2048 kB/s; contribute more to p2p network limit-rate-down=1048576 # 1048576 kB/s == 1GB/s; a raise from default 8192 kB/s; allow for faster initial sync","title":"monerod.conf"},{"location":"interacting/monero-config-file/#monero-wallet-cliconf","text":"This config is tailored for desktop usage on stagenet . # $HOME/.bitmonero/stagenet/monero-wallet-cli.conf # Pick network stagenet=1 # Connect to a remote full node daemon-address=monero-stagenet.exan.tech:38081 untrusted-daemon=1 # Log file log-file=/tmp/monero-wallet-cli.log # wallet-file=/home/YOUR-USER/.bitmonero/stagenet/wallets/MoneroExampleStagenetWallet","title":"monero-wallet-cli.conf"},{"location":"interacting/monero-wallet-cli-reference/","text":"monero-wallet-cli - Reference \u00b6 Note Get yourself comfortable with a friendly Monero CLI wallet. It is the most reliable and most complete wallet for Monero. Use stagenet for learning. Overview \u00b6 Command line wallet \u00b6 The \"official\" command line wallet for Monero. Available for Linux, macOS and Windows. Wallet uses your private keys to understand your total balance, transactions history, and to facilitate creating transactions. However, wallet does not store the blockchain and does not directly participate in the p2p network. The CLI wallet is the most reliable and most feature complete wallet for Monero. Depends on the full node \u00b6 Wallet connects to a full node to scan the blockchain for your transaction outputs and to send your transactions out to the network. The full node can be either local (same computer) or remote. Normally, you run the full node on the same computer as wallet (or within your home network). Connection happens over HTTP and uses this API . Any transaction leaving the wallet is already blinded by all Monero privacy features. This means plain text HTTP communication isn't an issue on its own even if you connect to a remote node. However, connecting to a remote node has other nuanced trade-offs, which is a topic for a separate article. Syntax \u00b6 ./monero-wallet-cli [options] [command] Example: ./monero-wallet-cli --stagenet Running \u00b6 Go to directory where you unpacked Monero. Run the full node and wait until it syncs up with the network (may take up to a few days): ./monerod --stagenet In a separate terminal window, run the wallet: ./monero-wallet-cli --stagenet --generate-new-wallet MoneroExampleStagenetWallet Options \u00b6 Help and version \u00b6 Option Description --help Enlist available options. --version Show monero-wallet-cli version to stdout. Example: Monero 'Boron Butterfly' (v0.14.0.0-release) Pick network \u00b6 Option Description (missing) By default wallet assumes mainnet . --stagenet Run on stagenet . Remember to run your daemon with --stagenet as well. --testnet Run on testnet . Remember to run your daemon with --testnet as well. Logging \u00b6 Option Description --log-file Full path to the log file. --log-level 0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0 . These are general presets and do not directly map to severity levels. For example, even with minimal 0 , you may see some most important INFO entries. --max-log-file-size Soft limit in bytes for the log file (=104850000 by default, which is just under 100MB). Once log file grows past that limit, monero creates the next log file with a UTC timestamp postfix -YYYY-MM-DD-HH-MM-SS . In production deployments, you would probably prefer to use established solutions like logrotate instead. In that case, set --max-log-file-size 0 to prevent monero from managing the log files. --max-log-files Limit on the number of log files (=50 by default). The oldest log files are removed. In production deployments, you would probably prefer to use established solutions like logrotate instead. Full node connection \u00b6 Wallet depends on a full node for all non-local operations. The following options define how to connect to monerod : Option Description --daemon-address Use monerod instance at : . Example: ./monero-wallet-cli --daemon-address monero-stagenet.exan.tech:38081 --stagenet --daemon-host Use monerod instance at host instead of localhost. --daemon-port Use monerod instance at port instead of 18081. --daemon-login Specify username[:password] for monerod RPC API. It is based on HTTP Basic Auth. Mind that connections are by default unencrypted. Authentication only makes sense if you establish a secure connection (maybe via Tor, or SSH tunneling, or reverse proxy w/ TLS). --trusted-daemon Enable commands and behaviors which rely on monerod instance being trusted. Default for localhost connection. The trust in this context concerns preserving your privacy. Only use this flag if you do control monerod . Trusted daemon allows for commands like rescan_spent , start_mining , import_key_images and behaviors like not warning about potential attack on transient problems with transaction sending. --untrusted-daemon Disable commands and behaviors which rely on monerod instance being trusted. Default for a non-localhost connections. See --trusted-daemon for more details. --do-not-relay The newly created transaction will not be relayed to the Monero network. Instead it will be dumped to a file in a raw hexadecimal format. Useful if you want to push the transaction through a gateway like https://xmrchain.net/rawtx . This may be easier to use over Tor than Monero wallet. --allow-mismatched-daemon-version Allow communicating with monerod that uses a different RPC version. Create new wallet \u00b6 Option Description --generate-new-wallet Create a new Monero wallet and save it to file. You will be asked for a password. The password is used to encrypt the wallet file but it is unrelated to your master spend key or mnemonic seed. Generate a very strong password with your password manager (~256 bits of entropy). Example: ./monero-wallet-cli --stagenet --generate-new-wallet $HOME/.bitmonero/stagenet/wallets/MoneroExampleStagenetWallet --kdf-rounds Concerns encrypting the wallet file. The wallet file is encrypted with ChaCha stream cipher. The encryption key is derived from the user supplied password by hashing the password with CryptoNight. This option defines how many times the CryptoNight hashing will be applied. The default is 1 round of hashing. Note this is unrelated to spend key generation. The more rounds the longer you will wait to open the wallet or send transaction. But also the attacker will have it harder to brute force your wallet password. Note: You will have to remember and provide the same kdf-rounds on every wallet access! Recommendation: Do not change the default value. Instead generate a very strong wallet password with your password manager (256 bits of entropy). Open existing wallet \u00b6 Option Description --wallet-file Open existing wallet. Example: ./monero-wallet-cli --stagenet --wallet-file $HOME/.bitmonero/stagenet/wallets/MoneroExampleStagenetWallet This is only for wallet files generated with monero-wallet-cli , monero-wallet-gui , or monero-wallet-rpc tools. If you have other type of wallet then see importing options. --password Provide wallet password as a parameter instead of interactively. Remember to escape/quote as needed. Not recommended because the password will remain in your command history and will also be visible in the process table. For automation prefer --password-file . The option also works in combination with --generate-new-wallet . --password-file Provide password as a file in stead of interactively. Trailing \\n are discarded when reading the password file. Prefer this over --password if you automate wallet access. Make sure the password file is meaningfully separated from the wallet file. Otherwise it provides no security benefit. The option also works in combination with --generate-new-wallet . Restore wallet \u00b6 Option Description --generate-from-device Restore/generate a special wallet to work with a hardware device like Ledger or Trezor and save it to file. Example: ./monero-wallet-cli --stagenet --generate-from-device MoneroExampleDeviceWallet --subaddress-lookahead 5:20 This is a one-time action. Next time you simply open the wallet . By default the command expects Ledger hardware connected. For Trezor hardware add --hw-device Trezor (expected ~May 2019). It will take up to 25 minutes with default settings. This is because hardware devices are slow to pre-generate subaddresses. To mitigate use low --subaddress-lookahead 5:20 . The local wallet will not have private spend key and will not be able to spend on its own. It serves as a user interface and a bridge for low-power hardware devices. Transaction signing with a private spend key always happens on the hardware device. See the complete guide to hardware wallet setup . --generate-from-view-key Restore a view-only version of the wallet to track incoming transactions and save it to file. The wallet is created based on a secret view key and standard address . The secret view key is meant to be pasted as hexadecimal. --generate-from-spend-key Restore a wallet from secret spend key and save it to file. The secret spend key is meant to be pasted as hexadecimal. --restore-deterministic-wallet Restore a wallet from secret mnemonic seed . Use this to restore from your 25 words backup. You will be asked for a password to encrypt the wallet file (once restored). Note this is not a passphrase to mnemonic seed. Mnemonic seeds generated by Monero official wallets are naked. --restore-height Only scan for transactions later than specific blockchain height. The default is 0 . Raising the value makes wallet restoration radically faster . The optimal value should match the day you originally created the wallet (but cannot be later). The mapping between the block height and date/time is available on block explorers like https://xmrchain.net . For instance, if you created the wallet in 2019+ use 1730000 . Multisig wallet \u00b6 Option Description --generate-from-multisig-keys Create a standard wallet from multisig keys. This is useful to combine all multisig secret keys back into the standard wallet (when you no longer need the multisig). The wallet will then have control of the funds. It only supports providing all secret keys even if the multisig scheme allowed for less (only N/N not N/M ). --restore-multisig-wallet Restore a multisig wallet from secret seed that was earlier exported with the seed interactive command. This only restores your part of the wallet. Other multisig participants will still be necessary to sign the transaction. Config file \u00b6 Option Description --config-file Full path to the configuration file . Note this should be a separate config than monerod uses because these tools accept different set of options. Performance \u00b6 Option Description --subaddress-lookahead Accepts m:n , by default 50:200 . The first value is the number of accounts and the second value is the number of subaddresses per account. The wallet will not check for payments to subaddresses further than n away from the last received payment. This can happen if you generated unique subaddresses for n clients in a row but none of them paid. On the other hand the more subaddresses you set to look ahead, the longer it takes to create your wallet, because they must be pre-computed. This is normally not a concern, except for hardware wallets. On the Ledger the default value of 50:200 can take over 20 minutes (one time on wallet creation)! --max-concurrency Max number of threads to use for parallel jobs. The default value 0 uses the number of CPU threads. Internationalization \u00b6 Option Description --mnemonic-language Language for mnemonic seed words. One of english , english_old , esperanto , french , german , italian , japanese , lojban , portuguese , russian , spanish . It might be a good idea to stick to default English which is by far the most popular and well tested. It also avoids potential non-ASCII characters pitfalls or bugs. --use-english-language-names If your display freezes, exit blind with ^C, then run again with --use-english-language-names . This can happen when Monero prompts for a language displaying language names in their natives alphabets. Legacy \u00b6 These options are either legacy or rarely useful. Option Description --non-deterministic Generate legacy non-deterministic wallet. The view key will not be derived from the spend key. You would also have to backup the .keys. To restore non-deterministic wallet (standard address) use --generate-from-keys . To restore fully you will need the .keys file. --generate-from-keys Restore legacy non-deterministic wallet by providing both spend and view keys and the standard address. --shared-ringdb-dir Set shared ring database path. No longer worthwhile . --create-address-file Has no effect. The *.address.txt file is created regardless of this option. --electrum-seed Provide mnemonic seed as a commandline option for --restore-deterministic-wallet instead of interactively. This is not recommended b/c the seed will be saved in your command history and also visible in the process list. --generate-from-json You would run monero-wallet-rpc to use this option. It seems exposed in monero-wallet-cli by accident. --tx-notify You would run monero-wallet-rpc to use this option. It seems exposed in monero-wallet-cli by accident. Defaults \u00b6 Wallet files are created and seek in current directory. This is rarely what you want. Use --wallet-file and similar options to control this. Log files are created in the same directory as monero-wallet-cli binary. Use --log-file to specify the location. Commands \u00b6 Commands are used interactively in the monero-wallet-cli prompt. You can also run a one-off command by providing it as a commandline parameter. This is rarely useful though. For automation prefer monero-wallet-rpc . The CLI wallet has built-in help for individual commands - we will not attempt to reproduce that. Instead we focus on grouping commands so you can quickly find what you are looking for. Use help command_name to learn more. Help and version \u00b6 help - list all commands help command_name - show help for individual command version - show version of the monero-wallet-cli binary Network status \u00b6 status - show if synced up to the blockchain height fee - show current fee-per-byte and full node's mempool (the backlog of transactions depending on the priority) wallet_info - show wallet file path, standard address, type and network Balance \u00b6 account - total balance; list accounts with respective balances balance detail - within the current account, list addresses with respective balances refresh - force refresh the balance and transactions by pulling latest blocks from the full node; this is often useful because auto-refresh only kicks in once in 90 seconds Manage accounts \u00b6 account account new account switch account label Manage addresses \u00b6 address all address new address label View transactions \u00b6 show_transfers - show all transactions on the current account; optionally provide a filter: in | out | pending | failed | pool | coinbase ; optionally provide subaddress index for output selection show_transfer - show details of specific transaction incoming_transfers [available|unavailable] [verbose] [index=[,[,...]]] - show the incoming transactions, all or filtered by availability and address index within current account; this will only show confirmed transactions; you will not see transactions awaiting in the mempool get_tx_note - get a string note for transaction id Keys and Passwords \u00b6 Secret mnemonic seed \u00b6 seed - show raw mnemonic seed encrypted_seed - create mnemonic seed encrypted with the passphrase; you will need to remember or store the passphrase separately; restoring will not be possible without the passphrase Secret keys \u00b6 spendkey - show secret spend key and public spend key viewkey - show secret view key and public view key Wallet password \u00b6 password - change wallet password; this password is used to encrypt the local wallet files; it does not change secret keys or backups Proofs \u00b6 get_reserve_proof -> check_reserve_proof - prove the balance get_spend_proof -> check_spend_proof - prove you made the payment sign -> verify
    - prove ownership of the address; allows to verify the file was signed by the owner of specific Monero address get_tx_proof -> check_tx_proof Multisig \u00b6 Setup \u00b6 prepare_multisig make_multisig finalize_multisig Update \u00b6 export_multisig_info import_multisig_info Other \u00b6 submit_multisig exchange_multisig_keys export_raw_multisig_tx sign_multisig Hardware wallet \u00b6 hw_reconnect - attempts to reconnect HW wallet Mining \u00b6 start_mining stop_mining Advanced \u00b6 Outputs \u00b6 unspent_outputs - show a list of, and a histogram of unspent outputs (indivisible pieces of your total balance) export_outputs -> import_outputs - helps with cold spending; export outputs from a view-wallet to the cold-wallet to make it aware of what had been sent to it mark_output_spent / | [add] mark_output_unspent / is_output_spent / Key images \u00b6 export_key_images -> import_key_images - used to inform the view-only wallet about outgoing transactions so it can calculate the real balance; normally view-only wallets only learn about incoming transactions, not outgoing Tx private key \u00b6 These allow to learn and verify transaction's private key r . This was useful to create a proof of payment but got superseded by get_spend_proof . get_tx_key check_tx_key
    set_tx_key Debugging \u00b6 rescan_spent - rescan the blockchain for spent outputs; sometimes, the wallet's idea of what outputs are spent and what outputs are not get out of sync with the blockchain. This can happen if you exit the wallet without saving after sending a tx, or if it crashes. This will look for the key images on the blockchain to make sure it's up to date. Cosmetics \u00b6 donate - donate to development team address_book [(add ((
    [pid ])|) [])|(delete )] set_description [free text note] -> get_description - manage convenience description of the wallet (the information is local) Legacy \u00b6 save - this now happens automatically save_bc - this now happens automatically bc_height - show blockchain height (superseded with status ) sweep_unmixable - only relevant for very old wallets (<= 2016); send all unmixable outputs to yourself with ring_size 10 locked_sweep_all - see rescan_bc - rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself TODO: document remaining commands","title":"monero-wallet-cli"},{"location":"interacting/monero-wallet-cli-reference/#monero-wallet-cli-reference","text":"Note Get yourself comfortable with a friendly Monero CLI wallet. It is the most reliable and most complete wallet for Monero. Use stagenet for learning.","title":"monero-wallet-cli - Reference"},{"location":"interacting/monero-wallet-cli-reference/#overview","text":"","title":"Overview"},{"location":"interacting/monero-wallet-cli-reference/#command-line-wallet","text":"The \"official\" command line wallet for Monero. Available for Linux, macOS and Windows. Wallet uses your private keys to understand your total balance, transactions history, and to facilitate creating transactions. However, wallet does not store the blockchain and does not directly participate in the p2p network. The CLI wallet is the most reliable and most feature complete wallet for Monero.","title":"Command line wallet"},{"location":"interacting/monero-wallet-cli-reference/#depends-on-the-full-node","text":"Wallet connects to a full node to scan the blockchain for your transaction outputs and to send your transactions out to the network. The full node can be either local (same computer) or remote. Normally, you run the full node on the same computer as wallet (or within your home network). Connection happens over HTTP and uses this API . Any transaction leaving the wallet is already blinded by all Monero privacy features. This means plain text HTTP communication isn't an issue on its own even if you connect to a remote node. However, connecting to a remote node has other nuanced trade-offs, which is a topic for a separate article.","title":"Depends on the full node"},{"location":"interacting/monero-wallet-cli-reference/#syntax","text":"./monero-wallet-cli [options] [command] Example: ./monero-wallet-cli --stagenet","title":"Syntax"},{"location":"interacting/monero-wallet-cli-reference/#running","text":"Go to directory where you unpacked Monero. Run the full node and wait until it syncs up with the network (may take up to a few days): ./monerod --stagenet In a separate terminal window, run the wallet: ./monero-wallet-cli --stagenet --generate-new-wallet MoneroExampleStagenetWallet","title":"Running"},{"location":"interacting/monero-wallet-cli-reference/#options","text":"","title":"Options"},{"location":"interacting/monero-wallet-cli-reference/#help-and-version","text":"Option Description --help Enlist available options. --version Show monero-wallet-cli version to stdout. Example: Monero 'Boron Butterfly' (v0.14.0.0-release)","title":"Help and version"},{"location":"interacting/monero-wallet-cli-reference/#pick-network","text":"Option Description (missing) By default wallet assumes mainnet . --stagenet Run on stagenet . Remember to run your daemon with --stagenet as well. --testnet Run on testnet . Remember to run your daemon with --testnet as well.","title":"Pick network"},{"location":"interacting/monero-wallet-cli-reference/#logging","text":"Option Description --log-file Full path to the log file. --log-level 0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0 . These are general presets and do not directly map to severity levels. For example, even with minimal 0 , you may see some most important INFO entries. --max-log-file-size Soft limit in bytes for the log file (=104850000 by default, which is just under 100MB). Once log file grows past that limit, monero creates the next log file with a UTC timestamp postfix -YYYY-MM-DD-HH-MM-SS . In production deployments, you would probably prefer to use established solutions like logrotate instead. In that case, set --max-log-file-size 0 to prevent monero from managing the log files. --max-log-files Limit on the number of log files (=50 by default). The oldest log files are removed. In production deployments, you would probably prefer to use established solutions like logrotate instead.","title":"Logging"},{"location":"interacting/monero-wallet-cli-reference/#full-node-connection","text":"Wallet depends on a full node for all non-local operations. The following options define how to connect to monerod : Option Description --daemon-address Use monerod instance at : . Example: ./monero-wallet-cli --daemon-address monero-stagenet.exan.tech:38081 --stagenet --daemon-host Use monerod instance at host instead of localhost. --daemon-port Use monerod instance at port instead of 18081. --daemon-login Specify username[:password] for monerod RPC API. It is based on HTTP Basic Auth. Mind that connections are by default unencrypted. Authentication only makes sense if you establish a secure connection (maybe via Tor, or SSH tunneling, or reverse proxy w/ TLS). --trusted-daemon Enable commands and behaviors which rely on monerod instance being trusted. Default for localhost connection. The trust in this context concerns preserving your privacy. Only use this flag if you do control monerod . Trusted daemon allows for commands like rescan_spent , start_mining , import_key_images and behaviors like not warning about potential attack on transient problems with transaction sending. --untrusted-daemon Disable commands and behaviors which rely on monerod instance being trusted. Default for a non-localhost connections. See --trusted-daemon for more details. --do-not-relay The newly created transaction will not be relayed to the Monero network. Instead it will be dumped to a file in a raw hexadecimal format. Useful if you want to push the transaction through a gateway like https://xmrchain.net/rawtx . This may be easier to use over Tor than Monero wallet. --allow-mismatched-daemon-version Allow communicating with monerod that uses a different RPC version.","title":"Full node connection"},{"location":"interacting/monero-wallet-cli-reference/#create-new-wallet","text":"Option Description --generate-new-wallet Create a new Monero wallet and save it to file. You will be asked for a password. The password is used to encrypt the wallet file but it is unrelated to your master spend key or mnemonic seed. Generate a very strong password with your password manager (~256 bits of entropy). Example: ./monero-wallet-cli --stagenet --generate-new-wallet $HOME/.bitmonero/stagenet/wallets/MoneroExampleStagenetWallet --kdf-rounds Concerns encrypting the wallet file. The wallet file is encrypted with ChaCha stream cipher. The encryption key is derived from the user supplied password by hashing the password with CryptoNight. This option defines how many times the CryptoNight hashing will be applied. The default is 1 round of hashing. Note this is unrelated to spend key generation. The more rounds the longer you will wait to open the wallet or send transaction. But also the attacker will have it harder to brute force your wallet password. Note: You will have to remember and provide the same kdf-rounds on every wallet access! Recommendation: Do not change the default value. Instead generate a very strong wallet password with your password manager (256 bits of entropy).","title":"Create new wallet"},{"location":"interacting/monero-wallet-cli-reference/#open-existing-wallet","text":"Option Description --wallet-file Open existing wallet. Example: ./monero-wallet-cli --stagenet --wallet-file $HOME/.bitmonero/stagenet/wallets/MoneroExampleStagenetWallet This is only for wallet files generated with monero-wallet-cli , monero-wallet-gui , or monero-wallet-rpc tools. If you have other type of wallet then see importing options. --password Provide wallet password as a parameter instead of interactively. Remember to escape/quote as needed. Not recommended because the password will remain in your command history and will also be visible in the process table. For automation prefer --password-file . The option also works in combination with --generate-new-wallet . --password-file Provide password as a file in stead of interactively. Trailing \\n are discarded when reading the password file. Prefer this over --password if you automate wallet access. Make sure the password file is meaningfully separated from the wallet file. Otherwise it provides no security benefit. The option also works in combination with --generate-new-wallet .","title":"Open existing wallet"},{"location":"interacting/monero-wallet-cli-reference/#restore-wallet","text":"Option Description --generate-from-device Restore/generate a special wallet to work with a hardware device like Ledger or Trezor and save it to file. Example: ./monero-wallet-cli --stagenet --generate-from-device MoneroExampleDeviceWallet --subaddress-lookahead 5:20 This is a one-time action. Next time you simply open the wallet . By default the command expects Ledger hardware connected. For Trezor hardware add --hw-device Trezor (expected ~May 2019). It will take up to 25 minutes with default settings. This is because hardware devices are slow to pre-generate subaddresses. To mitigate use low --subaddress-lookahead 5:20 . The local wallet will not have private spend key and will not be able to spend on its own. It serves as a user interface and a bridge for low-power hardware devices. Transaction signing with a private spend key always happens on the hardware device. See the complete guide to hardware wallet setup . --generate-from-view-key Restore a view-only version of the wallet to track incoming transactions and save it to file. The wallet is created based on a secret view key and standard address . The secret view key is meant to be pasted as hexadecimal. --generate-from-spend-key Restore a wallet from secret spend key and save it to file. The secret spend key is meant to be pasted as hexadecimal. --restore-deterministic-wallet Restore a wallet from secret mnemonic seed . Use this to restore from your 25 words backup. You will be asked for a password to encrypt the wallet file (once restored). Note this is not a passphrase to mnemonic seed. Mnemonic seeds generated by Monero official wallets are naked. --restore-height Only scan for transactions later than specific blockchain height. The default is 0 . Raising the value makes wallet restoration radically faster . The optimal value should match the day you originally created the wallet (but cannot be later). The mapping between the block height and date/time is available on block explorers like https://xmrchain.net . For instance, if you created the wallet in 2019+ use 1730000 .","title":"Restore wallet"},{"location":"interacting/monero-wallet-cli-reference/#multisig-wallet","text":"Option Description --generate-from-multisig-keys Create a standard wallet from multisig keys. This is useful to combine all multisig secret keys back into the standard wallet (when you no longer need the multisig). The wallet will then have control of the funds. It only supports providing all secret keys even if the multisig scheme allowed for less (only N/N not N/M ). --restore-multisig-wallet Restore a multisig wallet from secret seed that was earlier exported with the seed interactive command. This only restores your part of the wallet. Other multisig participants will still be necessary to sign the transaction.","title":"Multisig wallet"},{"location":"interacting/monero-wallet-cli-reference/#config-file","text":"Option Description --config-file Full path to the configuration file . Note this should be a separate config than monerod uses because these tools accept different set of options.","title":"Config file"},{"location":"interacting/monero-wallet-cli-reference/#performance","text":"Option Description --subaddress-lookahead Accepts m:n , by default 50:200 . The first value is the number of accounts and the second value is the number of subaddresses per account. The wallet will not check for payments to subaddresses further than n away from the last received payment. This can happen if you generated unique subaddresses for n clients in a row but none of them paid. On the other hand the more subaddresses you set to look ahead, the longer it takes to create your wallet, because they must be pre-computed. This is normally not a concern, except for hardware wallets. On the Ledger the default value of 50:200 can take over 20 minutes (one time on wallet creation)! --max-concurrency Max number of threads to use for parallel jobs. The default value 0 uses the number of CPU threads.","title":"Performance"},{"location":"interacting/monero-wallet-cli-reference/#internationalization","text":"Option Description --mnemonic-language Language for mnemonic seed words. One of english , english_old , esperanto , french , german , italian , japanese , lojban , portuguese , russian , spanish . It might be a good idea to stick to default English which is by far the most popular and well tested. It also avoids potential non-ASCII characters pitfalls or bugs. --use-english-language-names If your display freezes, exit blind with ^C, then run again with --use-english-language-names . This can happen when Monero prompts for a language displaying language names in their natives alphabets.","title":"Internationalization"},{"location":"interacting/monero-wallet-cli-reference/#legacy","text":"These options are either legacy or rarely useful. Option Description --non-deterministic Generate legacy non-deterministic wallet. The view key will not be derived from the spend key. You would also have to backup the .keys. To restore non-deterministic wallet (standard address) use --generate-from-keys . To restore fully you will need the .keys file. --generate-from-keys Restore legacy non-deterministic wallet by providing both spend and view keys and the standard address. --shared-ringdb-dir Set shared ring database path. No longer worthwhile . --create-address-file Has no effect. The *.address.txt file is created regardless of this option. --electrum-seed Provide mnemonic seed as a commandline option for --restore-deterministic-wallet instead of interactively. This is not recommended b/c the seed will be saved in your command history and also visible in the process list. --generate-from-json You would run monero-wallet-rpc to use this option. It seems exposed in monero-wallet-cli by accident. --tx-notify You would run monero-wallet-rpc to use this option. It seems exposed in monero-wallet-cli by accident.","title":"Legacy"},{"location":"interacting/monero-wallet-cli-reference/#defaults","text":"Wallet files are created and seek in current directory. This is rarely what you want. Use --wallet-file and similar options to control this. Log files are created in the same directory as monero-wallet-cli binary. Use --log-file to specify the location.","title":"Defaults"},{"location":"interacting/monero-wallet-cli-reference/#commands","text":"Commands are used interactively in the monero-wallet-cli prompt. You can also run a one-off command by providing it as a commandline parameter. This is rarely useful though. For automation prefer monero-wallet-rpc . The CLI wallet has built-in help for individual commands - we will not attempt to reproduce that. Instead we focus on grouping commands so you can quickly find what you are looking for. Use help command_name to learn more.","title":"Commands"},{"location":"interacting/monero-wallet-cli-reference/#help-and-version_1","text":"help - list all commands help command_name - show help for individual command version - show version of the monero-wallet-cli binary","title":"Help and version"},{"location":"interacting/monero-wallet-cli-reference/#network-status","text":"status - show if synced up to the blockchain height fee - show current fee-per-byte and full node's mempool (the backlog of transactions depending on the priority) wallet_info - show wallet file path, standard address, type and network","title":"Network status"},{"location":"interacting/monero-wallet-cli-reference/#balance","text":"account - total balance; list accounts with respective balances balance detail - within the current account, list addresses with respective balances refresh - force refresh the balance and transactions by pulling latest blocks from the full node; this is often useful because auto-refresh only kicks in once in 90 seconds","title":"Balance"},{"location":"interacting/monero-wallet-cli-reference/#manage-accounts","text":"account account new account switch account label","title":"Manage accounts"},{"location":"interacting/monero-wallet-cli-reference/#manage-addresses","text":"address all address new address label","title":"Manage addresses"},{"location":"interacting/monero-wallet-cli-reference/#view-transactions","text":"show_transfers - show all transactions on the current account; optionally provide a filter: in | out | pending | failed | pool | coinbase ; optionally provide subaddress index for output selection show_transfer - show details of specific transaction incoming_transfers [available|unavailable] [verbose] [index=[,[,...]]] - show the incoming transactions, all or filtered by availability and address index within current account; this will only show confirmed transactions; you will not see transactions awaiting in the mempool get_tx_note - get a string note for transaction id","title":"View transactions"},{"location":"interacting/monero-wallet-cli-reference/#keys-and-passwords","text":"","title":"Keys and Passwords"},{"location":"interacting/monero-wallet-cli-reference/#secret-mnemonic-seed","text":"seed - show raw mnemonic seed encrypted_seed - create mnemonic seed encrypted with the passphrase; you will need to remember or store the passphrase separately; restoring will not be possible without the passphrase","title":"Secret mnemonic seed"},{"location":"interacting/monero-wallet-cli-reference/#secret-keys","text":"spendkey - show secret spend key and public spend key viewkey - show secret view key and public view key","title":"Secret keys"},{"location":"interacting/monero-wallet-cli-reference/#wallet-password","text":"password - change wallet password; this password is used to encrypt the local wallet files; it does not change secret keys or backups","title":"Wallet password"},{"location":"interacting/monero-wallet-cli-reference/#proofs","text":"get_reserve_proof -> check_reserve_proof - prove the balance get_spend_proof -> check_spend_proof - prove you made the payment sign -> verify
    - prove ownership of the address; allows to verify the file was signed by the owner of specific Monero address get_tx_proof -> check_tx_proof","title":"Proofs"},{"location":"interacting/monero-wallet-cli-reference/#multisig","text":"","title":"Multisig"},{"location":"interacting/monero-wallet-cli-reference/#setup","text":"prepare_multisig make_multisig finalize_multisig","title":"Setup"},{"location":"interacting/monero-wallet-cli-reference/#update","text":"export_multisig_info import_multisig_info","title":"Update"},{"location":"interacting/monero-wallet-cli-reference/#other","text":"submit_multisig exchange_multisig_keys export_raw_multisig_tx sign_multisig ","title":"Other"},{"location":"interacting/monero-wallet-cli-reference/#hardware-wallet","text":"hw_reconnect - attempts to reconnect HW wallet","title":"Hardware wallet"},{"location":"interacting/monero-wallet-cli-reference/#mining","text":"start_mining stop_mining","title":"Mining"},{"location":"interacting/monero-wallet-cli-reference/#advanced","text":"","title":"Advanced"},{"location":"interacting/monero-wallet-cli-reference/#outputs","text":"unspent_outputs - show a list of, and a histogram of unspent outputs (indivisible pieces of your total balance) export_outputs -> import_outputs - helps with cold spending; export outputs from a view-wallet to the cold-wallet to make it aware of what had been sent to it mark_output_spent / | [add] mark_output_unspent / is_output_spent /","title":"Outputs"},{"location":"interacting/monero-wallet-cli-reference/#key-images","text":"export_key_images -> import_key_images - used to inform the view-only wallet about outgoing transactions so it can calculate the real balance; normally view-only wallets only learn about incoming transactions, not outgoing","title":"Key images"},{"location":"interacting/monero-wallet-cli-reference/#tx-private-key","text":"These allow to learn and verify transaction's private key r . This was useful to create a proof of payment but got superseded by get_spend_proof . get_tx_key check_tx_key
    set_tx_key ","title":"Tx private key"},{"location":"interacting/monero-wallet-cli-reference/#debugging","text":"rescan_spent - rescan the blockchain for spent outputs; sometimes, the wallet's idea of what outputs are spent and what outputs are not get out of sync with the blockchain. This can happen if you exit the wallet without saving after sending a tx, or if it crashes. This will look for the key images on the blockchain to make sure it's up to date.","title":"Debugging"},{"location":"interacting/monero-wallet-cli-reference/#cosmetics","text":"donate - donate to development team address_book [(add ((
    [pid ])|) [])|(delete )] set_description [free text note] -> get_description - manage convenience description of the wallet (the information is local)","title":"Cosmetics"},{"location":"interacting/monero-wallet-cli-reference/#legacy_1","text":"save - this now happens automatically save_bc - this now happens automatically bc_height - show blockchain height (superseded with status ) sweep_unmixable - only relevant for very old wallets (<= 2016); send all unmixable outputs to yourself with ring_size 10 locked_sweep_all - see rescan_bc - rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself TODO: document remaining commands","title":"Legacy"},{"location":"interacting/monero-wallet-gui-reference/","text":"monero-wallet-gui - Reference \u00b6 Overview \u00b6 Desktop GUI wallet \u00b6 The \"official\" desktop wallet for Monero. Available for Linux, macOS and Windows. Wallet uses your private keys to understand your total balance, transactions history, and to facilitate creating transactions. However, wallet does not store the blockchain and does not directly participate in the p2p network. Depends on the full node \u00b6 Wallet connects to a full node to scan the blockchain for your transaction outputs and to send your transactions out to the network. The full node can be either local (same computer) or remote. Normally, you run the full node on the same computer as wallet (or within your home network). Connection happens over HTTP and uses this API . Any transaction leaving the wallet is already blinded by all Monero privacy features. This means plain text HTTP communication isn't an issue on its own even if you connect to a remote node. However, connecting to a remote node has other nuanced trade-offs, which is a topic for a separate article. User guide PDF \u00b6 A nice PDF guide is available in the catalog you unpacked Monero. Make sure to check it out! The online living version is also available: https://github.com/monero-ecosystem/monero-GUI-guide/blob/master/monero-GUI-guide.md Syntax \u00b6 ./monero-wallet-gui [options] Example: ./monero-wallet-gui --log-file=/dev/null Running \u00b6 Go to directory where you unpacked Monero. Run the full node and wait until it syncs up with the network (may take up to a few days): ./monerod In a separate terminal window, run the wallet: ./monero-wallet-gui Options \u00b6 There are very few options because everything is set up via a GUI. Option Description --help Enlists available options. --log-file Full path to the log file. Example (mind file permissions): ./monerod --log-file=/var/log/monero/mainnet/monerod.log Defaults \u00b6 The wallet is created in $HOME/Monero/wallets/ . You may want to change it to $HOME/.bitmonero/wallets/ to have all Monero related files in one place. This is possible on wallet creation wizard in the GUI. The log file is created directly in the home directory $HOME/monero-wallet-gui.log . You may want to change with --log-file=$HOME/.bitmonero/monero-wallet-gui.log option.","title":"monero-wallet-gui"},{"location":"interacting/monero-wallet-gui-reference/#monero-wallet-gui-reference","text":"","title":"monero-wallet-gui - Reference"},{"location":"interacting/monero-wallet-gui-reference/#overview","text":"","title":"Overview"},{"location":"interacting/monero-wallet-gui-reference/#desktop-gui-wallet","text":"The \"official\" desktop wallet for Monero. Available for Linux, macOS and Windows. Wallet uses your private keys to understand your total balance, transactions history, and to facilitate creating transactions. However, wallet does not store the blockchain and does not directly participate in the p2p network.","title":"Desktop GUI wallet"},{"location":"interacting/monero-wallet-gui-reference/#depends-on-the-full-node","text":"Wallet connects to a full node to scan the blockchain for your transaction outputs and to send your transactions out to the network. The full node can be either local (same computer) or remote. Normally, you run the full node on the same computer as wallet (or within your home network). Connection happens over HTTP and uses this API . Any transaction leaving the wallet is already blinded by all Monero privacy features. This means plain text HTTP communication isn't an issue on its own even if you connect to a remote node. However, connecting to a remote node has other nuanced trade-offs, which is a topic for a separate article.","title":"Depends on the full node"},{"location":"interacting/monero-wallet-gui-reference/#user-guide-pdf","text":"A nice PDF guide is available in the catalog you unpacked Monero. Make sure to check it out! The online living version is also available: https://github.com/monero-ecosystem/monero-GUI-guide/blob/master/monero-GUI-guide.md","title":"User guide PDF"},{"location":"interacting/monero-wallet-gui-reference/#syntax","text":"./monero-wallet-gui [options] Example: ./monero-wallet-gui --log-file=/dev/null","title":"Syntax"},{"location":"interacting/monero-wallet-gui-reference/#running","text":"Go to directory where you unpacked Monero. Run the full node and wait until it syncs up with the network (may take up to a few days): ./monerod In a separate terminal window, run the wallet: ./monero-wallet-gui","title":"Running"},{"location":"interacting/monero-wallet-gui-reference/#options","text":"There are very few options because everything is set up via a GUI. Option Description --help Enlists available options. --log-file Full path to the log file. Example (mind file permissions): ./monerod --log-file=/var/log/monero/mainnet/monerod.log","title":"Options"},{"location":"interacting/monero-wallet-gui-reference/#defaults","text":"The wallet is created in $HOME/Monero/wallets/ . You may want to change it to $HOME/.bitmonero/wallets/ to have all Monero related files in one place. This is possible on wallet creation wizard in the GUI. The log file is created directly in the home directory $HOME/monero-wallet-gui.log . You may want to change with --log-file=$HOME/.bitmonero/monero-wallet-gui.log option.","title":"Defaults"},{"location":"interacting/monero-wallet-rpc-reference/","text":"monero-wallet-rpc - Reference \u00b6 Introduction \u00b6 This is a list of the monero-wallet-rpc calls, their inputs and outputs, and examples of each. The program monero-wallet-rpc replaced the rpc interface that was in simplewallet and then monero-wallet-cli. All monero-wallet-rpc methods use the same JSON RPC interface. For example: IP = 127 .0.0.1 PORT = 18082 METHOD = \"make_integrated_address\" PARAMS = \"{\\\"payment_id\\\":\\\"1234567890123456789012345678900012345678901234567890123456789000\\\"}\" curl \\ -X POST http:// $IP : $PORT /json_rpc \\ -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"' $METHOD '\",\"params\":' \" $PARAMS \" '}' \\ -H 'Content-Type: application/json' If the monero-wallet-rpc was executed with the --rpc-login argument as username:password , then follow this example: IP = 127 .0.0.1 PORT = 18082 METHOD = \"make_integrated_address\" PARAMS = \"{\\\"payment_id\\\":\\\"1234567890123456789012345678900012345678901234567890123456789000\\\"}\" curl \\ -u username:password --digest \\ -X POST http:// $IP : $PORT /json_rpc \\ -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"' $METHOD '\",\"params\":' \" $PARAMS \" '}' \\ -H 'Content-Type: application/json' Note: \"atomic units\" refer to the smallest fraction of 1 XMR according to the monerod implementation. 1 XMR = 1e12 atomic units. Index of JSON RPC Methods: \u00b6 add_address_book change_wallet_password check_reserve_proof check_spend_proof check_tx_key check_tx_proof close_wallet create_account create_address create_wallet delete_address_book export_key_images export_multisig_info export_outputs finalize_multisig get_accounts get_account_tags get_address_book get_address get_address_index get_attribute get_balance get_bulk_payments get_height get_languages get_payments get_reserve_proof get_spend_proof get_transfer_by_txid get_transfers get_tx_key get_tx_notes get_tx_proof get_version import_key_images import_multisig_info import_outputs incoming_transfers is_multisig label_account label_address make_integrated_address make_multisig make_uri open_wallet parse_uri prepare_multisig query_key refresh relay_tx rescan_blockchain rescan_spent set_account_tag_description set_attribute set_tx_notes sign_multisig sign sign_transfer split_integrated_address start_mining stop_mining stop_wallet store submit_multisig submit_transfer sweep_all sweep_dust sweep_single tag_accounts transfer_split transfer untag_accounts verify JSON RPC Methods: \u00b6 add_address_book \u00b6 Add an entry to the address book. Alias: None . Inputs: address - string; payment_id - (optional) string, defaults to \"0000000000000000000000000000000000000000000000000000000000000000\"; description - (optional) string, defaults to \"\"; Outputs: index - unsigned int; The index of the address book entry. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"add_address_book\",\"params\":{\"address\":\"78P16M3XmFRGcWFCcsgt1WcTntA1jzcq31seQX1Eg92j8VQ99NPivmdKam4J5CKNAD7KuNWcq5xUPgoWczChzdba5WLwQ4j\",\"description\":\"Third account\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"index\" : 1 } } change_wallet_password \u00b6 Change a wallet password. Alias: None . Inputs: old_password - string; (Optional) Current wallet password, if defined. new_password - string; (Optional) New wallet password, if not blank. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"change_wallet_password\",\"params\":{\"old_password\":\"theCurrentSecretPassPhrase\",\"new_password\":\"theNewSecretPassPhrase\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { } } check_reserve_proof \u00b6 Proves a wallet has a disposable reserve using a signature. Alias: None . Inputs: address - string; Public address of the wallet. message - string; (Optional) Should be the same message used in get_reserve_proof . signature - string; reserve signature to confirm. Outputs: good - boolean; States if the inputs proves the reserve. In the example below, the reserve has been proven: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_reserve_proof\",\"params\":{\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"signature\":\"ReserveProofV11BZ23sBt9sZJeGccf84mzyAmNCP3KzYbE1111112VKmH111118NfCYJQjZ6c46gT2kXgcHCaSSZeL8sRdzqjqx7i1e7FQfQGu2o113UYFVdwzHQi3iENDPa76Kn1BvywbKz3bMkXdZkBEEhBSF4kjjGaiMJ1ucKb6wvMVC4A8sA4nZEdL2Mk3wBucJCYTZwKqA8i1M113kqakDkG25FrjiDqdQTCYz2wDBmfKxF3eQiV5FWzZ6HmAyxnqTWUiMWukP9A3Edy3ZXqjP1b23dhz7Mbj39bBxe3ZeDNu9HnTSqYvHNRyqCkeUMJpHyQweqjGUJ1DSfFYr33J1E7MkhMnEi1o7trqWjVix32XLetYfePG73yvHbS24837L7Q64i5n1LSpd9yMiQZ3Dyaysi5y6jPx7TpAvnSqBFtuCciKoNzaXoA3dqt9cuVFZTXzdXKqdt3cXcVJMNxY8RvKPVQHhUur94Lpo1nSpxf7BN5a5rHrbZFqoZszsZmiWikYPkLX72XUdw6NWjLrTBxSy7KuPYH86c6udPEXLo2xgN6XHMBMBJzt8FqqK7EcpNUBkuHm2AtpGkf9CABY3oSjDQoRF5n4vNLd3qUaxNsG4XJ12L9gJ7GrK273BxkfEA8fDdxPrb1gpespbgEnCTuZHqj1A\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : true, \"spent\" : 0 , \"total\" : 100000000000 } } In the example below, all wallet reserve has been proven: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_reserve_proof\",\"params\":{\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"message\":\"I have 10 at least\",\"signature\":\"...signature...\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : true, \"spent\" : 0 , \"total\" : 164113855714662789 } } In the example below, the wrong message is used, avoiding the reserve to be proved: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_spend_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"message\":\"wrong message\",\"signature\":\"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : false } } check_spend_proof \u00b6 Prove a spend using a signature. Unlike proving a transaction, it does not requires the destination public address. Alias: None . Inputs: txid - string; transaction id. message - string; (Optional) Should be the same message used in get_spend_proof . signature - string; spend signature to confirm. Outputs: good - boolean; States if the inputs proves the spend. In the example below, the spend has been proven: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_spend_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"message\":\"this is my transaction\",\"signature\":\"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : true } } In the example below, the wrong message is used, avoiding the spend to be proved: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_spend_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"message\":\"wrong message\",\"signature\":\"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : false } } check_tx_key \u00b6 Check a transaction in the blockchain with its secret key. Alias: None . Inputs: txid - string; transaction id. tx_key - string; transaction secret key. address - string; destination public address of the transaction. Outputs: confirmations - unsigned int; Number of block mined after the one with the transaction. in_pool - boolean; States if the transaction is still in pool or has been added to a block. received - unsigned int; Amount of the transaction. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_tx_key\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"tx_key\":\"feba662cf8fb6d0d0da18fc9b70ab28e01cc76311278fdd7fe7ab16360762b06\",\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"confirmations\" : 0 , \"in_pool\" : false, \"received\" : 1000000000000 } } check_tx_proof \u00b6 Prove a transaction by checking its signature. Alias: None . Inputs: txid - string; transaction id. address - string; destination public address of the transaction. message - string; (Optional) Should be the same message used in get_tx_proof . signature - string; transaction signature to confirm. Outputs: confirmations - unsigned int; Number of block mined after the one with the transaction. good - boolean; States if the inputs proves the transaction. in_pool - boolean; States if the transaction is still in pool or has been added to a block. received - unsigned int; Amount of the transaction. In the example below, the transaction has been proven: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_tx_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\",\"message\":\"this is my transaction\",\"signature\":\"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"confirmations\" : 482 , \"good\" : true, \"in_pool\" : false, \"received\" : 1000000000000 } } In the example below, the wrong message is used, avoiding the transaction to be proved: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_tx_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\",\"message\":\"wrong message\",\"signature\":\"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"confirmations\" : 0 , \"good\" : false, \"in_pool\" : false, \"received\" : 0 } } close_wallet \u00b6 Close the currently opened wallet, after trying to save it. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"close_wallet\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { } } create_account \u00b6 Create a new account with an optional label. Alias: None . Inputs: label - string; (Optional) Label for the account. Outputs: account_index - unsigned int; Index of the new account. address - string; Address for this account. Base58 representation of the public keys. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"create_account\",\"params\":{\"label\":\"Secondary account\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"account_index\" : 1 , \"address\" : \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\" } } create_address \u00b6 Create a new address for an account. Optionally, label the new address. Alias: None . Inputs: account_index - unsigned int; Create a new address for this account. label - string; (Optional) Label for the new address. Outputs: address - string; Newly created address. Base58 representation of the public keys. address_index - unsigned int; Index of the new address under the input account. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"create_address\",\"params\":{\"account_index\":0,\"label\":\"new-sub\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"address\" : \"7BG5jr9QS5sGMdpbBrZEwVLZjSKJGJBsXdZLt8wiXyhhLjy7x2LZxsrAnHTgD8oG46ZtLjUGic2pWc96GFkGNPQQDA3Dt7Q\" , \"address_index\" : 5 } } create_wallet \u00b6 Create a new wallet. You need to have set the argument \"\u2013wallet-dir\" when launching monero-wallet-rpc to make this work. Alias: None . Inputs: filename - string; Wallet file name. password - string; (Optional) password to protect the wallet. language - string; Language for your wallets' seed. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"create_wallet\",\"params\":{\"filename\":\"mytestwallet\",\"password\":\"mytestpassword\",\"language\":\"English\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { } } delete_address_book \u00b6 Delete an entry from the address book. Alias: None . Inputs: index - unsigned int; The index of the address book entry. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"delete_address_book\",\"params\":{\"index\":1}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { } } export_key_images \u00b6 Export a signed set of key images. Alias: None . Inputs: None . Outputs: signed_key_images - array of signed key images: key_image - string; signature - string; Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"export_key_images\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"signed_key_images\" : [{ \"key_image\" : \"cd35239b72a35e26a57ed17400c0b66944a55de9d5bda0f21190fed17f8ea876\" , \"signature\" : \"c9d736869355da2538ab4af188279f84138c958edbae3c5caf388a63cd8e780b8c5a1aed850bd79657df659422c463608ea4e0c730ba9b662c906ae933816d00\" } , { \"key_image\" : \"65158a8ee5a3b32009b85a307d85b375175870e560e08de313531c7dbbe6fc19\" , \"signature\" : \"c96e40d09dfc45cfc5ed0b76bfd7ca793469588bb0cf2b4d7b45ef23d40fd4036057b397828062e31700dc0c2da364f50cd142295a8405b9fe97418b4b745d0c\" } ,... ] } } export_multisig_info \u00b6 Export multisig info for other participants. Alias: None . Inputs: None . Outputs: info - string; Multisig info in hex format for other participants. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"export_multisig_info\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"info\" : \"4d6f6e65726f206d756c7469736967206578706f72740105cf6442b09b75f5eca9d846771fe1a879c9a97ab0553ffbcec64b1148eb7832b51e7898d7944c41cee000415c5a98f4f80dc0efdae379a98805bb6eacae743446f6f421cd03e129eb5b27d6e3b73eb6929201507c1ae706c1a9ecd26ac8601932415b0b6f49cbbfd712e47d01262c59980a8f9a8be776f2bf585f1477a6df63d6364614d941ecfdcb6e958a390eb9aa7c87f056673d73bc7c5f0ab1f74a682e902e48a3322c0413bb7f6fd67404f13fb8e313f70a0ce568c853206751a334ef490068d3c8ca0e\" } } export_outputs \u00b6 Export all outputs in hex format. Alias: None . Inputs: None . Outputs: outputs_data_hex - string; wallet outputs in hex format. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"export_outputs\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"outputs_data_hex\" : \"...outputs...\" } } finalize_multisig \u00b6 Turn this wallet into a multisig wallet, extra step for N-1/N wallets. Alias: None . Inputs: multisig_info - array of string; List of multisig string from peers. password - string; Wallet password Outputs: address - string; multisig wallet address. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"finalize_multisig\",\"params\":{\"multisig_info\":[\"MultisigxV1JNC6Ja2oBt5Sqea9LN2YEF7WYZCpHqr2EKvPG89Trf3X4E8RWkLaGRf29fJ3stU471MELKxwufNYeigP7LoE4tn2McPr4SbL9q15xNvZT5uwC9YRr7UwjXqSZHmTWN9PBuZEKVAQ4HPPyQciSCdNjgwsuFRBzrskMdMUwNMgKst1debYfm37i6PSzDoS2tk4kYTYj83kkAdR7kdshet1axQPd6HQ\",\"MultisigxV1Unma7Ko4zdd8Ps3Af4oZwtj2JdWKzwNfP6s2G9ZvXhMoSscwn5g7PyCfcBc1V4ffRHY3Kxqq6VocSCUTncpVeUskMcPr4SbL9q15xNvZT5uwC9YRr7UwjXqSZHmTWN9PBuZE1LTpWxLoC3vPMSrqVVcjnmL9LYfdCZz3fECjNZbCEDq3PHDiUuY5jurQTcNoGhDTio5WM9xaAdim9YByiS5KyqF4\"]}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"address\" : \"5B9gZUTDuHTcGGuY3nL3t8K2tDnEHeRVHSBQgLZUTQxtFYVLnho5JJjWJyFp5YZgZRQ44RiviJi1sPHgLVMbckRsDqDx1gV\" } } get_account_tags \u00b6 Get a list of user-defined account tags. Alias: None . Inputs: None . Outputs: account_tags - array of account tag information: tag - string; Filter tag. label - string; Label for the tag. accounts - array of int; List of tagged account indices. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_account_tags\",\"params\":\"\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"account_tags\" : [{ \"accounts\" : [ 0 ] , \"label\" : \"Test tag\" , \"tag\" : \"myTag\" }] } } get_accounts \u00b6 Get all accounts for a wallet. Optionally filter accounts by tag. Alias: None . Inputs: tag - string; (Optional) Tag for filtering accounts. Outputs: subaddress_accounts - array of subaddress account information: account_index - unsigned int; Index of the account. balance - unsigned int; Balance of the account (locked or unlocked). base_address - string; Base64 representation of the first subaddress in the account. label - string; (Optional) Label of the account. tag - string; (Optional) Tag for filtering accounts. unlocked_balance - unsigned int; Unlocked balance for the account. total_balance - unsigned int; Total balance of the selected accounts (locked or unlocked). total_unlocked_balance - unsigned int; Total unlocked balance of the selected accounts. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_accounts\",\"params\":{\"tag\":\"myTag\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"subaddress_accounts\" : [{ \"account_index\" : 0 , \"balance\" : 157663195572433688 , \"base_address\" : \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\" , \"label\" : \"Primary account\" , \"tag\" : \"myTag\" , \"unlocked_balance\" : 157443303037455077 } , { \"account_index\" : 1 , \"balance\" : 0 , \"base_address\" : \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\" , \"label\" : \"Secondary account\" , \"tag\" : \"myTag\" , \"unlocked_balance\" : 0 }] , \"total_balance\" : 157663195572433688 , \"total_unlocked_balance\" : 157443303037455077 } } get_address \u00b6 Return the wallet's addresses for an account. Optionally filter for specific set of subaddresses. Alias: getaddress . Inputs: account_index - unsigned int; Return subaddresses for this account. address_index - array of unsigned int; (Optional) List of subaddresses to return from an account. Outputs: address - string; The 95-character hex address string of the monero-wallet-rpc in session. addresses array of addresses informations address string; The 95-character hex (sub)address string. label string; Label of the (sub)address address_index unsigned int; index of the subaddress used boolean; states if the (sub)address has already received funds Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_address\",\"params\":{\"account_index\":0,\"address_index\":[0,1,4]}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"address\" : \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\" , \"addresses\" : [{ \"address\" : \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\" , \"address_index\" : 0 , \"label\" : \"Primary account\" , \"used\" : true } , { \"address\" : \"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\" , \"address_index\" : 1 , \"label\" : \"\" , \"used\" : true } , { \"address\" : \"77xa6Dha7kzCQuvmd8iB5VYoMkdenwCNRU9khGhExXQ8KLL3z1N1ZATBD1sFPenyHWT9cm4fVFnCAUApY53peuoZFtwZiw5\" , \"address_index\" : 4 , \"label\" : \"test2\" , \"used\" : true }] } } get_address_book \u00b6 Retrieves entries from the address book. Alias: None . Inputs: entries - array of unsigned int; indices of the requested address book entries Outputs: entries - array of entries: address - string; Public address of the entry description - string; Description of this address entry index - unsigned int; payment_id - string; Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_address_book\",\"params\":{\"entries\":[0,1]}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"entries\" : [{ \"address\" : \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\" , \"description\" : \"Second account\" , \"index\" : 0 , \"payment_id\" : \"0000000000000000000000000000000000000000000000000000000000000000\" } , { \"address\" : \"78P16M3XmFRGcWFCcsgt1WcTntA1jzcq31seQX1Eg92j8VQ99NPivmdKam4J5CKNAD7KuNWcq5xUPgoWczChzdba5WLwQ4j\" , \"description\" : \"Third account\" , \"index\" : 1 , \"payment_id\" : \"0000000000000000000000000000000000000000000000000000000000000000\" }] } } get_address_index \u00b6 Get account and address indexes from a specific (sub)address Alias: None . Inputs: address - String; (sub)address to look for. Outputs: index - subaddress informations major unsigned int; Account index. minor unsigned int; Address index. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_address_index\",\"params\":{\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"index\": { \"major\": 0, \"minor\": 1 } } } get_attribute \u00b6 Get attribute value by name. Alias: None . Inputs: key - string; attribute name Outputs: value - string; attribute value Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_attribute\",\"params\":{\"key\":\"my_attribute\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"value\": \"my_value\" } } get_bulk_payments \u00b6 Get a list of incoming payments using a given payment id, or a list of payments ids, from a given height. This method is the preferred method over get_payments because it has the same functionality but is more extendable. Either is fine for looking up transactions by a single payment ID. Alias: None . Inputs: payment_ids - array of: string; Payment IDs used to find the payments (16 characters hex). min_block_height - unsigned int; The block height at which to start looking for payments. Outputs: payments - list of: payment_id - string; Payment ID matching one of the input IDs. tx_hash - string; Transaction hash used as the transaction ID. amount - unsigned int; Amount for this payment. block_height - unsigned int; Height of the block that first confirmed this payment. unlock_time - unsigned int; Time (in block height) until this payment is safe to spend. subaddr_index - subaddress index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress in the account. address - string; Address receiving the payment; Base58 representation of the public keys. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_bulk_payments\",\"params\":{\"payment_ids\":[\"60900e5603bf96e3\"],\"min_block_height\":\"120000\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"payments\": [{ \"address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\", \"amount\": 1000000000000, \"block_height\": 127606, \"payment_id\": \"60900e5603bf96e3\", \"subaddr_index\": { \"major\": 0, \"minor\": 0 }, \"tx_hash\": \"3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f\", \"unlock_time\": 0 }] } } get_height \u00b6 Returns the wallet's current block height. Alias: getheight . Inputs: None . Outputs: height - unsigned int; The current monero-wallet-rpc's blockchain height. If the wallet has been offline for a long time, it may need to catch up with the daemon. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_height\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"height\": 145545 } } get_languages \u00b6 Get a list of available languages for your wallet's seed. Alias: None . Inputs: None . Outputs: languages - array of string; List of available languages Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_languages\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"languages\": [\"Deutsch\",\"English\",\"Espa\u00f1ol\",\"Fran\u00e7ais\",\"Italiano\",\"Nederlands\",\"Portugu\u00eas\",\"\u0440\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a\",\"\u65e5\u672c\u8a9e\",\"\u7b80\u4f53\u4e2d\u6587 (\u4e2d\u56fd)\",\"Esperanto\",\"Lojban\"] } } get_payments \u00b6 Get a list of incoming payments using a given payment id. Alias: None . Inputs: payment_id - string; Payment ID used to find the payments (16 characters hex). Outputs: payments - list of: payment_id - string; Payment ID matching the input parameter. tx_hash - string; Transaction hash used as the transaction ID. amount - unsigned int; Amount for this payment. block_height - unsigned int; Height of the block that first confirmed this payment. unlock_time - unsigned int; Time (in block height) until this payment is safe to spend. subaddr_index - subaddress index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress in the account. address - string; Address receiving the payment; Base58 representation of the public keys. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_payments\",\"params\":{\"payment_id\":\"60900e5603bf96e3\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"payments\": [{ \"address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\", \"amount\": 1000000000000, \"block_height\": 127606, \"payment_id\": \"60900e5603bf96e3\", \"subaddr_index\": { \"major\": 0, \"minor\": 0 }, \"tx_hash\": \"3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f\", \"unlock_time\": 0 }] } } get_reserve_proof \u00b6 Generate a signature to prove of an available amount in a wallet. Alias: None . Inputs: all - boolean; Proves all wallet balance to be disposable. account_index - unsigned int; Specify the account from witch to prove reserve. (ignored if all is set to true) amount - unsigned int; Amount (in atomic units) to prove the account has for reserve. (ignored if all is set to true) message - string; (Optional) add a message to the signature to further authenticate the prooving process. Outputs: signature - string; reserve signature. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_reserve_proof\",\"params\":{\"all\":false,\"account_index\":0,\"amount\":100000000000}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signature\": \"ReserveProofV11BZ23sBt9sZJeGccf84mzyAmNCP3KzYbE1111112VKmH111118NfCYJQjZ6c46gT2kXgcHCaSSZeL8sRdzqjqx7i1e7FQfQGu2o113UYFVdwzHQi3iENDPa76Kn1BvywbKz3bMkXdZkBEEhBSF4kjjGaiMJ1ucKb6wvMVC4A8sA4nZEdL2Mk3wBucJCYTZwKqA8i1M113kqakDkG25FrjiDqdQTCYz2wDBmfKxF3eQiV5FWzZ6HmAyxnqTWUiMWukP9A3Edy3ZXqjP1b23dhz7Mbj39bBxe3ZeDNu9HnTSqYvHNRyqCkeUMJpHyQweqjGUJ1DSfFYr33J1E7MkhMnEi1o7trqWjVix32XLetYfePG73yvHbS24837L7Q64i5n1LSpd9yMiQZ3Dyaysi5y6jPx7TpAvnSqBFtuCciKoNzaXoA3dqt9cuVFZTXzdXKqdt3cXcVJMNxY8RvKPVQHhUur94Lpo1nSpxf7BN5a5rHrbZFqoZszsZmiWikYPkLX72XUdw6NWjLrTBxSy7KuPYH86c6udPEXLo2xgN6XHMBMBJzt8FqqK7EcpNUBkuHm2AtpGkf9CABY3oSjDQoRF5n4vNLd3qUaxNsG4XJ12L9gJ7GrK273BxkfEA8fDdxPrb1gpespbgEnCTuZHqj1A\" } } get_spend_proof \u00b6 Generate a signature to prove a spend. Unlike proving a transaction, it does not requires the destination public address. Alias: None . Inputs: txid - string; transaction id. message - string; (Optional) add a message to the signature to further authenticate the prooving process. Outputs: signature - string; spend signature. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_spend_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"message\":\"this is my transaction\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signature\": \"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB\" } } get_transfer_by_txid \u00b6 Show information about a transfer to/from this address. Alias: None . Inputs: txid - string; Transaction ID used to find the transfer. account_index - unsigned int; (Optional) Index of the account to query for the transfer. Outputs: transfer - JSON object containing payment information: address - string; Address that transferred the funds. Base58 representation of the public keys. amount - unsigned int; Amount of this transfer. confirmations - unsigned int; Number of block mined since the block containing this transaction (or block height at which the transaction should be added to a block if not yet confirmed). destinations - array of JSON objects containing transfer destinations: amount - unsigned int; Amount transferred to this destination. address - string; Address for this destination. Base58 representation of the public keys. double_spend_seen - boolean; True if the key image(s) for the transfer have been seen before. fee - unsigned int; Transaction fee for this transfer. height - unsigned int; Height of the first block that confirmed this transfer. note - string; Note about this transfer. payment_id - string; Payment ID for this transfer. subaddr_index - JSON object containing the major & minor subaddress index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress under the account. suggested_confirmations_threshold - unsigned int; Estimation of the confirmations needed for the transaction to be included in a block. timestamp - unsigned int; POSIX timestamp for the block that confirmed this transfer (or timestamp submission if not mined yet). txid - string; Transaction ID of this transfer (same as input TXID). type - string; Type of transfer, one of the following: \"in\", \"out\", \"pending\", \"failed\", \"pool\" unlock_time - unsigned int; Number of blocks until transfer is safely spendable. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_transfer_by_txid\",\"params\":{\"txid\":\"c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"transfer\": { \"address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\", \"amount\": 300000000000, \"confirmations\": 1, \"destinations\": [{ \"address\": \"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\", \"amount\": 100000000000 },{ \"address\": \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\", \"amount\": 200000000000 }], \"double_spend_seen\": false, \"fee\": 21650200000, \"height\": 153624, \"note\": \"\", \"payment_id\": \"0000000000000000\", \"subaddr_index\": { \"major\": 0, \"minor\": 0 }, \"suggested_confirmations_threshold\": 1, \"timestamp\": 1535918400, \"txid\": \"c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a\", \"type\": \"out\", \"unlock_time\": 0 } } } get_transfers \u00b6 Returns a list of transfers. Alias: None . Inputs: in - boolean; (Optional) Include incoming transfers. out - boolean; (Optional) Include outgoing transfers. pending - boolean; (Optional) Include pending transfers. failed - boolean; (Optional) Include failed transfers. pool - boolean; (Optional) Include transfers from the daemon's transaction pool. filter_by_height - boolean; (Optional) Filter transfers by block height. min_height - unsigned int; (Optional) Minimum block height to scan for transfers, if filtering by height is enabled. max_height - unsigned int; (Opional) Maximum block height to scan for transfers, if filtering by height is enabled (defaults to max block height). account_index - unsigned int; (Optional) Index of the account to query for transfers. (defaults to 0) subaddr_indices - array of unsigned int; (Optional) List of subaddress indices to query for transfers. (defaults to 0) Outputs: in array of transfers: address - string; Public address of the transfer. amount - unsigned int; Amount transferred. confirmations - unsigned int; Number of block mined since the block containing this transaction (or block height at which the transaction should be added to a block if not yet confirmed). double_spend_seen - boolean; True if the key image(s) for the transfer have been seen before. fee - unsigned int; Transaction fee for this transfer. height - unsigned int; Height of the first block that confirmed this transfer (0 if not mined yet). note - string; Note about this transfer. payment_id - string; Payment ID for this transfer. subaddr_index - JSON object containing the major & minor subaddress index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress under the account. suggested_confirmations_threshold - unsigned int; Estimation of the confirmations needed for the transaction to be included in a block. timestamp - unsigned int; POSIX timestamp for when this transfer was first confirmed in a block (or timestamp submission if not mined yet). txid - string; Transaction ID for this transfer. type - string; Transfer type: \"in\" unlock_time - unsigned int; Number of blocks until transfer is safely spendable. out array of transfers (see above). pending array of transfers (see above). failed array of transfers (see above). pool array of transfers (see above). Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_transfers\",\"params\":{\"in\":true,\"account_index\":1}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"in\": [{ \"address\": \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\", \"amount\": 200000000000, \"confirmations\": 1, \"double_spend_seen\": false, \"fee\": 21650200000, \"height\": 153624, \"note\": \"\", \"payment_id\": \"0000000000000000\", \"subaddr_index\": { \"major\": 1, \"minor\": 0 }, \"suggested_confirmations_threshold\": 1, \"timestamp\": 1535918400, \"txid\": \"c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a\", \"type\": \"in\", \"unlock_time\": 0 }] } } get_tx_key \u00b6 Get transaction secret key from transaction id. Alias: None . Inputs: txid - string; transaction id. Outputs: tx_key - string; transaction secret key. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_tx_key\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_key\": \"feba662cf8fb6d0d0da18fc9b70ab28e01cc76311278fdd7fe7ab16360762b06\" } } get_tx_notes \u00b6 Get string notes for transactions. Alias: None . Inputs: txids - array of string; transaction ids Outputs: notes - array of string; notes for the transactions Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_tx_notes\",\"params\":{\"txids\":[\"3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f\"]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"notes\": [\"This is an example\"] } } get_tx_proof \u00b6 Get transaction signature to prove it. Alias: None . Inputs: txid - string; transaction id. address - string; destination public address of the transaction. message - string; (Optional) add a message to the signature to further authenticate the prooving process. Outputs: signature - string; transaction signature. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_tx_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\",\"message\":\"this is my transaction\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signature\": \"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ\" } } get_version \u00b6 Get RPC version Major & Minor integer-format, where Major is the first 16 bits and Minor the last 16 bits. Alias: None . Inputs: None . Outputs: version - unsigned int; RPC version, formatted with Major * 2^16 + Minor (Major encoded over the first 16 bits, and Minor over the last 16 bits). Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"version\": 65539 } } import_key_images \u00b6 Import signed key images list and verify their spent status. Alias: None . Inputs: signed_key_images - array of signed key images: key_image - string; signature - string; Outputs: height - unsigned int; spent - unsigned int; Amount (in atomic units) spent from those key images. unspent - unsigned int; Amount (in atomic units) still available from those key images. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"import_key_images\", \"params\":{\"signed_key_images\":[{\"key_image\":\"cd35239b72a35e26a57ed17400c0b66944a55de9d5bda0f21190fed17f8ea876\",\"signature\":\"c9d736869355da2538ab4af188279f84138c958edbae3c5caf388a63cd8e780b8c5a1aed850bd79657df659422c463608ea4e0c730ba9b662c906ae933816d00\"},{\"key_image\":\"65158a8ee5a3b32009b85a307d85b375175870e560e08de313531c7dbbe6fc19\",\"signature\":\"c96e40d09dfc45cfc5ed0b76bfd7ca793469588bb0cf2b4d7b45ef23d40fd4036057b397828062e31700dc0c2da364f50cd142295a8405b9fe97418b4b745d0c\"}]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"height\": 76428, \"spent\": 62708953408711, \"unspent\": 0 } } import_multisig_info \u00b6 Import multisig info from other participants. Alias: None . Inputs: info - array of string; List of multisig info in hex format from other participants. Outputs: n_outputs - unsigned int; Number of outputs signed with those multisig info. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"import_multisig_info\",\"params\":{\"info\":[\"...multisig_info...\"]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"n_outputs\": 35 } } import_outputs \u00b6 Import outputs in hex format. Alias: None . Inputs: outputs_data_hex - string; wallet outputs in hex format. Outputs: num_imported - unsigned int; number of outputs imported. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"import_outputs\",\"params\":{\"outputs_data_hex\":\"...outputs...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"num_imported\": 6400 } } incoming_transfers \u00b6 Return a list of incoming transfers to the wallet. Inputs: transfer_type - string; \"all\": all the transfers, \"available\": only transfers which are not yet spent, OR \"unavailable\": only transfers which are already spent. account_index - unsigned int; (Optional) Return transfers for this account. (defaults to 0) subaddr_indices - array of unsigned int; (Optional) Return transfers sent to these subaddresses. verbose - boolean; (Optional) Enable verbose output, return key image if true. Outputs: transfers - list of: amount - unsigned int; Amount of this transfer. global_index - unsigned int; Mostly internal use, can be ignored by most users. key_image - string; Key image for the incoming transfer's unspent output (empty unless verbose is true). spent - boolean; Indicates if this transfer has been spent. subaddr_index - unsigned int; Subaddress index for incoming transfer. tx_hash - string; Several incoming transfers may share the same hash if they were in the same transaction. tx_size - unsigned int; Size of transaction in bytes. Example, get all transfers: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"incoming_transfers\",\"params\":{\"transfer_type\":\"all\",\"account_index\":0,\"subaddr_indices\":[3],\"verbose\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"transfers\": [{ \"amount\": 60000000000000, \"global_index\": 122405, \"key_image\": \"768f5144777eb23477ab7acf83562581d690abaf98ca897c03a9d2b900eb479b\", \"spent\": true, \"subaddr_index\": 3, \"tx_hash\": \"f53401f21c6a43e44d5dd7a90eba5cf580012ad0e15d050059136f8a0da34f6b\", \"tx_size\": 159 },{ \"amount\": 27126892247503, \"global_index\": 594994, \"key_image\": \"7e561394806afd1be61980cc3431f6ef3569fa9151cd8d234f8ec13aa145695e\", \"spent\": false, \"subaddr_index\": 3, \"tx_hash\": \"106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b\", \"tx_size\": 157 },{ \"amount\": 27169374733655, \"global_index\": 594997, \"key_image\": \"e76c0a3bfeaae35e4173712f782eb34011198e26b990225b71aa787c8ba8a157\", \"spent\": false, \"subaddr_index\": 3, \"tx_hash\": \"0bd959b59117ee1254bd8e5aa8e77ec04ef744144a1ffb2d5c1eb9380a719621\", \"tx_size\": 158 }] } } Example, get available transfers: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"incoming_transfers\",\"params\":{\"transfer_type\":\"available\",\"account_index\":0,\"subaddr_indices\":[3],\"verbose\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"transfers\": [{ \"amount\": 27126892247503, \"global_index\": 594994, \"key_image\": \"7e561394806afd1be61980cc3431f6ef3569fa9151cd8d234f8ec13aa145695e\", \"spent\": false, \"subaddr_index\": 3, \"tx_hash\": \"106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b\", \"tx_size\": 157 },{ \"amount\": 27169374733655, \"global_index\": 594997, \"key_image\": \"e76c0a3bfeaae35e4173712f782eb34011198e26b990225b71aa787c8ba8a157\", \"spent\": false, \"subaddr_index\": 3, \"tx_hash\": \"0bd959b59117ee1254bd8e5aa8e77ec04ef744144a1ffb2d5c1eb9380a719621\", \"tx_size\": 158 }] } } Example, get unavailable transfers: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"incoming_transfers\",\"params\":{\"transfer_type\":\"unavailable\",\"account_index\":0,\"subaddr_indices\":[3],\"verbose\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"transfers\": [{ \"amount\": 60000000000000, \"global_index\": 122405, \"key_image\": \"768f5144777eb23477ab7acf83562581d690abaf98ca897c03a9d2b900eb479b\", \"spent\": true, \"subaddr_index\": 3, \"tx_hash\": \"f53401f21c6a43e44d5dd7a90eba5cf580012ad0e15d050059136f8a0da34f6b\", \"tx_size\": 159 }] } } is_multisig \u00b6 Check if a wallet is a multisig one. Alias: None . Inputs: None . Outputs: multisig - boolean; States if the wallet is multisig ready - boolean; threshold - unsigned int; Amount of signature needed to sign a transfer. total - unsigned int; Total amount of signature in the multisig wallet. Example for a non-multisig wallet: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"is_multisig\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"multisig\": false, \"ready\": false, \"threshold\": 0, \"total\": 0 } } Example for a multisig wallet: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"is_multisig\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"multisig\": true, \"ready\": true, \"threshold\": 2, \"total\": 2 } } label_account \u00b6 Label an account. Alias: None . Inputs: account_index - unsigned int; Apply label to account at this index. label - string; Label for the account. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"label_account\",\"params\":{\"account_index\":0,\"label\":\"Primary account\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"account_tags\": [{ \"accounts\": [0,1], \"label\": \"\", \"tag\": \"myTag\" }] } } label_address \u00b6 Label an address. Alias: None . Inputs: index - subaddress index; JSON Object containing the major & minor address index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress in the account. label - string; Label for the address. Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"label_address\",\"params\":{\"index\":{\"major\":0,\"minor\":5},\"label\":\"myLabel\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } make_integrated_address \u00b6 Make an integrated address from the wallet address and a payment id. Alias: None . Inputs: standard_address - string; (Optional, defaults to primary address) Destination public address. payment_id - string; (Optional, defaults to a random ID) 16 characters hex encoded. Outputs: integrated_address - string payment_id - string; hex encoded; Example (Payment ID is empty, use a random ID): $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"make_integrated_address\",\"params\":{\"standard_address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"integrated_address\": \"5F38Rw9HKeaLQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZXCkbHUXdPHyiUeRyokn\", \"payment_id\": \"420fa29b2d9a49f5\" } } make_multisig \u00b6 Make a wallet multisig by importing peers multisig string. Alias: None . Inputs: multisig_info - array of string; List of multisig string from peers. threshold - unsigned int; Amount of signatures needed to sign a transfer. Must be less or equal than the amount of signature in multisig_info . password - string; Wallet password Outputs: address - string; multisig wallet address. multisig_info - string; Multisig string to share with peers to create the multisig wallet (extra step for N-1/N wallets). Example for 2/2 Multisig Wallet: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"make_multisig\",\"params\":{\"multisig_info\":[\"MultisigV1K4tGGe8QirZdHgTYoBZMumSug97fdDyM3Z63M3ZY5VXvAdoZvx16HJzPCP4Rp2ABMKUqLD2a74ugMdBfrVpKt4BwD8qCL5aZLrsYWoHiA7JJwDESuhsC3eF8QC9UMvxLXEMsMVh16o98GnKRYz1HCKXrAEWfcrCHyz3bLW1Pdggyowop\"],\"threshold\":2}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"address\": \"55SoZTKH7D39drxfgT62k8T4adVFjmDLUXnbzEKYf1MoYwnmTNKKaqGfxm4sqeKCHXQ5up7PVxrkoeRzXu83d8xYURouMod\", \"multisig_info\": \"\" } } Example for 2/3 Multisig Wallet: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"make_multisig\",\"params\":{\"multisig_info\":[\"MultisigV1MTVm4DZAdJw1PyVutpSy8Q4WisZBCFRAaZY7hhQnMwr5AZ4swzThyaSiVVQM5FHj1JQi3zPKhQ4k81BZkPSEaFjwRJtbfqfJcVvCqRnmBVcWVxhnihX5s8fZWBCjKrzT3CS95spG4dzNzJSUcjheAkLzCpVmSzGtgwMhAS3Vuz9Pas24\",\"MultisigV1TEx58ycKCd6ADCfxF8hALpcdSRAkhZTi1bu4Rs6FdRC98EdB1LY7TAkMxasM55khFgcxrSXivaSr5FCMyJGHmojm1eE4HpGWPeZKv6cgCTThRzC4u6bkkSoFQdbzWN92yn1XEjuP2XQrGHk81mG2LMeyB51MWKJAVF99Pg9mX2BpmYFj\"],\"threshold\":2}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"address\": \"51sLpF8fWaK1111111111111111111111111111111111ABVbHNf1JFWJyFp5YZgZRQ44RiviJi1sPHgLVMbckRsDkTRgKS\", \"multisig_info\": \"MultisigxV18jCaYAQQvzCMUJaAWMCaAbAoHpAD6WPmYDmLtBtazD654E8RWkLaGRf29fJ3stU471MELKxwufNYeigP7LoE4tn2Sscwn5g7PyCfcBc1V4ffRHY3Kxqq6VocSCUTncpVeUskaDKuTAWtdB9VTBGW7iG1cd7Zm1dYgur3CiemkGjRUAj9bL3xTEuyaKGYSDhtpFZFp99HQX57EawhiRHk3qq4hjWX\" } } make_uri \u00b6 Create a payment URI using the official URI spec. Alias: None . Inputs: address - string; Wallet address amount - unsigned int; (optional) the integer amount to receive, in atomic units payment_id - string; (optional) 16 or 64 character hexadecimal payment id recipient_name - string; (optional) name of the payment recipient tx_description - string; (optional) Description of the reason for the tx Outputs: uri - string; This contains all the payment input information as a properly formatted payment URI Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"make_uri\",\"params\":{\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"amount\":10,\"payment_id\":\"420fa29b2d9a49f5\",\"tx_description\":\"Testing out the make_uri function.\",\"recipient_name\":\"el00ruobuob Stagenet wallet\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"uri\": \"monero:55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt?tx_payment_id=420fa29b2d9a49f5&tx_amount=0.000000000010&recipient_name=el00ruobuob%20Stagenet%20wallet&tx_description=Testing%20out%20the%20make_uri%20function.\" } } open_wallet \u00b6 Open a wallet. You need to have set the argument \"\u2013wallet-dir\" when launching monero-wallet-rpc to make this work. Alias: None . Inputs: filename - string; wallet name stored in \u2013wallet-dir. password - string; (Optional) only needed if the wallet has a password defined. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"open_wallet\",\"params\":{\"filename\":\"mytestwallet\",\"password\":\"mytestpassword\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } parse_uri \u00b6 Parse a payment URI to get payment information. Alias: None . Inputs: uri - string; This contains all the payment input information as a properly formatted payment URI Outputs: uri - JSON object containing payment information: address - string; Wallet address amount - unsigned int; Decimal amount to receive, in coin units (0 if not provided) payment_id - string; 16 or 64 character hexadecimal payment id (empty if not provided) recipient_name - string; Name of the payment recipient (empty if not provided) tx_description - string; Description of the reason for the tx (empty if not provided) Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"parse_uri\",\"params\":{\"uri\":\"monero:55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt?tx_payment_id=420fa29b2d9a49f5&tx_amount=0.000000000010&recipient_name=el00ruobuob%20Stagenet%20wallet&tx_description=Testing%20out%20the%20make_uri%20function.\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"uri\": { \"address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\", \"amount\": 10, \"payment_id\": \"420fa29b2d9a49f5\", \"recipient_name\": \"el00ruobuob Stagenet wallet\", \"tx_description\": \"Testing out the make_uri function.\" } } } prepare_multisig \u00b6 Prepare a wallet for multisig by generating a multisig string to share with peers. Alias: None . Inputs: None . Outputs: multisig_info - string; Multisig string to share with peers to create the multisig wallet. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"prepare_multisig\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"multisig_info\": \"MultisigV1BFdxQ653cQHB8wsj9WJQd2VdnjxK89g5M94dKPBNw22reJnyJYKrz6rJeXdjFwJ3Mz6n4qNQLd6eqUZKLiNzJFi3UPNVcTjtkG2aeSys9sYkvYYKMZ7chCxvoEXVgm74KKUcUu4V8xveCBFadFuZs8shnxBWHbcwFr5AziLr2mE7KHJT\" } } query_key \u00b6 Return the spend or view private key. Alias: None . Inputs: key_type - string; Which key to retrieve: \"mnemonic\" - the mnemonic seed (older wallets do not have one) OR \"view_key\" - the view key Outputs: key - string; The view key will be hex encoded, while the mnemonic will be a string of words. Example (Query view key): $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"query_key\",\"params\":{\"key_type\":\"view_key\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"key\": \"0a1a38f6d246e894600a3e27238a064bf5e8d91801df47a17107596b1378e501\" } } Example (Query mnemonic key): $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"query_key\",\"params\":{\"key_type\":\"mnemonic\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"key\": \"vocal either anvil films dolphin zeal bacon cuisine quote syndrome rejoices envy okay pancakes tulips lair greater petals organs enmity dedicated oust thwart tomorrow tomorrow\" } } refresh \u00b6 Refresh a wallet after openning. Alias: None . Inputs: start_height - unsigned int; (Optional) The block height from which to start refreshing. Outputs: blocks_fetched - unsigned int; Number of new blocks scanned. received_money - boolean; States if transactions to the wallet have been found in the blocks. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"refresh\",\"params\":{\"start_height\":100000}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"blocks_fetched\": 24, \"received_money\": true } } relay_tx \u00b6 Relay a transaction previously created with \"do_not_relay\":true . Alias: None . Inputs: hex - string; transaction metadata returned from a transfer method with get_tx_metadata set to true . Outputs: tx_hash - String for the publically searchable transaction hash. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"relay_tx\",\"params\":{\"hex\":\"...tx_metadata...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_hash\": \"1c42dcc5672bb09bccf33fb1e9ab4a498af59a6dbd33b3d0cfb289b9e0e25fa5\" } } rescan_blockchain \u00b6 Rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself. This includes destination addresses, tx secret keys, tx notes, etc. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"rescan_blockchain\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } rescan_spent \u00b6 Rescan the blockchain for spent outputs. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"rescan_spent\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } set_account_tag_description \u00b6 Set description for an account tag. Alias: None . Inputs: tag - string; Set a description for this tag. description - string; Description for the tag. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"set_account_tag_description\",\"params\":{\"tag\":\"myTag\",\"description\":\"Test tag\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } set_attribute \u00b6 Set arbitrary attribute. Alias: None . Inputs: key - string; attribute name value - string; attribute value Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"set_attribute\",\"params\":{\"key\":\"my_attribute\",\"value\":\"my_value\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } set_tx_notes \u00b6 Set arbitrary string notes for transactions. Alias: None . Inputs: txids - array of string; transaction ids notes - array of string; notes for the transactions Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"set_tx_notes\",\"params\":{\"txids\":[\"3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f\"],\"notes\":[\"This is an example\"]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } sign \u00b6 Sign a string. Alias: None . Inputs: data - string; Anything you need to sign. Outputs: signature - string; Signature generated against the \"data\" and the account public address. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sign\",\"params\":{\"data\":\"This is sample data to be signed\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signature\": \"SigV14K6G151gycjiGxjQ74tKX6A2LwwghvuHjcDeuRFQio5LS6Gb27BNxjYQY1dPuUvXkEbGQUkiHSVLPj4nJAHRrrw3\" } } sign_multisig \u00b6 Sign a transaction in multisig. Alias: None . Inputs: tx_data_hex - string; Multisig transaction in hex format, as returned by transfer under multisig_txset . Outputs: tx_data_hex - string; Multisig transaction in hex format. tx_hash_list - array of string; List of transaction Hash. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sign_multisig\",\"params\":{\"tx_data_hex\":\"...multisig_txset...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_data_hex\": \"...multisig_txset...\", \"tx_hash_list\": [\"4996091b61c1be112c1097fd5e97d8ff8b28f0e5e62e1137a8c831bacf034f2d\"] } } sign_transfer \u00b6 Sign a transaction created on a read-only wallet (in cold-signing process) Alias: None . Inputs: unsigned_txset - string. Set of unsigned tx returned by \"transfer\" or \"transfer_split\" methods. export_raw - boolean; (Optional) If true, return the raw transaction data. (Defaults to false) Outputs: signed_txset - string. Set of signed tx to be used for submitting transfer. tx_hash_list - array of: string. The tx hashes of every transaction. tx_raw_list - array of: string. The tx raw data of every transaction. In the example below, we first generate an unsigned_txset on a read only wallet before signing it: Generate unsigned_txset using the above \"transfer\" method on read-only wallet: curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"transfer\",\"params\":{\"destinations\":[{\"amount\":1000000000000,\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"}],\"account_index\":0,\"subaddr_indices\":[0],\"priority\":0,\"ring_size\":7,\"do_not_relay\":true,\"get_tx_hex\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount\": 1000000000000, \"fee\": 15202740000, \"multisig_txset\": \"\", \"tx_blob\": \"...long_hex...\", \"tx_hash\": \"c648ba0a049e5ce4ec21361dbf6e4b21eac0f828eea9090215de86c76b31d0a4\", \"tx_key\": \"\", \"tx_metadata\": \"\", \"unsigned_txset\": \"...long_hex...\" } } Sign tx using the previously generated unsigned_txset $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sign_transfer\",\"params\":{\"unsigned_txset\":...long_hex...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signed_txset\": \"...long_hex...\", \"tx_hash_list\": [\"ff2e2d49fbfb1c9a55754f786576e171c8bf21b463a74438df604b7fa6cebc6d\"] } } split_integrated_address \u00b6 Retrieve the standard address and payment id corresponding to an integrated address. Alias: None . Inputs: integrated_address - string Outputs: is_subaddress - boolean; States if the address is a subaddress payment - string; hex encoded standard_address - string Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"split_integrated_address\",\"params\":{\"integrated_address\": \"5F38Rw9HKeaLQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZXCkbHUXdPHyiUeRyokn\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"is_subaddress\": false, \"payment_id\": \"420fa29b2d9a49f5\", \"standard_address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\" } } start_mining \u00b6 Start mining in the Monero daemon. Alias: None . Inputs: threads_count - unsigned int; Number of threads created for mining. do_background_mining - boolean; Allow to start the miner in smart mining mode. ignore_battery - boolean; Ignore battery status (for smart mining only) Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"start_mining\",\"params\":{\"threads_count\":1,\"do_background_mining\":true,\"ignore_battery\":false}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } stop_mining \u00b6 Stop mining in the Monero daemon. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"stop_mining\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } stop_wallet \u00b6 Stops the wallet, storing the current state. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"stop_wallet\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } store \u00b6 Save the wallet file. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"store\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } submit_multisig \u00b6 Submit a signed multisig transaction. Alias: None . Inputs: tx_data_hex - string; Multisig transaction in hex format, as returned by sign_multisig under tx_data_hex . Outputs: tx_hash_list - array of string; List of transaction Hash. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"submit_multisig\",\"params\":{\"tx_data_hex\":\"...tx_data_hex...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_hash_list\": [\"4996091b61c1be112c1097fd5e97d8ff8b28f0e5e62e1137a8c831bacf034f2d\"] } } submit_transfer \u00b6 Submit a previously signed transaction on a read-only wallet (in cold-signing process). Alias: None . Inputs: tx_data_hex - string; Set of signed tx returned by \"sign_transfer\" Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. In the example below, we submit the transfer using the signed_txset generated above: curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"submit_transfer\",\"params\":{\"tx_data_hex\":...long_hex...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_hash_list\": [\"40fad7c828bb383ac02648732f7afce9adc520ba5629e1f5d9c03f584ac53d74\"] } } sweep_all \u00b6 Send all unlocked balance to an address. Alias: None . Inputs: address - string; Destination public address. account_index - unsigned int; Sweep transactions from this account. subaddr_indices - array of unsigned int; (Optional) Sweep from this set of subaddresses in the account. priority - unsigned int; (Optional) Priority for sending the sweep transfer, partially determines fee. mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing). ring_size - unsigned int; Sets ringsize to n (mixin + 1). unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock). payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction. get_tx_keys - boolean; (Optional) Return the transaction keys after sending. below_amount - unsigned int; (Optional) Include outputs below this amount. do_not_relay - boolean; (Optional) If true, do not relay this sweep transfer. (Defaults to false) get_tx_hex - boolean; (Optional) return the transactions as hex encoded string. (Defaults to false) get_tx_metadata - boolean; (Optional) return the transaction metadata as a string. (Defaults to false) Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. tx_key_list - array of: string. The transaction keys for every transaction. amount_list - array of: integer. The amount transferred for every transaction. fee_list - array of: integer. The amount of fees paid for every transaction. tx_blob_list - array of: string. The tx as hex string for every transaction. tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later. multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig). unsigned_txset - string. Set of unsigned tx for cold-signing purposes. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sweep_all\",\"params\":{\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"subaddr_indices\":[4],\"ring_size\":7,\"unlock_time\":0,\"get_tx_keys\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount_list\": [9985885770000], \"fee_list\": [14114230000], \"multisig_txset\": \"\", \"tx_hash_list\": [\"ab4b6b65cc8cd8c9dd317d0b90d97582d68d0aa1637b0065b05b61f9a66ea5c5\"], \"tx_key_list\": [\"b9b4b39d3bb3062ddb85ec0266d4df39058f4c86077d99309f218ce4d76af607\"], \"unsigned_txset\": \"\" } } sweep_dust \u00b6 Send all dust outputs back to the wallet's, to make them easier to spend (and mix). Alias: sweep_unmixable . Inputs: get_tx_keys - boolean; (Optional) Return the transaction keys after sending. do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the monero network. (Defaults to false) get_tx_hex - boolean; (Optional) Return the transactions as hex string after sending. (Defaults to false) get_tx_metadata - boolean; (Optional) Return list of transaction metadata needed to relay the transfer later. (Defaults to false) Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. tx_key_list - array of: string. The transaction keys for every transaction. amount_list - array of: integer. The amount transferred for every transaction. fee_list - array of: integer. The amount of fees paid for every transaction. tx_blob_list - array of: string. The tx as hex string for every transaction. tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later. multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig). unsigned_txset - string. Set of unsigned tx for cold-signing purposes. Example (In this example, sweep_dust returns nothing because there are no funds to sweep): $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sweep_dust\",\"params\":{\"get_tx_keys\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"multisig_txset\": \"\", \"unsigned_txset\": \"\" } } sweep_single \u00b6 Send all of a specific unlocked output to an address. Alias: None . Inputs: address - string; Destination public address. account_index - unsigned int; Sweep transactions from this account. subaddr_indices - array of unsigned int; (Optional) Sweep from this set of subaddresses in the account. priority - unsigned int; (Optional) Priority for sending the sweep transfer, partially determines fee. mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing). ring_size - unsigned int; Sets ringsize to n (mixin + 1). unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock). payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction. get_tx_keys - boolean; (Optional) Return the transaction keys after sending. key_image - string; Key image of specific output to sweep. below_amount - unsigned int; (Optional) Include outputs below this amount. do_not_relay - boolean; (Optional) If true, do not relay this sweep transfer. (Defaults to false) get_tx_hex - boolean; (Optional) return the transactions as hex encoded string. (Defaults to false) get_tx_metadata - boolean; (Optional) return the transaction metadata as a string. (Defaults to false) Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. tx_key_list - array of: string. The transaction keys for every transaction. amount_list - array of: integer. The amount transferred for every transaction. fee_list - array of: integer. The amount of fees paid for every transaction. tx_blob_list - array of: string. The tx as hex string for every transaction. tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later. multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig). unsigned_txset - string. Set of unsigned tx for cold-signing purposes. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sweep_single\",\"params\":{\"address\":\"74Jsocx8xbpTBEjm3ncKE5LBQbiJouyCDaGhgSiebpvNDXZnTAbW2CmUR5SsBeae2pNk9WMVuz6jegkC4krUyqRjA6VjoLD\",\"ring_size\":7,\"unlock_time\":0,\"key_image\":\"a7834459ef795d2efb6f665d2fd758c8d9288989d8d4c712a68f8023f7804a5e\",\"get_tx_keys\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount\": 27126892247503, \"fee\": 14111630000, \"multisig_txset\": \"\", \"tx_blob\": \"\", \"tx_hash\": \"106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b\", \"tx_key\": \"\", \"tx_metadata\": \"\", \"unsigned_txset\": \"\" } } tag_accounts \u00b6 Apply a filtering tag to a list of accounts. Alias: None . Inputs: tag - string; Tag for the accounts. accounts - array of unsigned int; Tag this list of accounts. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"tag_accounts\",\"params\":{\"tag\":\"myTag\",\"accounts\":[0,1]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } transfer \u00b6 Send monero to a number of recipients. Alias: None . Inputs: destinations - array of destinations to receive XMR: amount - unsigned int; Amount to send to each destination, in atomic units. address - string; Destination public address. account_index - unsigned int; (Optional) Transfer from this account index. (Defaults to 0) subaddr_indices - array of unsigned int; (Optional) Transfer from this set of subaddresses. (Defaults to 0) priority - unsigned int; Set a priority for the transaction. Accepted Values are: 0-3 for: default, unimportant, normal, elevated, priority. mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing). ring_size - unsigned int; Number of outputs to mix in the transaction (this output + N decoys from the blockchain). unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock). payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction. get_tx_key - boolean; (Optional) Return the transaction key after sending. do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the monero network. (Defaults to false) get_tx_hex - boolean; Return the transaction as hex string after sending (Defaults to false) get_tx_metadata - boolean; Return the metadata needed to relay the transaction. (Defaults to false) Outputs: amount - Amount transferred for the transaction. fee - Integer value of the fee charged for the txn. multisig_txset - Set of multisig transactions in the process of being signed (empty for non-multisig). tx_blob - Raw transaction represented as hex string, if get_tx_hex is true. tx_hash - String for the publically searchable transaction hash. tx_key - String for the transaction key if get_tx_key is true, otherwise, blank string. tx_metadata - Set of transaction metadata needed to relay this transfer later, if get_tx_metadata is true. unsigned_txset - String. Set of unsigned tx for cold-signing purposes. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"transfer\",\"params\":{\"destinations\":[{\"amount\":100000000000,\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"},{\"amount\":200000000000,\"address\":\"75sNpRwUtekcJGejMuLSGA71QFuK1qcCVLZnYRTfQLgFU5nJ7xiAHtR5ihioS53KMe8pBhH61moraZHyLoG4G7fMER8xkNv\"}],\"account_index\":0,\"subaddr_indices\":[0],\"priority\":0,\"ring_size\":7,\"get_tx_key\": true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount\": 300000000000, \"fee\": 86897600000, \"multisig_txset\": \"\", \"tx_blob\": \"\", \"tx_hash\": \"7663438de4f72b25a0e395b770ea9ecf7108cd2f0c4b75be0b14a103d3362be9\", \"tx_key\": \"25c9d8ec20045c80c93d665c9d3684aab7335f8b2cd02e1ba2638485afd1c70e236c4bdd7a2f1cb511dbf466f13421bdf8df988b7b969c448ca6239d7251490e4bf1bbf9f6ffacffdcdc93b9d1648ec499eada4d6b4e02ce92d4a1c0452e5d009fbbbf15b549df8856205a4c7bda6338d82c823f911acd00cb75850b198c5803\", \"tx_metadata\": \"\", \"unsigned_txset\": \"\" } } transfer_split \u00b6 Same as transfer, but can split into more than one tx if necessary. Alias: None . Inputs: destinations - array of destinations to receive XMR: amount - unsigned int; Amount to send to each destination, in atomic units. address - string; Destination public address. account_index - unsigned int; (Optional) Transfer from this account index. (Defaults to 0) subaddr_indices - array of unsigned int; (Optional) Transfer from this set of subaddresses. (Defaults to 0) mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing). ring_size - unsigned int; Sets ringsize to n (mixin + 1). unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock). payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction. get_tx_keys - boolean; (Optional) Return the transaction keys after sending. priority - unsigned int; Set a priority for the transactions. Accepted Values are: 0-3 for: default, unimportant, normal, elevated, priority. do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the monero network. (Defaults to false) get_tx_hex - boolean; Return the transactions as hex string after sending new_algorithm - boolean; True to use the new transaction construction algorithm, defaults to false. get_tx_metadata - boolean; Return list of transaction metadata needed to relay the transfer later. Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. tx_key_list - array of: string. The transaction keys for every transaction. amount_list - array of: integer. The amount transferred for every transaction. fee_list - array of: integer. The amount of fees paid for every transaction. tx_blob_list - array of: string. The tx as hex string for every transaction. tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later. multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig). unsigned_txset - string. Set of unsigned tx for cold-signing purposes. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"transfer_split\",\"params\":{\"destinations\":[{\"amount\":1000000000000,\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"},{\"amount\":2000000000000,\"address\":\"75sNpRwUtekcJGejMuLSGA71QFuK1qcCVLZnYRTfQLgFU5nJ7xiAHtR5ihioS53KMe8pBhH61moraZHyLoG4G7fMER8xkNv\"}],\"account_index\":0,\"subaddr_indices\":[0],\"priority\":0,\"ring_size\":7,\"get_tx_key\": true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount_list\": [3000000000000], \"fee_list\": [85106400000], \"multisig_txset\": \"\", \"tx_hash_list\": [\"c8d815f48f27d53fdaf198a74b292a91bfaf87529a9a9a9ee66079a890b3b58b\"], \"unsigned_txset\": \"\" } } untag_accounts \u00b6 Remove filtering tag from a list of accounts. Alias: None . Inputs: accounts - array of unsigned int; Remove tag from this list of accounts. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"untag_accounts\",\"params\":{\"accounts\":[1]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } } verify \u00b6 Verify a signature on a string. Alias: None . Inputs: data - string; What should have been signed. address - string; Public address of the wallet used to sign the data. signature - string; signature generated by sign method. Outputs: good - boolean; Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"verify\",\"params\":{\"data\":\"This is sample data to be signed\",\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"signature\":\"SigV14K6G151gycjiGxjQ74tKX6A2LwwghvuHjcDeuRFQio5LS6Gb27BNxjYQY1dPuUvXkEbGQUkiHSVLPj4nJAHRrrw3\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"good\": true } } Sources: \u00b6 Reworked from GetMonero.org","title":"monero-wallet-rpc"},{"location":"interacting/monero-wallet-rpc-reference/#monero-wallet-rpc-reference","text":"","title":"monero-wallet-rpc - Reference"},{"location":"interacting/monero-wallet-rpc-reference/#introduction","text":"This is a list of the monero-wallet-rpc calls, their inputs and outputs, and examples of each. The program monero-wallet-rpc replaced the rpc interface that was in simplewallet and then monero-wallet-cli. All monero-wallet-rpc methods use the same JSON RPC interface. For example: IP = 127 .0.0.1 PORT = 18082 METHOD = \"make_integrated_address\" PARAMS = \"{\\\"payment_id\\\":\\\"1234567890123456789012345678900012345678901234567890123456789000\\\"}\" curl \\ -X POST http:// $IP : $PORT /json_rpc \\ -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"' $METHOD '\",\"params\":' \" $PARAMS \" '}' \\ -H 'Content-Type: application/json' If the monero-wallet-rpc was executed with the --rpc-login argument as username:password , then follow this example: IP = 127 .0.0.1 PORT = 18082 METHOD = \"make_integrated_address\" PARAMS = \"{\\\"payment_id\\\":\\\"1234567890123456789012345678900012345678901234567890123456789000\\\"}\" curl \\ -u username:password --digest \\ -X POST http:// $IP : $PORT /json_rpc \\ -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"' $METHOD '\",\"params\":' \" $PARAMS \" '}' \\ -H 'Content-Type: application/json' Note: \"atomic units\" refer to the smallest fraction of 1 XMR according to the monerod implementation. 1 XMR = 1e12 atomic units.","title":"Introduction"},{"location":"interacting/monero-wallet-rpc-reference/#index-of-json-rpc-methods","text":"add_address_book change_wallet_password check_reserve_proof check_spend_proof check_tx_key check_tx_proof close_wallet create_account create_address create_wallet delete_address_book export_key_images export_multisig_info export_outputs finalize_multisig get_accounts get_account_tags get_address_book get_address get_address_index get_attribute get_balance get_bulk_payments get_height get_languages get_payments get_reserve_proof get_spend_proof get_transfer_by_txid get_transfers get_tx_key get_tx_notes get_tx_proof get_version import_key_images import_multisig_info import_outputs incoming_transfers is_multisig label_account label_address make_integrated_address make_multisig make_uri open_wallet parse_uri prepare_multisig query_key refresh relay_tx rescan_blockchain rescan_spent set_account_tag_description set_attribute set_tx_notes sign_multisig sign sign_transfer split_integrated_address start_mining stop_mining stop_wallet store submit_multisig submit_transfer sweep_all sweep_dust sweep_single tag_accounts transfer_split transfer untag_accounts verify","title":"Index of JSON RPC Methods:"},{"location":"interacting/monero-wallet-rpc-reference/#json-rpc-methods","text":"","title":"JSON RPC Methods:"},{"location":"interacting/monero-wallet-rpc-reference/#add_address_book","text":"Add an entry to the address book. Alias: None . Inputs: address - string; payment_id - (optional) string, defaults to \"0000000000000000000000000000000000000000000000000000000000000000\"; description - (optional) string, defaults to \"\"; Outputs: index - unsigned int; The index of the address book entry. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"add_address_book\",\"params\":{\"address\":\"78P16M3XmFRGcWFCcsgt1WcTntA1jzcq31seQX1Eg92j8VQ99NPivmdKam4J5CKNAD7KuNWcq5xUPgoWczChzdba5WLwQ4j\",\"description\":\"Third account\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"index\" : 1 } }","title":"add_address_book"},{"location":"interacting/monero-wallet-rpc-reference/#change_wallet_password","text":"Change a wallet password. Alias: None . Inputs: old_password - string; (Optional) Current wallet password, if defined. new_password - string; (Optional) New wallet password, if not blank. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"change_wallet_password\",\"params\":{\"old_password\":\"theCurrentSecretPassPhrase\",\"new_password\":\"theNewSecretPassPhrase\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { } }","title":"change_wallet_password"},{"location":"interacting/monero-wallet-rpc-reference/#check_reserve_proof","text":"Proves a wallet has a disposable reserve using a signature. Alias: None . Inputs: address - string; Public address of the wallet. message - string; (Optional) Should be the same message used in get_reserve_proof . signature - string; reserve signature to confirm. Outputs: good - boolean; States if the inputs proves the reserve. In the example below, the reserve has been proven: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_reserve_proof\",\"params\":{\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"signature\":\"ReserveProofV11BZ23sBt9sZJeGccf84mzyAmNCP3KzYbE1111112VKmH111118NfCYJQjZ6c46gT2kXgcHCaSSZeL8sRdzqjqx7i1e7FQfQGu2o113UYFVdwzHQi3iENDPa76Kn1BvywbKz3bMkXdZkBEEhBSF4kjjGaiMJ1ucKb6wvMVC4A8sA4nZEdL2Mk3wBucJCYTZwKqA8i1M113kqakDkG25FrjiDqdQTCYz2wDBmfKxF3eQiV5FWzZ6HmAyxnqTWUiMWukP9A3Edy3ZXqjP1b23dhz7Mbj39bBxe3ZeDNu9HnTSqYvHNRyqCkeUMJpHyQweqjGUJ1DSfFYr33J1E7MkhMnEi1o7trqWjVix32XLetYfePG73yvHbS24837L7Q64i5n1LSpd9yMiQZ3Dyaysi5y6jPx7TpAvnSqBFtuCciKoNzaXoA3dqt9cuVFZTXzdXKqdt3cXcVJMNxY8RvKPVQHhUur94Lpo1nSpxf7BN5a5rHrbZFqoZszsZmiWikYPkLX72XUdw6NWjLrTBxSy7KuPYH86c6udPEXLo2xgN6XHMBMBJzt8FqqK7EcpNUBkuHm2AtpGkf9CABY3oSjDQoRF5n4vNLd3qUaxNsG4XJ12L9gJ7GrK273BxkfEA8fDdxPrb1gpespbgEnCTuZHqj1A\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : true, \"spent\" : 0 , \"total\" : 100000000000 } } In the example below, all wallet reserve has been proven: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_reserve_proof\",\"params\":{\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"message\":\"I have 10 at least\",\"signature\":\"...signature...\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : true, \"spent\" : 0 , \"total\" : 164113855714662789 } } In the example below, the wrong message is used, avoiding the reserve to be proved: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_spend_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"message\":\"wrong message\",\"signature\":\"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : false } }","title":"check_reserve_proof"},{"location":"interacting/monero-wallet-rpc-reference/#check_spend_proof","text":"Prove a spend using a signature. Unlike proving a transaction, it does not requires the destination public address. Alias: None . Inputs: txid - string; transaction id. message - string; (Optional) Should be the same message used in get_spend_proof . signature - string; spend signature to confirm. Outputs: good - boolean; States if the inputs proves the spend. In the example below, the spend has been proven: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_spend_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"message\":\"this is my transaction\",\"signature\":\"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : true } } In the example below, the wrong message is used, avoiding the spend to be proved: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_spend_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"message\":\"wrong message\",\"signature\":\"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"good\" : false } }","title":"check_spend_proof"},{"location":"interacting/monero-wallet-rpc-reference/#check_tx_key","text":"Check a transaction in the blockchain with its secret key. Alias: None . Inputs: txid - string; transaction id. tx_key - string; transaction secret key. address - string; destination public address of the transaction. Outputs: confirmations - unsigned int; Number of block mined after the one with the transaction. in_pool - boolean; States if the transaction is still in pool or has been added to a block. received - unsigned int; Amount of the transaction. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_tx_key\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"tx_key\":\"feba662cf8fb6d0d0da18fc9b70ab28e01cc76311278fdd7fe7ab16360762b06\",\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"confirmations\" : 0 , \"in_pool\" : false, \"received\" : 1000000000000 } }","title":"check_tx_key"},{"location":"interacting/monero-wallet-rpc-reference/#check_tx_proof","text":"Prove a transaction by checking its signature. Alias: None . Inputs: txid - string; transaction id. address - string; destination public address of the transaction. message - string; (Optional) Should be the same message used in get_tx_proof . signature - string; transaction signature to confirm. Outputs: confirmations - unsigned int; Number of block mined after the one with the transaction. good - boolean; States if the inputs proves the transaction. in_pool - boolean; States if the transaction is still in pool or has been added to a block. received - unsigned int; Amount of the transaction. In the example below, the transaction has been proven: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_tx_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\",\"message\":\"this is my transaction\",\"signature\":\"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"confirmations\" : 482 , \"good\" : true, \"in_pool\" : false, \"received\" : 1000000000000 } } In the example below, the wrong message is used, avoiding the transaction to be proved: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"check_tx_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\",\"message\":\"wrong message\",\"signature\":\"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"confirmations\" : 0 , \"good\" : false, \"in_pool\" : false, \"received\" : 0 } }","title":"check_tx_proof"},{"location":"interacting/monero-wallet-rpc-reference/#close_wallet","text":"Close the currently opened wallet, after trying to save it. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"close_wallet\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { } }","title":"close_wallet"},{"location":"interacting/monero-wallet-rpc-reference/#create_account","text":"Create a new account with an optional label. Alias: None . Inputs: label - string; (Optional) Label for the account. Outputs: account_index - unsigned int; Index of the new account. address - string; Address for this account. Base58 representation of the public keys. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"create_account\",\"params\":{\"label\":\"Secondary account\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"account_index\" : 1 , \"address\" : \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\" } }","title":"create_account"},{"location":"interacting/monero-wallet-rpc-reference/#create_address","text":"Create a new address for an account. Optionally, label the new address. Alias: None . Inputs: account_index - unsigned int; Create a new address for this account. label - string; (Optional) Label for the new address. Outputs: address - string; Newly created address. Base58 representation of the public keys. address_index - unsigned int; Index of the new address under the input account. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"create_address\",\"params\":{\"account_index\":0,\"label\":\"new-sub\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"address\" : \"7BG5jr9QS5sGMdpbBrZEwVLZjSKJGJBsXdZLt8wiXyhhLjy7x2LZxsrAnHTgD8oG46ZtLjUGic2pWc96GFkGNPQQDA3Dt7Q\" , \"address_index\" : 5 } }","title":"create_address"},{"location":"interacting/monero-wallet-rpc-reference/#create_wallet","text":"Create a new wallet. You need to have set the argument \"\u2013wallet-dir\" when launching monero-wallet-rpc to make this work. Alias: None . Inputs: filename - string; Wallet file name. password - string; (Optional) password to protect the wallet. language - string; Language for your wallets' seed. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"create_wallet\",\"params\":{\"filename\":\"mytestwallet\",\"password\":\"mytestpassword\",\"language\":\"English\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { } }","title":"create_wallet"},{"location":"interacting/monero-wallet-rpc-reference/#delete_address_book","text":"Delete an entry from the address book. Alias: None . Inputs: index - unsigned int; The index of the address book entry. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"delete_address_book\",\"params\":{\"index\":1}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { } }","title":"delete_address_book"},{"location":"interacting/monero-wallet-rpc-reference/#export_key_images","text":"Export a signed set of key images. Alias: None . Inputs: None . Outputs: signed_key_images - array of signed key images: key_image - string; signature - string; Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"export_key_images\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"signed_key_images\" : [{ \"key_image\" : \"cd35239b72a35e26a57ed17400c0b66944a55de9d5bda0f21190fed17f8ea876\" , \"signature\" : \"c9d736869355da2538ab4af188279f84138c958edbae3c5caf388a63cd8e780b8c5a1aed850bd79657df659422c463608ea4e0c730ba9b662c906ae933816d00\" } , { \"key_image\" : \"65158a8ee5a3b32009b85a307d85b375175870e560e08de313531c7dbbe6fc19\" , \"signature\" : \"c96e40d09dfc45cfc5ed0b76bfd7ca793469588bb0cf2b4d7b45ef23d40fd4036057b397828062e31700dc0c2da364f50cd142295a8405b9fe97418b4b745d0c\" } ,... ] } }","title":"export_key_images"},{"location":"interacting/monero-wallet-rpc-reference/#export_multisig_info","text":"Export multisig info for other participants. Alias: None . Inputs: None . Outputs: info - string; Multisig info in hex format for other participants. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"export_multisig_info\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"info\" : \"4d6f6e65726f206d756c7469736967206578706f72740105cf6442b09b75f5eca9d846771fe1a879c9a97ab0553ffbcec64b1148eb7832b51e7898d7944c41cee000415c5a98f4f80dc0efdae379a98805bb6eacae743446f6f421cd03e129eb5b27d6e3b73eb6929201507c1ae706c1a9ecd26ac8601932415b0b6f49cbbfd712e47d01262c59980a8f9a8be776f2bf585f1477a6df63d6364614d941ecfdcb6e958a390eb9aa7c87f056673d73bc7c5f0ab1f74a682e902e48a3322c0413bb7f6fd67404f13fb8e313f70a0ce568c853206751a334ef490068d3c8ca0e\" } }","title":"export_multisig_info"},{"location":"interacting/monero-wallet-rpc-reference/#export_outputs","text":"Export all outputs in hex format. Alias: None . Inputs: None . Outputs: outputs_data_hex - string; wallet outputs in hex format. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"export_outputs\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"outputs_data_hex\" : \"...outputs...\" } }","title":"export_outputs"},{"location":"interacting/monero-wallet-rpc-reference/#finalize_multisig","text":"Turn this wallet into a multisig wallet, extra step for N-1/N wallets. Alias: None . Inputs: multisig_info - array of string; List of multisig string from peers. password - string; Wallet password Outputs: address - string; multisig wallet address. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"finalize_multisig\",\"params\":{\"multisig_info\":[\"MultisigxV1JNC6Ja2oBt5Sqea9LN2YEF7WYZCpHqr2EKvPG89Trf3X4E8RWkLaGRf29fJ3stU471MELKxwufNYeigP7LoE4tn2McPr4SbL9q15xNvZT5uwC9YRr7UwjXqSZHmTWN9PBuZEKVAQ4HPPyQciSCdNjgwsuFRBzrskMdMUwNMgKst1debYfm37i6PSzDoS2tk4kYTYj83kkAdR7kdshet1axQPd6HQ\",\"MultisigxV1Unma7Ko4zdd8Ps3Af4oZwtj2JdWKzwNfP6s2G9ZvXhMoSscwn5g7PyCfcBc1V4ffRHY3Kxqq6VocSCUTncpVeUskMcPr4SbL9q15xNvZT5uwC9YRr7UwjXqSZHmTWN9PBuZE1LTpWxLoC3vPMSrqVVcjnmL9LYfdCZz3fECjNZbCEDq3PHDiUuY5jurQTcNoGhDTio5WM9xaAdim9YByiS5KyqF4\"]}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"address\" : \"5B9gZUTDuHTcGGuY3nL3t8K2tDnEHeRVHSBQgLZUTQxtFYVLnho5JJjWJyFp5YZgZRQ44RiviJi1sPHgLVMbckRsDqDx1gV\" } }","title":"finalize_multisig"},{"location":"interacting/monero-wallet-rpc-reference/#get_account_tags","text":"Get a list of user-defined account tags. Alias: None . Inputs: None . Outputs: account_tags - array of account tag information: tag - string; Filter tag. label - string; Label for the tag. accounts - array of int; List of tagged account indices. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_account_tags\",\"params\":\"\"}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"account_tags\" : [{ \"accounts\" : [ 0 ] , \"label\" : \"Test tag\" , \"tag\" : \"myTag\" }] } }","title":"get_account_tags"},{"location":"interacting/monero-wallet-rpc-reference/#get_accounts","text":"Get all accounts for a wallet. Optionally filter accounts by tag. Alias: None . Inputs: tag - string; (Optional) Tag for filtering accounts. Outputs: subaddress_accounts - array of subaddress account information: account_index - unsigned int; Index of the account. balance - unsigned int; Balance of the account (locked or unlocked). base_address - string; Base64 representation of the first subaddress in the account. label - string; (Optional) Label of the account. tag - string; (Optional) Tag for filtering accounts. unlocked_balance - unsigned int; Unlocked balance for the account. total_balance - unsigned int; Total balance of the selected accounts (locked or unlocked). total_unlocked_balance - unsigned int; Total unlocked balance of the selected accounts. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_accounts\",\"params\":{\"tag\":\"myTag\"}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"subaddress_accounts\" : [{ \"account_index\" : 0 , \"balance\" : 157663195572433688 , \"base_address\" : \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\" , \"label\" : \"Primary account\" , \"tag\" : \"myTag\" , \"unlocked_balance\" : 157443303037455077 } , { \"account_index\" : 1 , \"balance\" : 0 , \"base_address\" : \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\" , \"label\" : \"Secondary account\" , \"tag\" : \"myTag\" , \"unlocked_balance\" : 0 }] , \"total_balance\" : 157663195572433688 , \"total_unlocked_balance\" : 157443303037455077 } }","title":"get_accounts"},{"location":"interacting/monero-wallet-rpc-reference/#get_address","text":"Return the wallet's addresses for an account. Optionally filter for specific set of subaddresses. Alias: getaddress . Inputs: account_index - unsigned int; Return subaddresses for this account. address_index - array of unsigned int; (Optional) List of subaddresses to return from an account. Outputs: address - string; The 95-character hex address string of the monero-wallet-rpc in session. addresses array of addresses informations address string; The 95-character hex (sub)address string. label string; Label of the (sub)address address_index unsigned int; index of the subaddress used boolean; states if the (sub)address has already received funds Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_address\",\"params\":{\"account_index\":0,\"address_index\":[0,1,4]}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"address\" : \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\" , \"addresses\" : [{ \"address\" : \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\" , \"address_index\" : 0 , \"label\" : \"Primary account\" , \"used\" : true } , { \"address\" : \"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\" , \"address_index\" : 1 , \"label\" : \"\" , \"used\" : true } , { \"address\" : \"77xa6Dha7kzCQuvmd8iB5VYoMkdenwCNRU9khGhExXQ8KLL3z1N1ZATBD1sFPenyHWT9cm4fVFnCAUApY53peuoZFtwZiw5\" , \"address_index\" : 4 , \"label\" : \"test2\" , \"used\" : true }] } }","title":"get_address"},{"location":"interacting/monero-wallet-rpc-reference/#get_address_book","text":"Retrieves entries from the address book. Alias: None . Inputs: entries - array of unsigned int; indices of the requested address book entries Outputs: entries - array of entries: address - string; Public address of the entry description - string; Description of this address entry index - unsigned int; payment_id - string; Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_address_book\",\"params\":{\"entries\":[0,1]}}' -H 'Content-Type: application/json' { \"id\" : \"0\" , \"jsonrpc\" : \"2.0\" , \"result\" : { \"entries\" : [{ \"address\" : \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\" , \"description\" : \"Second account\" , \"index\" : 0 , \"payment_id\" : \"0000000000000000000000000000000000000000000000000000000000000000\" } , { \"address\" : \"78P16M3XmFRGcWFCcsgt1WcTntA1jzcq31seQX1Eg92j8VQ99NPivmdKam4J5CKNAD7KuNWcq5xUPgoWczChzdba5WLwQ4j\" , \"description\" : \"Third account\" , \"index\" : 1 , \"payment_id\" : \"0000000000000000000000000000000000000000000000000000000000000000\" }] } }","title":"get_address_book"},{"location":"interacting/monero-wallet-rpc-reference/#get_address_index","text":"Get account and address indexes from a specific (sub)address Alias: None . Inputs: address - String; (sub)address to look for. Outputs: index - subaddress informations major unsigned int; Account index. minor unsigned int; Address index. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_address_index\",\"params\":{\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"index\": { \"major\": 0, \"minor\": 1 } } }","title":"get_address_index"},{"location":"interacting/monero-wallet-rpc-reference/#get_attribute","text":"Get attribute value by name. Alias: None . Inputs: key - string; attribute name Outputs: value - string; attribute value Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_attribute\",\"params\":{\"key\":\"my_attribute\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"value\": \"my_value\" } }","title":"get_attribute"},{"location":"interacting/monero-wallet-rpc-reference/#get_bulk_payments","text":"Get a list of incoming payments using a given payment id, or a list of payments ids, from a given height. This method is the preferred method over get_payments because it has the same functionality but is more extendable. Either is fine for looking up transactions by a single payment ID. Alias: None . Inputs: payment_ids - array of: string; Payment IDs used to find the payments (16 characters hex). min_block_height - unsigned int; The block height at which to start looking for payments. Outputs: payments - list of: payment_id - string; Payment ID matching one of the input IDs. tx_hash - string; Transaction hash used as the transaction ID. amount - unsigned int; Amount for this payment. block_height - unsigned int; Height of the block that first confirmed this payment. unlock_time - unsigned int; Time (in block height) until this payment is safe to spend. subaddr_index - subaddress index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress in the account. address - string; Address receiving the payment; Base58 representation of the public keys. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_bulk_payments\",\"params\":{\"payment_ids\":[\"60900e5603bf96e3\"],\"min_block_height\":\"120000\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"payments\": [{ \"address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\", \"amount\": 1000000000000, \"block_height\": 127606, \"payment_id\": \"60900e5603bf96e3\", \"subaddr_index\": { \"major\": 0, \"minor\": 0 }, \"tx_hash\": \"3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f\", \"unlock_time\": 0 }] } }","title":"get_bulk_payments"},{"location":"interacting/monero-wallet-rpc-reference/#get_height","text":"Returns the wallet's current block height. Alias: getheight . Inputs: None . Outputs: height - unsigned int; The current monero-wallet-rpc's blockchain height. If the wallet has been offline for a long time, it may need to catch up with the daemon. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_height\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"height\": 145545 } }","title":"get_height"},{"location":"interacting/monero-wallet-rpc-reference/#get_languages","text":"Get a list of available languages for your wallet's seed. Alias: None . Inputs: None . Outputs: languages - array of string; List of available languages Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_languages\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"languages\": [\"Deutsch\",\"English\",\"Espa\u00f1ol\",\"Fran\u00e7ais\",\"Italiano\",\"Nederlands\",\"Portugu\u00eas\",\"\u0440\u0443\u0441\u0441\u043a\u0438\u0439 \u044f\u0437\u044b\u043a\",\"\u65e5\u672c\u8a9e\",\"\u7b80\u4f53\u4e2d\u6587 (\u4e2d\u56fd)\",\"Esperanto\",\"Lojban\"] } }","title":"get_languages"},{"location":"interacting/monero-wallet-rpc-reference/#get_payments","text":"Get a list of incoming payments using a given payment id. Alias: None . Inputs: payment_id - string; Payment ID used to find the payments (16 characters hex). Outputs: payments - list of: payment_id - string; Payment ID matching the input parameter. tx_hash - string; Transaction hash used as the transaction ID. amount - unsigned int; Amount for this payment. block_height - unsigned int; Height of the block that first confirmed this payment. unlock_time - unsigned int; Time (in block height) until this payment is safe to spend. subaddr_index - subaddress index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress in the account. address - string; Address receiving the payment; Base58 representation of the public keys. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_payments\",\"params\":{\"payment_id\":\"60900e5603bf96e3\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"payments\": [{ \"address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\", \"amount\": 1000000000000, \"block_height\": 127606, \"payment_id\": \"60900e5603bf96e3\", \"subaddr_index\": { \"major\": 0, \"minor\": 0 }, \"tx_hash\": \"3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f\", \"unlock_time\": 0 }] } }","title":"get_payments"},{"location":"interacting/monero-wallet-rpc-reference/#get_reserve_proof","text":"Generate a signature to prove of an available amount in a wallet. Alias: None . Inputs: all - boolean; Proves all wallet balance to be disposable. account_index - unsigned int; Specify the account from witch to prove reserve. (ignored if all is set to true) amount - unsigned int; Amount (in atomic units) to prove the account has for reserve. (ignored if all is set to true) message - string; (Optional) add a message to the signature to further authenticate the prooving process. Outputs: signature - string; reserve signature. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_reserve_proof\",\"params\":{\"all\":false,\"account_index\":0,\"amount\":100000000000}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signature\": \"ReserveProofV11BZ23sBt9sZJeGccf84mzyAmNCP3KzYbE1111112VKmH111118NfCYJQjZ6c46gT2kXgcHCaSSZeL8sRdzqjqx7i1e7FQfQGu2o113UYFVdwzHQi3iENDPa76Kn1BvywbKz3bMkXdZkBEEhBSF4kjjGaiMJ1ucKb6wvMVC4A8sA4nZEdL2Mk3wBucJCYTZwKqA8i1M113kqakDkG25FrjiDqdQTCYz2wDBmfKxF3eQiV5FWzZ6HmAyxnqTWUiMWukP9A3Edy3ZXqjP1b23dhz7Mbj39bBxe3ZeDNu9HnTSqYvHNRyqCkeUMJpHyQweqjGUJ1DSfFYr33J1E7MkhMnEi1o7trqWjVix32XLetYfePG73yvHbS24837L7Q64i5n1LSpd9yMiQZ3Dyaysi5y6jPx7TpAvnSqBFtuCciKoNzaXoA3dqt9cuVFZTXzdXKqdt3cXcVJMNxY8RvKPVQHhUur94Lpo1nSpxf7BN5a5rHrbZFqoZszsZmiWikYPkLX72XUdw6NWjLrTBxSy7KuPYH86c6udPEXLo2xgN6XHMBMBJzt8FqqK7EcpNUBkuHm2AtpGkf9CABY3oSjDQoRF5n4vNLd3qUaxNsG4XJ12L9gJ7GrK273BxkfEA8fDdxPrb1gpespbgEnCTuZHqj1A\" } }","title":"get_reserve_proof"},{"location":"interacting/monero-wallet-rpc-reference/#get_spend_proof","text":"Generate a signature to prove a spend. Unlike proving a transaction, it does not requires the destination public address. Alias: None . Inputs: txid - string; transaction id. message - string; (Optional) add a message to the signature to further authenticate the prooving process. Outputs: signature - string; spend signature. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_spend_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"message\":\"this is my transaction\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signature\": \"SpendProofV1aSh8Todhk54736iXgV6vJAFP7egxByuMWZeyNDaN2JY737S95X5zz5mNMQSuCNSLjjhi5HJCsndpNWSNVsuThxwv285qy1KkUrLFRkxMSCjfL6bbycYN33ScZ5UB4Fzseceo1ndpL393T1q638VmcU3a56dhNHF1RPZFiGPS61FA78nXFSqE9uoKCCoHkEz83M1dQVhxZV5CEPF2P6VioGTKgprLCH9vvj9k1ivd4SX19L2VSMc3zD1u3mkR24ioETvxBoLeBSpxMoikyZ6inhuPm8yYo9YWyFtQK4XYfAV9mJ9knz5fUPXR8vvh7KJCAg4dqeJXTVb4mbMzYtsSZXHd6ouWoyCd6qMALdW8pKhgMCHcVYMWp9X9WHZuCo9rsRjRpg15sJUw7oJg1JoGiVgj8P4JeGDjnZHnmLVa5bpJhVCbMhyM7JLXNQJzFWTGC27TQBbthxCfQaKdusYnvZnKPDJWSeceYEFzepUnsWhQtyhbb73FzqgWC4eKEFKAZJqT2LuuSoxmihJ9acnFK7Ze23KTVYgDyMKY61VXADxmSrBvwUtxCaW4nQtnbMxiPMNnDMzeixqsFMBtN72j5UqhiLRY99k6SE7Qf5f29haNSBNSXCFFHChPKNTwJrehkofBdKUhh2VGPqZDNoefWUwfudeu83t85bmjv8Q3LrQSkFgFjRT5tLo8TMawNXoZCrQpyZrEvnodMDDUUNf3NL7rxyv3gM1KrTWjYaWXFU2RAsFee2Q2MTwUW7hR25cJvSFuB1BX2bfkoCbiMk923tHZGU2g7rSKF1GDDkXAc1EvFFD4iGbh1Q5t6hPRhBV8PEncdcCWGq5uAL5D4Bjr6VXG8uNeCy5oYWNgbZ5JRSfm7QEhPv8Fy9AKMgmCxDGMF9dVEaU6tw2BAnJavQdfrxChbDBeQXzCbCfep6oei6n2LZdE5Q84wp7eoQFE5Cwuo23tHkbJCaw2njFi3WGBbA7uGZaGHJPyB2rofTWBiSUXZnP2hiE9bjJghAcDm1M4LVLfWvhZmFEnyeru3VWMETnetz1BYLUC5MJGFXuhnHwWh7F6r74FDyhdswYop4eWPbyrXMXmUQEccTGd2NaT8g2VHADZ76gMC6BjWESvcnz2D4n8XwdmM7ZQ1jFwhuXrBfrb1dwRasyXxxHMGAC2onatNiExyeQ9G1W5LwqNLAh9hvcaNTGaYKYXoceVzLkgm6e5WMkLsCwuZXvB\" } }","title":"get_spend_proof"},{"location":"interacting/monero-wallet-rpc-reference/#get_transfer_by_txid","text":"Show information about a transfer to/from this address. Alias: None . Inputs: txid - string; Transaction ID used to find the transfer. account_index - unsigned int; (Optional) Index of the account to query for the transfer. Outputs: transfer - JSON object containing payment information: address - string; Address that transferred the funds. Base58 representation of the public keys. amount - unsigned int; Amount of this transfer. confirmations - unsigned int; Number of block mined since the block containing this transaction (or block height at which the transaction should be added to a block if not yet confirmed). destinations - array of JSON objects containing transfer destinations: amount - unsigned int; Amount transferred to this destination. address - string; Address for this destination. Base58 representation of the public keys. double_spend_seen - boolean; True if the key image(s) for the transfer have been seen before. fee - unsigned int; Transaction fee for this transfer. height - unsigned int; Height of the first block that confirmed this transfer. note - string; Note about this transfer. payment_id - string; Payment ID for this transfer. subaddr_index - JSON object containing the major & minor subaddress index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress under the account. suggested_confirmations_threshold - unsigned int; Estimation of the confirmations needed for the transaction to be included in a block. timestamp - unsigned int; POSIX timestamp for the block that confirmed this transfer (or timestamp submission if not mined yet). txid - string; Transaction ID of this transfer (same as input TXID). type - string; Type of transfer, one of the following: \"in\", \"out\", \"pending\", \"failed\", \"pool\" unlock_time - unsigned int; Number of blocks until transfer is safely spendable. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_transfer_by_txid\",\"params\":{\"txid\":\"c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"transfer\": { \"address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\", \"amount\": 300000000000, \"confirmations\": 1, \"destinations\": [{ \"address\": \"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\", \"amount\": 100000000000 },{ \"address\": \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\", \"amount\": 200000000000 }], \"double_spend_seen\": false, \"fee\": 21650200000, \"height\": 153624, \"note\": \"\", \"payment_id\": \"0000000000000000\", \"subaddr_index\": { \"major\": 0, \"minor\": 0 }, \"suggested_confirmations_threshold\": 1, \"timestamp\": 1535918400, \"txid\": \"c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a\", \"type\": \"out\", \"unlock_time\": 0 } } }","title":"get_transfer_by_txid"},{"location":"interacting/monero-wallet-rpc-reference/#get_transfers","text":"Returns a list of transfers. Alias: None . Inputs: in - boolean; (Optional) Include incoming transfers. out - boolean; (Optional) Include outgoing transfers. pending - boolean; (Optional) Include pending transfers. failed - boolean; (Optional) Include failed transfers. pool - boolean; (Optional) Include transfers from the daemon's transaction pool. filter_by_height - boolean; (Optional) Filter transfers by block height. min_height - unsigned int; (Optional) Minimum block height to scan for transfers, if filtering by height is enabled. max_height - unsigned int; (Opional) Maximum block height to scan for transfers, if filtering by height is enabled (defaults to max block height). account_index - unsigned int; (Optional) Index of the account to query for transfers. (defaults to 0) subaddr_indices - array of unsigned int; (Optional) List of subaddress indices to query for transfers. (defaults to 0) Outputs: in array of transfers: address - string; Public address of the transfer. amount - unsigned int; Amount transferred. confirmations - unsigned int; Number of block mined since the block containing this transaction (or block height at which the transaction should be added to a block if not yet confirmed). double_spend_seen - boolean; True if the key image(s) for the transfer have been seen before. fee - unsigned int; Transaction fee for this transfer. height - unsigned int; Height of the first block that confirmed this transfer (0 if not mined yet). note - string; Note about this transfer. payment_id - string; Payment ID for this transfer. subaddr_index - JSON object containing the major & minor subaddress index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress under the account. suggested_confirmations_threshold - unsigned int; Estimation of the confirmations needed for the transaction to be included in a block. timestamp - unsigned int; POSIX timestamp for when this transfer was first confirmed in a block (or timestamp submission if not mined yet). txid - string; Transaction ID for this transfer. type - string; Transfer type: \"in\" unlock_time - unsigned int; Number of blocks until transfer is safely spendable. out array of transfers (see above). pending array of transfers (see above). failed array of transfers (see above). pool array of transfers (see above). Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_transfers\",\"params\":{\"in\":true,\"account_index\":1}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"in\": [{ \"address\": \"77Vx9cs1VPicFndSVgYUvTdLCJEZw9h81hXLMYsjBCXSJfUehLa9TDW3Ffh45SQa7xb6dUs18mpNxfUhQGqfwXPSMrvKhVp\", \"amount\": 200000000000, \"confirmations\": 1, \"double_spend_seen\": false, \"fee\": 21650200000, \"height\": 153624, \"note\": \"\", \"payment_id\": \"0000000000000000\", \"subaddr_index\": { \"major\": 1, \"minor\": 0 }, \"suggested_confirmations_threshold\": 1, \"timestamp\": 1535918400, \"txid\": \"c36258a276018c3a4bc1f195a7fb530f50cd63a4fa765fb7c6f7f49fc051762a\", \"type\": \"in\", \"unlock_time\": 0 }] } }","title":"get_transfers"},{"location":"interacting/monero-wallet-rpc-reference/#get_tx_key","text":"Get transaction secret key from transaction id. Alias: None . Inputs: txid - string; transaction id. Outputs: tx_key - string; transaction secret key. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_tx_key\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_key\": \"feba662cf8fb6d0d0da18fc9b70ab28e01cc76311278fdd7fe7ab16360762b06\" } }","title":"get_tx_key"},{"location":"interacting/monero-wallet-rpc-reference/#get_tx_notes","text":"Get string notes for transactions. Alias: None . Inputs: txids - array of string; transaction ids Outputs: notes - array of string; notes for the transactions Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_tx_notes\",\"params\":{\"txids\":[\"3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f\"]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"notes\": [\"This is an example\"] } }","title":"get_tx_notes"},{"location":"interacting/monero-wallet-rpc-reference/#get_tx_proof","text":"Get transaction signature to prove it. Alias: None . Inputs: txid - string; transaction id. address - string; destination public address of the transaction. message - string; (Optional) add a message to the signature to further authenticate the prooving process. Outputs: signature - string; transaction signature. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_tx_proof\",\"params\":{\"txid\":\"19d5089f9469db3d90aca9024dfcb17ce94b948300101c8345a5e9f7257353be\",\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\",\"message\":\"this is my transaction\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signature\": \"InProofV13vqBCT6dpSAXkypZmSEMPGVnNRFDX2vscUYeVS4WnSVnV5BwLs31T9q6Etfj9Wts6tAxSAS4gkMeSYzzLS7Gt4vvCSQRh9niGJMUDJsB5hTzb2XJiCkUzWkkcjLFBBRVD5QZ\" } }","title":"get_tx_proof"},{"location":"interacting/monero-wallet-rpc-reference/#get_version","text":"Get RPC version Major & Minor integer-format, where Major is the first 16 bits and Minor the last 16 bits. Alias: None . Inputs: None . Outputs: version - unsigned int; RPC version, formatted with Major * 2^16 + Minor (Major encoded over the first 16 bits, and Minor over the last 16 bits). Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"version\": 65539 } }","title":"get_version"},{"location":"interacting/monero-wallet-rpc-reference/#import_key_images","text":"Import signed key images list and verify their spent status. Alias: None . Inputs: signed_key_images - array of signed key images: key_image - string; signature - string; Outputs: height - unsigned int; spent - unsigned int; Amount (in atomic units) spent from those key images. unspent - unsigned int; Amount (in atomic units) still available from those key images. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"import_key_images\", \"params\":{\"signed_key_images\":[{\"key_image\":\"cd35239b72a35e26a57ed17400c0b66944a55de9d5bda0f21190fed17f8ea876\",\"signature\":\"c9d736869355da2538ab4af188279f84138c958edbae3c5caf388a63cd8e780b8c5a1aed850bd79657df659422c463608ea4e0c730ba9b662c906ae933816d00\"},{\"key_image\":\"65158a8ee5a3b32009b85a307d85b375175870e560e08de313531c7dbbe6fc19\",\"signature\":\"c96e40d09dfc45cfc5ed0b76bfd7ca793469588bb0cf2b4d7b45ef23d40fd4036057b397828062e31700dc0c2da364f50cd142295a8405b9fe97418b4b745d0c\"}]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"height\": 76428, \"spent\": 62708953408711, \"unspent\": 0 } }","title":"import_key_images"},{"location":"interacting/monero-wallet-rpc-reference/#import_multisig_info","text":"Import multisig info from other participants. Alias: None . Inputs: info - array of string; List of multisig info in hex format from other participants. Outputs: n_outputs - unsigned int; Number of outputs signed with those multisig info. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"import_multisig_info\",\"params\":{\"info\":[\"...multisig_info...\"]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"n_outputs\": 35 } }","title":"import_multisig_info"},{"location":"interacting/monero-wallet-rpc-reference/#import_outputs","text":"Import outputs in hex format. Alias: None . Inputs: outputs_data_hex - string; wallet outputs in hex format. Outputs: num_imported - unsigned int; number of outputs imported. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"import_outputs\",\"params\":{\"outputs_data_hex\":\"...outputs...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"num_imported\": 6400 } }","title":"import_outputs"},{"location":"interacting/monero-wallet-rpc-reference/#incoming_transfers","text":"Return a list of incoming transfers to the wallet. Inputs: transfer_type - string; \"all\": all the transfers, \"available\": only transfers which are not yet spent, OR \"unavailable\": only transfers which are already spent. account_index - unsigned int; (Optional) Return transfers for this account. (defaults to 0) subaddr_indices - array of unsigned int; (Optional) Return transfers sent to these subaddresses. verbose - boolean; (Optional) Enable verbose output, return key image if true. Outputs: transfers - list of: amount - unsigned int; Amount of this transfer. global_index - unsigned int; Mostly internal use, can be ignored by most users. key_image - string; Key image for the incoming transfer's unspent output (empty unless verbose is true). spent - boolean; Indicates if this transfer has been spent. subaddr_index - unsigned int; Subaddress index for incoming transfer. tx_hash - string; Several incoming transfers may share the same hash if they were in the same transaction. tx_size - unsigned int; Size of transaction in bytes. Example, get all transfers: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"incoming_transfers\",\"params\":{\"transfer_type\":\"all\",\"account_index\":0,\"subaddr_indices\":[3],\"verbose\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"transfers\": [{ \"amount\": 60000000000000, \"global_index\": 122405, \"key_image\": \"768f5144777eb23477ab7acf83562581d690abaf98ca897c03a9d2b900eb479b\", \"spent\": true, \"subaddr_index\": 3, \"tx_hash\": \"f53401f21c6a43e44d5dd7a90eba5cf580012ad0e15d050059136f8a0da34f6b\", \"tx_size\": 159 },{ \"amount\": 27126892247503, \"global_index\": 594994, \"key_image\": \"7e561394806afd1be61980cc3431f6ef3569fa9151cd8d234f8ec13aa145695e\", \"spent\": false, \"subaddr_index\": 3, \"tx_hash\": \"106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b\", \"tx_size\": 157 },{ \"amount\": 27169374733655, \"global_index\": 594997, \"key_image\": \"e76c0a3bfeaae35e4173712f782eb34011198e26b990225b71aa787c8ba8a157\", \"spent\": false, \"subaddr_index\": 3, \"tx_hash\": \"0bd959b59117ee1254bd8e5aa8e77ec04ef744144a1ffb2d5c1eb9380a719621\", \"tx_size\": 158 }] } } Example, get available transfers: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"incoming_transfers\",\"params\":{\"transfer_type\":\"available\",\"account_index\":0,\"subaddr_indices\":[3],\"verbose\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"transfers\": [{ \"amount\": 27126892247503, \"global_index\": 594994, \"key_image\": \"7e561394806afd1be61980cc3431f6ef3569fa9151cd8d234f8ec13aa145695e\", \"spent\": false, \"subaddr_index\": 3, \"tx_hash\": \"106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b\", \"tx_size\": 157 },{ \"amount\": 27169374733655, \"global_index\": 594997, \"key_image\": \"e76c0a3bfeaae35e4173712f782eb34011198e26b990225b71aa787c8ba8a157\", \"spent\": false, \"subaddr_index\": 3, \"tx_hash\": \"0bd959b59117ee1254bd8e5aa8e77ec04ef744144a1ffb2d5c1eb9380a719621\", \"tx_size\": 158 }] } } Example, get unavailable transfers: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"incoming_transfers\",\"params\":{\"transfer_type\":\"unavailable\",\"account_index\":0,\"subaddr_indices\":[3],\"verbose\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"transfers\": [{ \"amount\": 60000000000000, \"global_index\": 122405, \"key_image\": \"768f5144777eb23477ab7acf83562581d690abaf98ca897c03a9d2b900eb479b\", \"spent\": true, \"subaddr_index\": 3, \"tx_hash\": \"f53401f21c6a43e44d5dd7a90eba5cf580012ad0e15d050059136f8a0da34f6b\", \"tx_size\": 159 }] } }","title":"incoming_transfers"},{"location":"interacting/monero-wallet-rpc-reference/#is_multisig","text":"Check if a wallet is a multisig one. Alias: None . Inputs: None . Outputs: multisig - boolean; States if the wallet is multisig ready - boolean; threshold - unsigned int; Amount of signature needed to sign a transfer. total - unsigned int; Total amount of signature in the multisig wallet. Example for a non-multisig wallet: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"is_multisig\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"multisig\": false, \"ready\": false, \"threshold\": 0, \"total\": 0 } } Example for a multisig wallet: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"is_multisig\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"multisig\": true, \"ready\": true, \"threshold\": 2, \"total\": 2 } }","title":"is_multisig"},{"location":"interacting/monero-wallet-rpc-reference/#label_account","text":"Label an account. Alias: None . Inputs: account_index - unsigned int; Apply label to account at this index. label - string; Label for the account. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"label_account\",\"params\":{\"account_index\":0,\"label\":\"Primary account\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"account_tags\": [{ \"accounts\": [0,1], \"label\": \"\", \"tag\": \"myTag\" }] } }","title":"label_account"},{"location":"interacting/monero-wallet-rpc-reference/#label_address","text":"Label an address. Alias: None . Inputs: index - subaddress index; JSON Object containing the major & minor address index: major - unsigned int; Account index for the subaddress. minor - unsigned int; Index of the subaddress in the account. label - string; Label for the address. Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"label_address\",\"params\":{\"index\":{\"major\":0,\"minor\":5},\"label\":\"myLabel\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"label_address"},{"location":"interacting/monero-wallet-rpc-reference/#make_integrated_address","text":"Make an integrated address from the wallet address and a payment id. Alias: None . Inputs: standard_address - string; (Optional, defaults to primary address) Destination public address. payment_id - string; (Optional, defaults to a random ID) 16 characters hex encoded. Outputs: integrated_address - string payment_id - string; hex encoded; Example (Payment ID is empty, use a random ID): $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"make_integrated_address\",\"params\":{\"standard_address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"integrated_address\": \"5F38Rw9HKeaLQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZXCkbHUXdPHyiUeRyokn\", \"payment_id\": \"420fa29b2d9a49f5\" } }","title":"make_integrated_address"},{"location":"interacting/monero-wallet-rpc-reference/#make_multisig","text":"Make a wallet multisig by importing peers multisig string. Alias: None . Inputs: multisig_info - array of string; List of multisig string from peers. threshold - unsigned int; Amount of signatures needed to sign a transfer. Must be less or equal than the amount of signature in multisig_info . password - string; Wallet password Outputs: address - string; multisig wallet address. multisig_info - string; Multisig string to share with peers to create the multisig wallet (extra step for N-1/N wallets). Example for 2/2 Multisig Wallet: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"make_multisig\",\"params\":{\"multisig_info\":[\"MultisigV1K4tGGe8QirZdHgTYoBZMumSug97fdDyM3Z63M3ZY5VXvAdoZvx16HJzPCP4Rp2ABMKUqLD2a74ugMdBfrVpKt4BwD8qCL5aZLrsYWoHiA7JJwDESuhsC3eF8QC9UMvxLXEMsMVh16o98GnKRYz1HCKXrAEWfcrCHyz3bLW1Pdggyowop\"],\"threshold\":2}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"address\": \"55SoZTKH7D39drxfgT62k8T4adVFjmDLUXnbzEKYf1MoYwnmTNKKaqGfxm4sqeKCHXQ5up7PVxrkoeRzXu83d8xYURouMod\", \"multisig_info\": \"\" } } Example for 2/3 Multisig Wallet: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"make_multisig\",\"params\":{\"multisig_info\":[\"MultisigV1MTVm4DZAdJw1PyVutpSy8Q4WisZBCFRAaZY7hhQnMwr5AZ4swzThyaSiVVQM5FHj1JQi3zPKhQ4k81BZkPSEaFjwRJtbfqfJcVvCqRnmBVcWVxhnihX5s8fZWBCjKrzT3CS95spG4dzNzJSUcjheAkLzCpVmSzGtgwMhAS3Vuz9Pas24\",\"MultisigV1TEx58ycKCd6ADCfxF8hALpcdSRAkhZTi1bu4Rs6FdRC98EdB1LY7TAkMxasM55khFgcxrSXivaSr5FCMyJGHmojm1eE4HpGWPeZKv6cgCTThRzC4u6bkkSoFQdbzWN92yn1XEjuP2XQrGHk81mG2LMeyB51MWKJAVF99Pg9mX2BpmYFj\"],\"threshold\":2}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"address\": \"51sLpF8fWaK1111111111111111111111111111111111ABVbHNf1JFWJyFp5YZgZRQ44RiviJi1sPHgLVMbckRsDkTRgKS\", \"multisig_info\": \"MultisigxV18jCaYAQQvzCMUJaAWMCaAbAoHpAD6WPmYDmLtBtazD654E8RWkLaGRf29fJ3stU471MELKxwufNYeigP7LoE4tn2Sscwn5g7PyCfcBc1V4ffRHY3Kxqq6VocSCUTncpVeUskaDKuTAWtdB9VTBGW7iG1cd7Zm1dYgur3CiemkGjRUAj9bL3xTEuyaKGYSDhtpFZFp99HQX57EawhiRHk3qq4hjWX\" } }","title":"make_multisig"},{"location":"interacting/monero-wallet-rpc-reference/#make_uri","text":"Create a payment URI using the official URI spec. Alias: None . Inputs: address - string; Wallet address amount - unsigned int; (optional) the integer amount to receive, in atomic units payment_id - string; (optional) 16 or 64 character hexadecimal payment id recipient_name - string; (optional) name of the payment recipient tx_description - string; (optional) Description of the reason for the tx Outputs: uri - string; This contains all the payment input information as a properly formatted payment URI Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"make_uri\",\"params\":{\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"amount\":10,\"payment_id\":\"420fa29b2d9a49f5\",\"tx_description\":\"Testing out the make_uri function.\",\"recipient_name\":\"el00ruobuob Stagenet wallet\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"uri\": \"monero:55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt?tx_payment_id=420fa29b2d9a49f5&tx_amount=0.000000000010&recipient_name=el00ruobuob%20Stagenet%20wallet&tx_description=Testing%20out%20the%20make_uri%20function.\" } }","title":"make_uri"},{"location":"interacting/monero-wallet-rpc-reference/#open_wallet","text":"Open a wallet. You need to have set the argument \"\u2013wallet-dir\" when launching monero-wallet-rpc to make this work. Alias: None . Inputs: filename - string; wallet name stored in \u2013wallet-dir. password - string; (Optional) only needed if the wallet has a password defined. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"open_wallet\",\"params\":{\"filename\":\"mytestwallet\",\"password\":\"mytestpassword\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"open_wallet"},{"location":"interacting/monero-wallet-rpc-reference/#parse_uri","text":"Parse a payment URI to get payment information. Alias: None . Inputs: uri - string; This contains all the payment input information as a properly formatted payment URI Outputs: uri - JSON object containing payment information: address - string; Wallet address amount - unsigned int; Decimal amount to receive, in coin units (0 if not provided) payment_id - string; 16 or 64 character hexadecimal payment id (empty if not provided) recipient_name - string; Name of the payment recipient (empty if not provided) tx_description - string; Description of the reason for the tx (empty if not provided) Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"parse_uri\",\"params\":{\"uri\":\"monero:55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt?tx_payment_id=420fa29b2d9a49f5&tx_amount=0.000000000010&recipient_name=el00ruobuob%20Stagenet%20wallet&tx_description=Testing%20out%20the%20make_uri%20function.\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"uri\": { \"address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\", \"amount\": 10, \"payment_id\": \"420fa29b2d9a49f5\", \"recipient_name\": \"el00ruobuob Stagenet wallet\", \"tx_description\": \"Testing out the make_uri function.\" } } }","title":"parse_uri"},{"location":"interacting/monero-wallet-rpc-reference/#prepare_multisig","text":"Prepare a wallet for multisig by generating a multisig string to share with peers. Alias: None . Inputs: None . Outputs: multisig_info - string; Multisig string to share with peers to create the multisig wallet. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"prepare_multisig\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"multisig_info\": \"MultisigV1BFdxQ653cQHB8wsj9WJQd2VdnjxK89g5M94dKPBNw22reJnyJYKrz6rJeXdjFwJ3Mz6n4qNQLd6eqUZKLiNzJFi3UPNVcTjtkG2aeSys9sYkvYYKMZ7chCxvoEXVgm74KKUcUu4V8xveCBFadFuZs8shnxBWHbcwFr5AziLr2mE7KHJT\" } }","title":"prepare_multisig"},{"location":"interacting/monero-wallet-rpc-reference/#query_key","text":"Return the spend or view private key. Alias: None . Inputs: key_type - string; Which key to retrieve: \"mnemonic\" - the mnemonic seed (older wallets do not have one) OR \"view_key\" - the view key Outputs: key - string; The view key will be hex encoded, while the mnemonic will be a string of words. Example (Query view key): $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"query_key\",\"params\":{\"key_type\":\"view_key\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"key\": \"0a1a38f6d246e894600a3e27238a064bf5e8d91801df47a17107596b1378e501\" } } Example (Query mnemonic key): $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"query_key\",\"params\":{\"key_type\":\"mnemonic\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"key\": \"vocal either anvil films dolphin zeal bacon cuisine quote syndrome rejoices envy okay pancakes tulips lair greater petals organs enmity dedicated oust thwart tomorrow tomorrow\" } }","title":"query_key"},{"location":"interacting/monero-wallet-rpc-reference/#refresh","text":"Refresh a wallet after openning. Alias: None . Inputs: start_height - unsigned int; (Optional) The block height from which to start refreshing. Outputs: blocks_fetched - unsigned int; Number of new blocks scanned. received_money - boolean; States if transactions to the wallet have been found in the blocks. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"refresh\",\"params\":{\"start_height\":100000}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"blocks_fetched\": 24, \"received_money\": true } }","title":"refresh"},{"location":"interacting/monero-wallet-rpc-reference/#relay_tx","text":"Relay a transaction previously created with \"do_not_relay\":true . Alias: None . Inputs: hex - string; transaction metadata returned from a transfer method with get_tx_metadata set to true . Outputs: tx_hash - String for the publically searchable transaction hash. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"relay_tx\",\"params\":{\"hex\":\"...tx_metadata...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_hash\": \"1c42dcc5672bb09bccf33fb1e9ab4a498af59a6dbd33b3d0cfb289b9e0e25fa5\" } }","title":"relay_tx"},{"location":"interacting/monero-wallet-rpc-reference/#rescan_blockchain","text":"Rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself. This includes destination addresses, tx secret keys, tx notes, etc. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"rescan_blockchain\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"rescan_blockchain"},{"location":"interacting/monero-wallet-rpc-reference/#rescan_spent","text":"Rescan the blockchain for spent outputs. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"rescan_spent\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"rescan_spent"},{"location":"interacting/monero-wallet-rpc-reference/#set_account_tag_description","text":"Set description for an account tag. Alias: None . Inputs: tag - string; Set a description for this tag. description - string; Description for the tag. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"set_account_tag_description\",\"params\":{\"tag\":\"myTag\",\"description\":\"Test tag\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"set_account_tag_description"},{"location":"interacting/monero-wallet-rpc-reference/#set_attribute","text":"Set arbitrary attribute. Alias: None . Inputs: key - string; attribute name value - string; attribute value Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"set_attribute\",\"params\":{\"key\":\"my_attribute\",\"value\":\"my_value\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"set_attribute"},{"location":"interacting/monero-wallet-rpc-reference/#set_tx_notes","text":"Set arbitrary string notes for transactions. Alias: None . Inputs: txids - array of string; transaction ids notes - array of string; notes for the transactions Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"set_tx_notes\",\"params\":{\"txids\":[\"3292e83ad28fc1cc7bc26dbd38862308f4588680fbf93eae3e803cddd1bd614f\"],\"notes\":[\"This is an example\"]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"set_tx_notes"},{"location":"interacting/monero-wallet-rpc-reference/#sign","text":"Sign a string. Alias: None . Inputs: data - string; Anything you need to sign. Outputs: signature - string; Signature generated against the \"data\" and the account public address. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sign\",\"params\":{\"data\":\"This is sample data to be signed\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signature\": \"SigV14K6G151gycjiGxjQ74tKX6A2LwwghvuHjcDeuRFQio5LS6Gb27BNxjYQY1dPuUvXkEbGQUkiHSVLPj4nJAHRrrw3\" } }","title":"sign"},{"location":"interacting/monero-wallet-rpc-reference/#sign_multisig","text":"Sign a transaction in multisig. Alias: None . Inputs: tx_data_hex - string; Multisig transaction in hex format, as returned by transfer under multisig_txset . Outputs: tx_data_hex - string; Multisig transaction in hex format. tx_hash_list - array of string; List of transaction Hash. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sign_multisig\",\"params\":{\"tx_data_hex\":\"...multisig_txset...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_data_hex\": \"...multisig_txset...\", \"tx_hash_list\": [\"4996091b61c1be112c1097fd5e97d8ff8b28f0e5e62e1137a8c831bacf034f2d\"] } }","title":"sign_multisig"},{"location":"interacting/monero-wallet-rpc-reference/#sign_transfer","text":"Sign a transaction created on a read-only wallet (in cold-signing process) Alias: None . Inputs: unsigned_txset - string. Set of unsigned tx returned by \"transfer\" or \"transfer_split\" methods. export_raw - boolean; (Optional) If true, return the raw transaction data. (Defaults to false) Outputs: signed_txset - string. Set of signed tx to be used for submitting transfer. tx_hash_list - array of: string. The tx hashes of every transaction. tx_raw_list - array of: string. The tx raw data of every transaction. In the example below, we first generate an unsigned_txset on a read only wallet before signing it: Generate unsigned_txset using the above \"transfer\" method on read-only wallet: curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"transfer\",\"params\":{\"destinations\":[{\"amount\":1000000000000,\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"}],\"account_index\":0,\"subaddr_indices\":[0],\"priority\":0,\"ring_size\":7,\"do_not_relay\":true,\"get_tx_hex\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount\": 1000000000000, \"fee\": 15202740000, \"multisig_txset\": \"\", \"tx_blob\": \"...long_hex...\", \"tx_hash\": \"c648ba0a049e5ce4ec21361dbf6e4b21eac0f828eea9090215de86c76b31d0a4\", \"tx_key\": \"\", \"tx_metadata\": \"\", \"unsigned_txset\": \"...long_hex...\" } } Sign tx using the previously generated unsigned_txset $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sign_transfer\",\"params\":{\"unsigned_txset\":...long_hex...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"signed_txset\": \"...long_hex...\", \"tx_hash_list\": [\"ff2e2d49fbfb1c9a55754f786576e171c8bf21b463a74438df604b7fa6cebc6d\"] } }","title":"sign_transfer"},{"location":"interacting/monero-wallet-rpc-reference/#split_integrated_address","text":"Retrieve the standard address and payment id corresponding to an integrated address. Alias: None . Inputs: integrated_address - string Outputs: is_subaddress - boolean; States if the address is a subaddress payment - string; hex encoded standard_address - string Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"split_integrated_address\",\"params\":{\"integrated_address\": \"5F38Rw9HKeaLQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZXCkbHUXdPHyiUeRyokn\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"is_subaddress\": false, \"payment_id\": \"420fa29b2d9a49f5\", \"standard_address\": \"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\" } }","title":"split_integrated_address"},{"location":"interacting/monero-wallet-rpc-reference/#start_mining","text":"Start mining in the Monero daemon. Alias: None . Inputs: threads_count - unsigned int; Number of threads created for mining. do_background_mining - boolean; Allow to start the miner in smart mining mode. ignore_battery - boolean; Ignore battery status (for smart mining only) Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"start_mining\",\"params\":{\"threads_count\":1,\"do_background_mining\":true,\"ignore_battery\":false}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"start_mining"},{"location":"interacting/monero-wallet-rpc-reference/#stop_mining","text":"Stop mining in the Monero daemon. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"stop_mining\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"stop_mining"},{"location":"interacting/monero-wallet-rpc-reference/#stop_wallet","text":"Stops the wallet, storing the current state. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"stop_wallet\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"stop_wallet"},{"location":"interacting/monero-wallet-rpc-reference/#store","text":"Save the wallet file. Alias: None . Inputs: None . Outputs: None . Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"store\"}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"store"},{"location":"interacting/monero-wallet-rpc-reference/#submit_multisig","text":"Submit a signed multisig transaction. Alias: None . Inputs: tx_data_hex - string; Multisig transaction in hex format, as returned by sign_multisig under tx_data_hex . Outputs: tx_hash_list - array of string; List of transaction Hash. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"submit_multisig\",\"params\":{\"tx_data_hex\":\"...tx_data_hex...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_hash_list\": [\"4996091b61c1be112c1097fd5e97d8ff8b28f0e5e62e1137a8c831bacf034f2d\"] } }","title":"submit_multisig"},{"location":"interacting/monero-wallet-rpc-reference/#submit_transfer","text":"Submit a previously signed transaction on a read-only wallet (in cold-signing process). Alias: None . Inputs: tx_data_hex - string; Set of signed tx returned by \"sign_transfer\" Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. In the example below, we submit the transfer using the signed_txset generated above: curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"submit_transfer\",\"params\":{\"tx_data_hex\":...long_hex...\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"tx_hash_list\": [\"40fad7c828bb383ac02648732f7afce9adc520ba5629e1f5d9c03f584ac53d74\"] } }","title":"submit_transfer"},{"location":"interacting/monero-wallet-rpc-reference/#sweep_all","text":"Send all unlocked balance to an address. Alias: None . Inputs: address - string; Destination public address. account_index - unsigned int; Sweep transactions from this account. subaddr_indices - array of unsigned int; (Optional) Sweep from this set of subaddresses in the account. priority - unsigned int; (Optional) Priority for sending the sweep transfer, partially determines fee. mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing). ring_size - unsigned int; Sets ringsize to n (mixin + 1). unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock). payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction. get_tx_keys - boolean; (Optional) Return the transaction keys after sending. below_amount - unsigned int; (Optional) Include outputs below this amount. do_not_relay - boolean; (Optional) If true, do not relay this sweep transfer. (Defaults to false) get_tx_hex - boolean; (Optional) return the transactions as hex encoded string. (Defaults to false) get_tx_metadata - boolean; (Optional) return the transaction metadata as a string. (Defaults to false) Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. tx_key_list - array of: string. The transaction keys for every transaction. amount_list - array of: integer. The amount transferred for every transaction. fee_list - array of: integer. The amount of fees paid for every transaction. tx_blob_list - array of: string. The tx as hex string for every transaction. tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later. multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig). unsigned_txset - string. Set of unsigned tx for cold-signing purposes. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sweep_all\",\"params\":{\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"subaddr_indices\":[4],\"ring_size\":7,\"unlock_time\":0,\"get_tx_keys\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount_list\": [9985885770000], \"fee_list\": [14114230000], \"multisig_txset\": \"\", \"tx_hash_list\": [\"ab4b6b65cc8cd8c9dd317d0b90d97582d68d0aa1637b0065b05b61f9a66ea5c5\"], \"tx_key_list\": [\"b9b4b39d3bb3062ddb85ec0266d4df39058f4c86077d99309f218ce4d76af607\"], \"unsigned_txset\": \"\" } }","title":"sweep_all"},{"location":"interacting/monero-wallet-rpc-reference/#sweep_dust","text":"Send all dust outputs back to the wallet's, to make them easier to spend (and mix). Alias: sweep_unmixable . Inputs: get_tx_keys - boolean; (Optional) Return the transaction keys after sending. do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the monero network. (Defaults to false) get_tx_hex - boolean; (Optional) Return the transactions as hex string after sending. (Defaults to false) get_tx_metadata - boolean; (Optional) Return list of transaction metadata needed to relay the transfer later. (Defaults to false) Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. tx_key_list - array of: string. The transaction keys for every transaction. amount_list - array of: integer. The amount transferred for every transaction. fee_list - array of: integer. The amount of fees paid for every transaction. tx_blob_list - array of: string. The tx as hex string for every transaction. tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later. multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig). unsigned_txset - string. Set of unsigned tx for cold-signing purposes. Example (In this example, sweep_dust returns nothing because there are no funds to sweep): $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sweep_dust\",\"params\":{\"get_tx_keys\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"multisig_txset\": \"\", \"unsigned_txset\": \"\" } }","title":"sweep_dust"},{"location":"interacting/monero-wallet-rpc-reference/#sweep_single","text":"Send all of a specific unlocked output to an address. Alias: None . Inputs: address - string; Destination public address. account_index - unsigned int; Sweep transactions from this account. subaddr_indices - array of unsigned int; (Optional) Sweep from this set of subaddresses in the account. priority - unsigned int; (Optional) Priority for sending the sweep transfer, partially determines fee. mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing). ring_size - unsigned int; Sets ringsize to n (mixin + 1). unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock). payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction. get_tx_keys - boolean; (Optional) Return the transaction keys after sending. key_image - string; Key image of specific output to sweep. below_amount - unsigned int; (Optional) Include outputs below this amount. do_not_relay - boolean; (Optional) If true, do not relay this sweep transfer. (Defaults to false) get_tx_hex - boolean; (Optional) return the transactions as hex encoded string. (Defaults to false) get_tx_metadata - boolean; (Optional) return the transaction metadata as a string. (Defaults to false) Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. tx_key_list - array of: string. The transaction keys for every transaction. amount_list - array of: integer. The amount transferred for every transaction. fee_list - array of: integer. The amount of fees paid for every transaction. tx_blob_list - array of: string. The tx as hex string for every transaction. tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later. multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig). unsigned_txset - string. Set of unsigned tx for cold-signing purposes. Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"sweep_single\",\"params\":{\"address\":\"74Jsocx8xbpTBEjm3ncKE5LBQbiJouyCDaGhgSiebpvNDXZnTAbW2CmUR5SsBeae2pNk9WMVuz6jegkC4krUyqRjA6VjoLD\",\"ring_size\":7,\"unlock_time\":0,\"key_image\":\"a7834459ef795d2efb6f665d2fd758c8d9288989d8d4c712a68f8023f7804a5e\",\"get_tx_keys\":true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount\": 27126892247503, \"fee\": 14111630000, \"multisig_txset\": \"\", \"tx_blob\": \"\", \"tx_hash\": \"106d4391a031e5b735ded555862fec63233e34e5fa4fc7edcfdbe461c275ae5b\", \"tx_key\": \"\", \"tx_metadata\": \"\", \"unsigned_txset\": \"\" } }","title":"sweep_single"},{"location":"interacting/monero-wallet-rpc-reference/#tag_accounts","text":"Apply a filtering tag to a list of accounts. Alias: None . Inputs: tag - string; Tag for the accounts. accounts - array of unsigned int; Tag this list of accounts. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"tag_accounts\",\"params\":{\"tag\":\"myTag\",\"accounts\":[0,1]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"tag_accounts"},{"location":"interacting/monero-wallet-rpc-reference/#transfer","text":"Send monero to a number of recipients. Alias: None . Inputs: destinations - array of destinations to receive XMR: amount - unsigned int; Amount to send to each destination, in atomic units. address - string; Destination public address. account_index - unsigned int; (Optional) Transfer from this account index. (Defaults to 0) subaddr_indices - array of unsigned int; (Optional) Transfer from this set of subaddresses. (Defaults to 0) priority - unsigned int; Set a priority for the transaction. Accepted Values are: 0-3 for: default, unimportant, normal, elevated, priority. mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing). ring_size - unsigned int; Number of outputs to mix in the transaction (this output + N decoys from the blockchain). unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock). payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction. get_tx_key - boolean; (Optional) Return the transaction key after sending. do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the monero network. (Defaults to false) get_tx_hex - boolean; Return the transaction as hex string after sending (Defaults to false) get_tx_metadata - boolean; Return the metadata needed to relay the transaction. (Defaults to false) Outputs: amount - Amount transferred for the transaction. fee - Integer value of the fee charged for the txn. multisig_txset - Set of multisig transactions in the process of being signed (empty for non-multisig). tx_blob - Raw transaction represented as hex string, if get_tx_hex is true. tx_hash - String for the publically searchable transaction hash. tx_key - String for the transaction key if get_tx_key is true, otherwise, blank string. tx_metadata - Set of transaction metadata needed to relay this transfer later, if get_tx_metadata is true. unsigned_txset - String. Set of unsigned tx for cold-signing purposes. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"transfer\",\"params\":{\"destinations\":[{\"amount\":100000000000,\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"},{\"amount\":200000000000,\"address\":\"75sNpRwUtekcJGejMuLSGA71QFuK1qcCVLZnYRTfQLgFU5nJ7xiAHtR5ihioS53KMe8pBhH61moraZHyLoG4G7fMER8xkNv\"}],\"account_index\":0,\"subaddr_indices\":[0],\"priority\":0,\"ring_size\":7,\"get_tx_key\": true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount\": 300000000000, \"fee\": 86897600000, \"multisig_txset\": \"\", \"tx_blob\": \"\", \"tx_hash\": \"7663438de4f72b25a0e395b770ea9ecf7108cd2f0c4b75be0b14a103d3362be9\", \"tx_key\": \"25c9d8ec20045c80c93d665c9d3684aab7335f8b2cd02e1ba2638485afd1c70e236c4bdd7a2f1cb511dbf466f13421bdf8df988b7b969c448ca6239d7251490e4bf1bbf9f6ffacffdcdc93b9d1648ec499eada4d6b4e02ce92d4a1c0452e5d009fbbbf15b549df8856205a4c7bda6338d82c823f911acd00cb75850b198c5803\", \"tx_metadata\": \"\", \"unsigned_txset\": \"\" } }","title":"transfer"},{"location":"interacting/monero-wallet-rpc-reference/#transfer_split","text":"Same as transfer, but can split into more than one tx if necessary. Alias: None . Inputs: destinations - array of destinations to receive XMR: amount - unsigned int; Amount to send to each destination, in atomic units. address - string; Destination public address. account_index - unsigned int; (Optional) Transfer from this account index. (Defaults to 0) subaddr_indices - array of unsigned int; (Optional) Transfer from this set of subaddresses. (Defaults to 0) mixin - unsigned int; Number of outputs from the blockchain to mix with (0 means no mixing). ring_size - unsigned int; Sets ringsize to n (mixin + 1). unlock_time - unsigned int; Number of blocks before the monero can be spent (0 to not add a lock). payment_id - string; (Optional) Random 32-byte/64-character hex string to identify a transaction. get_tx_keys - boolean; (Optional) Return the transaction keys after sending. priority - unsigned int; Set a priority for the transactions. Accepted Values are: 0-3 for: default, unimportant, normal, elevated, priority. do_not_relay - boolean; (Optional) If true, the newly created transaction will not be relayed to the monero network. (Defaults to false) get_tx_hex - boolean; Return the transactions as hex string after sending new_algorithm - boolean; True to use the new transaction construction algorithm, defaults to false. get_tx_metadata - boolean; Return list of transaction metadata needed to relay the transfer later. Outputs: tx_hash_list - array of: string. The tx hashes of every transaction. tx_key_list - array of: string. The transaction keys for every transaction. amount_list - array of: integer. The amount transferred for every transaction. fee_list - array of: integer. The amount of fees paid for every transaction. tx_blob_list - array of: string. The tx as hex string for every transaction. tx_metadata_list - array of: string. List of transaction metadata needed to relay the transactions later. multisig_txset - string. The set of signing keys used in a multisig transaction (empty for non-multisig). unsigned_txset - string. Set of unsigned tx for cold-signing purposes. Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"transfer_split\",\"params\":{\"destinations\":[{\"amount\":1000000000000,\"address\":\"7BnERTpvL5MbCLtj5n9No7J5oE5hHiB3tVCK5cjSvCsYWD2WRJLFuWeKTLiXo5QJqt2ZwUaLy2Vh1Ad51K7FNgqcHgjW85o\"},{\"amount\":2000000000000,\"address\":\"75sNpRwUtekcJGejMuLSGA71QFuK1qcCVLZnYRTfQLgFU5nJ7xiAHtR5ihioS53KMe8pBhH61moraZHyLoG4G7fMER8xkNv\"}],\"account_index\":0,\"subaddr_indices\":[0],\"priority\":0,\"ring_size\":7,\"get_tx_key\": true}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"amount_list\": [3000000000000], \"fee_list\": [85106400000], \"multisig_txset\": \"\", \"tx_hash_list\": [\"c8d815f48f27d53fdaf198a74b292a91bfaf87529a9a9a9ee66079a890b3b58b\"], \"unsigned_txset\": \"\" } }","title":"transfer_split"},{"location":"interacting/monero-wallet-rpc-reference/#untag_accounts","text":"Remove filtering tag from a list of accounts. Alias: None . Inputs: accounts - array of unsigned int; Remove tag from this list of accounts. Outputs: None . Example: $ curl -X POST http://localhost:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"untag_accounts\",\"params\":{\"accounts\":[1]}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { } }","title":"untag_accounts"},{"location":"interacting/monero-wallet-rpc-reference/#verify","text":"Verify a signature on a string. Alias: None . Inputs: data - string; What should have been signed. address - string; Public address of the wallet used to sign the data. signature - string; signature generated by sign method. Outputs: good - boolean; Example: $ curl -X POST http://127.0.0.1:18082/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"verify\",\"params\":{\"data\":\"This is sample data to be signed\",\"address\":\"55LTR8KniP4LQGJSPtbYDacR7dz8RBFnsfAKMaMuwUNYX6aQbBcovzDPyrQF9KXF9tVU6Xk3K8no1BywnJX6GvZX8yJsXvt\",\"signature\":\"SigV14K6G151gycjiGxjQ74tKX6A2LwwghvuHjcDeuRFQio5LS6Gb27BNxjYQY1dPuUvXkEbGQUkiHSVLPj4nJAHRrrw3\"}}' -H 'Content-Type: application/json' { \"id\": \"0\", \"jsonrpc\": \"2.0\", \"result\": { \"good\": true } }","title":"verify"},{"location":"interacting/monero-wallet-rpc-reference/#sources","text":"Reworked from GetMonero.org","title":"Sources:"},{"location":"interacting/monerod-reference/","text":"monerod - Reference \u00b6 Overview \u00b6 Connects you to Monero network \u00b6 The Monero daemon monerod keeps your computer synced up with the Monero network. It downloads and validates the blockchain from the p2p network. Not aware of your private keys \u00b6 monerod is entirely decoupled from your wallet. monerod does not access your private keys - it is not aware of your transactions and balance. This allows you to run monerod on a separate computer or in the cloud. In fact, you can connect to a remote monerod instance provided by a semi-trusted 3rd party. Such 3rd party will not be able to steal your funds. This is very handy for learning and experimentation. However, there are privacy and reliability implications to using a remote, untrusted node. For any real business you should be running your own full node . Syntax \u00b6 ./monerod [options] [command] Options define how the daemon should be working. Their names follow the --option-name pattern. Commands give access to specific services provided by the daemon. Commands are executed against the running daemon. Their names follow the command_name pattern. Running \u00b6 Go to directory where you unpacked Monero. The stagenet is what your should be using for learning and experimentation. ./monerod --stagenet --detach # run as a daemon in background tail -f ~/.bitmonero/stagenet/bitmonero.log # watch the logs ./monerod --stagenet exit # ask daemon to exit gracefully The mainnnet is when you want to deal with the real XMR. ./monerod --detach # run as a daemon in background tail -f ~/.bitmonero/bitmonero.log # watch the logs ./monerod exit # ask daemon to exit gracefully Options \u00b6 Options define how the daemon should be working. Their names follow the --option-name pattern. The following groups are only to make reference easier to follow. The daemon itself does not group options in any way. Help and version \u00b6 Option Description --help Enlist available options. --version Show monerod version to stdout. Example output: Monero 'Oxygen Orion' (v0.17.1.8-release) --os-version Show build timestamp and target operating system. Example output: OS: Linux #65-Ubuntu SMP Thu Dec 10 12:01:51 UTC 2020 5.4.0-59-generic . --check-updates One of: disabled | notify | download (= notify by default). Check for new versions of Monero and optionally download it. You should probably prefer your OS package manager to do the update, if possible. There is also unimplemented update option shown by the help system. Pick network \u00b6 Option Description (missing) By default monerod assumes mainnet . --stagenet Run on stagenet . Remember to run your wallet with --stagenet as well. --testnet Run on testnet . Remember to run your wallet with --testnet as well. Logging \u00b6 Option Description --log-file Full path to the log file. Example (mind file permissions): ./monerod --log-file=/var/log/monero/mainnet/monerod.log --log-level 0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0 . These are general presets and do not directly map to severity levels. For example, even with minimal 0 , you may see some most important INFO entries. Temporarily changing to 1 allows for much better understanding of how the full node operates. Example: ./monerod --log-level=1 --max-log-file-size Soft limit in bytes for the log file (=104850000 by default, which is just under 100MB). Once log file grows past that limit, monerod creates the next log file with a UTC timestamp postfix -YYYY-MM-DD-HH-MM-SS . In production deployments, you would probably prefer to use established solutions like logrotate instead. In that case, set --max-log-file-size=0 to prevent monerod from managing the log files. --max-log-files Limit on the number of log files (=50 by default). The oldest log files are removed. In production deployments, you would probably prefer to use established solutions like logrotate instead. Server \u00b6 monerod defaults are adjusted for running it occasionally on the same computer as your Monero wallet. The following options will be helpful if you intend to have an always running node \u2014 most likely on a remote server or your own separate PC. Option Description --config-file Full path to the configuration file . By default monerod looks for bitmonero.conf in Monero data directory . --data-dir Full path to data directory. This is where the blockchain, log files, and p2p network memory are stored. For defaults and details see data directory . --pidfile Full path to the PID file. Works only with --detach . Example: ./monerod --detach --pidfile=/run/monero/monerod.pid --detach Go to background (decouple from the terminal). This is useful for long-running / server scenarios. Typically, you will also want to manage monerod daemon with systemd or similar. By default monerod runs in a foreground. --non-interactive Do not require tty in a foreground mode. Helpful when running in a container. By default monerod runs in a foreground and opens stdin for reading. This breaks containerization because no tty gets assigned and monerod process crashes. You can make it run in a background with --detach but this is inconvenient in a containerized environment because the canonical usage is that the container waits on the main process to exist (forking makes things more complicated). --no-zmq Disable ZMQ RPC server. You should use this option to limit attack surface and number of unnecessarily open ports (the ZMQ server is unfinished thing and you are unlikely to ever use it). --no-igd Disable UPnP port mapping on the router (\"Internet Gateway Device\"). Add this option to improve security if you are not behind a NAT (you can bind directly to public IP or you run through Tor). --max-txpool-weight Set maximum transactions pool size in bytes. By default 648000000 (~618MB). These are transactions pending for confirmations (not included in any block). --enforce-dns-checkpointing The emergency checkpoints set by MoneroPulse operators will be enforced. It is probably a good idea to set enforcing for unattended nodes. If encountered block hash does not match corresponding checkpoint, the local blockchain will be rolled back a few blocks, effectively blocking following what MoneroPulse operators consider invalid fork. The log entry will be produced: ERROR Local blockchain failed to pass a checkpoint, rolling back! Eventually, the alternative (\"fixed\") fork will get heavier and the node will follow it, leaving the \"invalid\" fork behind. By default checkpointing only notifies about discrepancy by producing the following log entry: ERROR WARNING: local blockchain failed to pass a MoneroPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option . Reference: source code . --disable-dns-checkpoints The MoneroPulse checkpoints set by core developers will be discarded. The checkpoints are apparently still fetched though. P2P network \u00b6 The following options define how your node participates in Monero peer-to-peer network. This is for node-to-node communication. The following options do not affect wallet-to-node interface. The node and peer words are used interchangeably. Option Description --p2p-bind-ip IPv4 network interface to bind to for p2p network protocol. Default value 0.0.0.0 binds to all network interfaces. This is typically what you want. You must change this if you want to constrain binding, for example to force working through Tor via torsocks: DNS_PUBLIC=tcp://1.1.1.1 TORSOCKS_ALLOW_INBOUND=1 torsocks ./monerod --p2p-bind-ip 127.0.0.1\u200a --no-igd\u200a --hide-my-port --p2p-bind-port TCP port to listen for p2p network connections. Defaults to 18080 for mainnet, 28080 for testnet, and 38080 for stagenet. You normally wouldn't change that. This is helpful to run several nodes on your machine to simulate private Monero p2p network (likely using private Testnet). Example: ./monerod --p2p-bind-port=48080 --p2p-external-port TCP port to listen for p2p network connections on your router. Relevant if you are behind a NAT and still want to accept incoming connections. You must then set this to relevant port on your router. This is to let monerod know what to advertise on the network. Default is 0 . --p2p-use-ipv6 Enable IPv6 for p2p (disabled by default). --p2p-bind-ipv6-address IPv6 network interface to bind to for p2p network protocol. Default value :: binds to all network interfaces. --p2p-ignore-ipv4 Ignore unsuccessful IPv4 bind for p2p. Useful if you only want to use IPv6. --igd Set UPnP port mapping on the router (\"Internet Gateway Device\"). One of: disabled | enabled | delayed (= delayed by default). Relevant if you are behind NAT and want to accept incoming P2P network connections. The delayed value means it will wait for incoming connections in hope UPnP may not be necessary. After a while w/o incoming connections found it will attempt to map ports with UPnP. If you know you need UPnP change it to enabled to fast track the process. --hide-my-port monerod will still open and listen on the p2p port. However, it will not announce itself as a peer list candidate. Technically, it will return port 0 in a response to p2p handshake ( node_data.my_port = 0 in get_local_node_data function). In effect nodes you connect to won't spread your IP to other nodes. To sum up, it is not really hiding, it is more like \"do not advertise\". --seed-node Connect to a node to retrieve other nodes' addresses, and disconnect. If not specified, monerod will use hardcoded seed nodes on the first run, and peers cached on disk on subsequent runs. --add-peer Manually add node to local peer list, host:port . Syntax supports IP addresses, domain names, onion and i2p hosts. --add-priority-node Specify list of nodes to connect to and then attempt to keep the connection open. To add multiple nodes use the option several times. Example: ./monerod --add-priority-node=178.128.192.138:18081 --add-priority-node=144.76.202.167:18081 --add-exclusive-node Specify list of nodes to connect to only. If this option is given the options --add-priority-node and --seed-node are ignored. To add multiple nodes use the option several times. Example: ./monerod --add-exclusive-node=178.128.192.138:18081 --add-exclusive-node=144.76.202.167:18081 --out-peers Set max number of outgoing connections to other nodes. By default 12. Value -1 represents the code default. --in-peers Set max number of incoming connections (nodes actively connecting to you). By default unlimited. Value -1 represents the code default. --limit-rate-up Set outgoing data transfer limit [kB/s]. By default 2048 kB/s. Value -1 represents the code default. --limit-rate-down Set incoming data transfer limit [kB/s]. By default 8192 kB/s. Value -1 represents the code default. --limit-rate Set the same limit value for incoming and outgoing data transfer. By default ( -1 ) the individual up/down default limits will be used. It is better to use --limit-rate-up and --limit-rate-down instead to avoid confusion. --offline Do not listen for peers, nor connect to any. Useful for working with a local, archival blockchain. --allow-local-ip Allow adding local IP to peer list. Useful mostly for debug purposes when you may want to have multiple nodes on a single machine. Tor/I2P \u00b6 This is experimental. It may be best to start with this guide . Option Description --tx-proxy Send out your local transactions through SOCKS5 proxy (Tor or I2P). Format: ,[,max_connections][,disable_noise] Example: ./monerod --tx-proxy \"tx-proxy=tor,127.0.0.1:9050,16\" This was introduced to make publishing transactions over Tor easier (no need for torsocks) while allowing clearnet for blocks at the same time (while torsocks affected everything). Adding ,disable_noise disables Dandelion++ (will speed up tx broadcast but is otherwise not recommended). Note that forwarded transactions (those not originating from connected wallet) will still be relayed over clearnet. Requires multiple --add-peer to manually add onion-enabled p2p seed nodes - see Tor onion seed nodes for Monero P2P network . See this guide and commit . --anonymous-inbound Allow anonymous incoming connections to your onionized P2P interface. Format: ,<[bind-ip:]port>[,max_connections] Example: ./monerod --anonymous-inbound \"rveahdfho7wo4b2m.onion:18083,127.0.0.1:18083,100\" . Obviously, you first need to setup the hidden service in your Tor config. See the guide . --pad-transactions Pad relayed transactions to next 1024 bytes to help defend against traffic volume analysis. This only makes sense if you are behind Tor or I2P. See commit . Node RPC API \u00b6 monerod node offers powerful API. It serves 3 purposes: provides network data (stats, blocks, transactions, ...) provides local node information (peer list, hash rate if mining, ...) provides interface for wallets (send transactions, ...) This API is typically referred to as \"RPC\" because it is mostly based on JSON/RPC standard. The following options define how the API behaves. Option Description --public-node Advertise to other users they can use this node as a remote one for connecting their wallets. Requires --restricted-rpc , --rpc-bind-ip and --confirm-external-bind . Without --public-node the node can still be public (assuming other relevant options are set) but won't be advertised as such on the P2P network. This option will allow wallets to auto-discover public nodes (instead of requiring user to manually find one). --rpc-bind-ip IP to listen on. By default 127.0.0.1 because API gives full administrative capabilities over the node. Set it to 0.0.0.0 to listen on all interfaces - but only in connection with one of *-restricted-* options and --confirm-external-bind . --rpc-bind-port TCP port to listen on. By default 18081 (mainnet), 28081 (testnet), 38081 (stagenet). --rpc-bind-ipv6-address IPv6 to listen on. By default ::1 (localhost). All remarks for --rpc-bind-ip are applicable here as well. --rpc-use-ipv6 Enable IPv6 for RPC server (disabled by default). --rpc-ignore-ipv4 Ignore unsuccessful IPv4 bind for RPC. Useful if you only want to use IPv6. --rpc-restricted-bind-ip IP to listen on with the limited version of API. The limited API can be made public to create an Open Node. --rpc-restricted-bind-port TCP port to listen on with the limited version of API. To be used in combination with `--rpc-restricted-bind-port . --confirm-external-bind Confirm you consciously set --rpc-bind-ip to non-localhost IP and you understand the consequences. --restricted-rpc Restrict API to view only commands and do not return privacy sensitive data. Note this does not make sense with --rpc-restricted-bind-port because you would end up with two restricted APIs. --rpc-ssl Enable TLS on RPC connections. One of: enabled | disabled | autodetect ( =autodetect by default). You should enable this if you connect a remote wallet. --rpc-ssl-private-key Path to server's private key in PEM format. Generate it with monero-gen-ssl-cert tool. This is to facilitate server authentication to client. --rpc-ssl-certificate Path to server's certificate in PEM format. Generate it with monero-gen-ssl-cert tool. This is to facilitate server authentication to client. --rpc-ssl-allowed-fingerprints List of certificate fingerprints to accept. This is a way to authenticate clients. --rpc-ssl-allow-any-cert Allow any certificate of connecting client. --rpc-ssl-ca-certificates Path to file containing concatenated PEM format certificate(s) to replace system CA(s). --rpc-ssl-allow-chained Allow user chained certificates. This is only applicable if user has a \"real\" CA issued certificate. --rpc-login Specify username[:password] required to connect to API. --rpc-access-control-origins Specify a comma separated list of origins to allow cross origin resource sharing. This is useful if you want to use monerod API directly from a web browser via JavaScript (say in a pure-fronted web appp scenario). With this option monerod will put proper HTTP CORS headers to its responses. You will also need to set --rpc-login if you use this option. Normally though, the API is used by backend app and this option isn't necessary. Accepting Monero \u00b6 These are network notifications offered by monerod . There are also wallet notifications like --tx-notify offered by monero-wallet-rpc here . Option Description --block-notify Run a program for each new block. The must be a full path . If the contains %s it will be replaced by the block hash. Example: ./monerod --block-notify=\"/usr/bin/echo %s\" Block notifications are good for immediate reaction. However, you should always assume you will miss some block notifications and you should independently poll the API to cover this up. Mind blockchain reorganizations. Block notifications can revert to same and past heights. Small reorganizations are natural and happen every day. --block-rate-notify Run a program when the number of blocks received in the recent past deviates significantly from the expectation. The must be a full path . The can contain any of %t , %b , %e symbols to interpolate: %t : the number of minutes in the observation window %b : the number of blocks observed in that window %e : the ideal number of blocks expected in that window The option will let you know if the network hash rate drops by a lot. This may be indicative of a large section of the network miners moving off to mine a private chain, to be later released to the network. Note that if this event triggers, it is not incontrovertible proof that this is happening. It might just be chance. The longer the window (the %t parameter), and the larger the distance between actual and expected number of blocks, the more indicative it is of a possible chain reorg double-spend attack being prepared. Recommendation: unless you run economically significant Monero exchange or operation, do not act on this data. It is hard to calibrate and easy to misinterpret. If this is a real attack, it will target high-liquidity entities and not small merchants. --reorg-notify Run a program when reorganization happens (ie, at least one block is removed from the top of the blockchain). The must be a full path . The can contain any of %s , %h , %n symbols to interpolate: %s : the height at which the split occurs %h : the height of the new blockchain %d : the number of blocks discarded from the old chain %n : the number of blocks being added The option will let you know when a block is removed from the chain to be replaced by other blocks. This happens when a 51% attack occurs, but small reorgs also happen in the normal course of things. The %d parameter will be set to the number of blocks discarded from the old chain (so if this is higher than the number of confirmations you wait to act upon an incoming payment, that payment might have been cancelled). The %n parameter wil be set to the number of blocks in the new chain (so if this is higher than the number of confirmations you wait to act upon an incoming payment, any incoming payment in the first block will be automatically acted upon by your platform). Recommendation : unless you run economically significant Monero exchange or operation, you do not need to bother with this option. Simply account for reorganizations by requiring at least 10 confirmations before shipping valuable goods. Performance \u00b6 These are advanced options that allow you to optimize performance of your monerod node, sometimes at the expense of reliability. Option Description --prune-blockchain Pruning saves 2/3 of disk space w/o degrading functionality. For maximum effect this should be used already on the first sync . If you add this option later the past data will only be pruned logically w/o shrinking the file size and the gain will be delayed. If you already have unpruned blockchain, see the monero-blockchain-prune tool. The drawback is that you will contribute less to Monero P2P network in terms of helping new nodes to sync up (up to 1/8 of normal contribution). You will still be useful regarding relaying new transactions and blocks though. --sync-pruned-blocks Accept pruned blocks instead of pruning yourself. It should save network transfer when used with --prune-blockchain . See the commit and comments . --db-sync-mode Specify sync option, using format: [safe|fast|fastest]:[sync|async]:[[blocks]|[bytes]] The default is fast:async:250000000bytes . The fast:async:* can corrupt blockchain database in case of a system crash. It should not corrupt if just monerod crashes. If you are concerned with system crashes use safe:sync . --max-concurrency Max number of threads to use for parallel jobs. The default value 0 uses the number of CPU threads. --prep-blocks-threads Max number of threads to use when computing block hashes (PoW) in groups. Defaults to 4. Decrease this if you don't want monerod hog your computer when syncing. --fast-block-sync Sync up most of the way by using embedded, \"known\" block hashes. Pass 1 to turn on and 0 to turn off. This is on ( 1 ) by default. Normally, for every block the full node must calculate the block hash to verify miner's proof of work. Because the CryptoNight PoW used in Monero is very expensive (even for verification), monerod offers skipping these calculations for old blocks. In other words, it's a mechanism to trust monerod binary regarding old blocks' PoW validity, to sync up faster. --block-sync-size How many blocks are processed in a single batch during chain synchronization. By default this is 20 blocks for newer history and 100 blocks for older history (\"pre v4\"). Default behavior is represented by value 0 . Intuitively, the more resources you have, the bigger batch size you may want to try out. Example: ./monerod --block-sync-size=500 --bootstrap-daemon-address The host:port of a \"bootstrap\" remote open node that the connected wallets can use while this node is still not fully synced. Example: ./monerod --bootstrap-daemon-address=opennode.xmr-tw.org:18089 . The node will forward selected RPC calls to the bootstrap node. The wallet will handle this automatically and transparently. Obviously, such bootstraping phase has privacy implications similar to directly using a remote node. --bootstrap-daemon-login Specify username:password for the bootstrap daemon login (if required). This considers the RPC interface used by the wallet. Normally, open nodes do not require any credentials. --no-sync Do not sync up. Continue using bootstrap daemon instead (if set). See commit . Mining \u00b6 The following options configure solo mining using CPU with the standard software stack monerod . This is mostly useful for: generating your stagenet or testnet coins experimentation and learning if you have super cheap access to vast CPU resources Be advised though that real mining happens in pools and with high-end GPU-s instead of CPU-s. Option Description --start-mining Specify wallet address to mining for. This must be a standard address ! It can be neither a subaddres nor integrated address. --mining-threads Specify mining threads count. By default ony one thread will be used. For best results, set it to number of your physical cores. --extra-messages-file Specify file for extra messages to include into coinbase transactions. --bg-mining-enable Enable unobtrusive mining. In this mode mining will use a small percentage of your system resources to never noticeably slow down your computer. This is intended to encourage people to mine to improve decentralization. That being said chances of finding a block are diminishingly small with solo CPU mining, and even lesser with its unobtrusive version. You can tweak the unobtrusivness / power trade-offs with the further --bg-* options below. --bg-mining-ignore-battery If true, assumes plugged in when unable to query system power status. --bg-mining-min-idle-interval Specify min lookback interval in seconds for determining idle state. --bg-mining-idle-threshold Specify minimum avg idle percentage over lookback interval. --bg-mining-miner-target Specify maximum percentage cpu use by miner(s). Testing Monero itself \u00b6 These options are useful for Monero project developers and testers. Normal users shouldn't be concerned with these. Option Description --keep-alt-blocks Keep alternative blocks on restart. May help with researching reorgs etc. Commit . Research project by noncesense research lab . --test-drop-download For net tests: in download, discard ALL blocks instead checking/saving them (very fast). --test-drop-download-height Like test-drop-download but discards only after around certain height. By default 0 . --regtest Run in a regression testing mode. --keep-fakechain Don't delete any existing database when in fakechain mode. --fixed-difficulty Fixed difficulty used for testing. By default 0 . --test-dbg-lock-sleep Sleep time in ms, defaults to 0 (off), used to debug before/after locking mutex. Values 100 to 1000 are good for tests. --save-graph Save data for dr Monero. Legacy \u00b6 These options should no longer be necessary. They are still present in monerod for backwards compatibility. Option Description --ban-list Specify ban list file, one IP address per line. This was introduced as an emergency measure to deal with large DDoS attacks on Monero p2p network in Dec 2020 / Jan 2021. Example: ./monerod --ban-list=block_tor.txt . Here is the popular block_tor.txt file. It is not recommended to statically ban any IP addresses unless you absolutely need to. Banning IPs often excludes the most vulnerable users who are forced to operate entirely behind Tor or other anonymity networks. --enable-dns-blocklist Similar to --ban-list but instead of a static file uses dynamic IP blocklist available as DNS TXT entries. The DNS blocklist is centrally managed by Monero contributors. It is not recommended unless in emergency situations. --fluffy-blocks Relay compact blocks. Default. Compact block is just a header and a list of transaction IDs. --no-fluffy-blocks Relay classic full blocks. Classic block contains all transactions. --show-time-stats Official docs say \"Show time-stats when processing blocks/txs and disk synchronization\" but it does not seem to produce any output during usual blockchain synchronization. --zmq-rpc-bind-ip IP for ZMQ RPC server to listen on. By default 127.0.0.1 . This is not yet widely used as ZMQ interface currently does not provide meaningful advantage over classic JSON-RPC interface. --zmq-rpc-bind-port Port for ZMQ RPC server to listen on. By default 18082 for mainnet, 38082 for stagenet, and 28082 for testnet. --zmq-pub Address for ZMQ pub - tcp://ip:port or ipc://path --db-type Specify database type. The default and only available: lmdb . Commands \u00b6 Commands give access to specific services provided by the daemon. Commands are executed against the running daemon. Their names follow the command_name pattern. The following groups are only to make reference easier to follow. The daemon itself does not group commands in any way. See running for example usage. You can also type commands directly in the console of the running monerod (if not detached). Help, version, status \u00b6 Option Description help [] Show help for . version Show version information. Example output: Monero 'Boron Butterfly' (v0.14.0.0-release) status Show status. Example output: Height: 186754/186754 (100.0%) on stagenet, not mining, net hash 317 H/s, v9, up to date, 8(out)+0(in) connections, uptime 0d 3h 48m 47s P2P network \u00b6 Option Description print_pl Show the full peer list. print_pl_stats Show the full peer list statistics (white vs gray peers). White peers are online and reachable. Grey peers are offline but your monerod remembers them from past sessions. print_cn Show connected peers with connection initiative (incoming/outgoing) and other stats. ban [] Ban a given for a given amount of . By default the ban is for 24h. Example: ./monerod ban 187.63.135.161 . unban Unban a given . bans Show the currently banned IPs. Example output: 187.63.135.161 banned for 86397 seconds . in_peers Set the of incoming connections from other peers. out_peers Set the of outgoing connections to other peers. limit [] Get or set the download and upload limit. limit_down [] Get or set the download limit. limit_up [] Get or set the upload limit. Transaction pool \u00b6 Option Description flush_txpool [] Flush specified transaction from transactions pool, or flush the whole transactions pool if was not provided. print_pool Print the transaction pool using a verbose format. print_pool_sh Print the transaction pool using a short format. print_pool_stats Print the transaction pool's statistics (number of transactions, memory size, fees, double spend attempts etc). Transactions \u00b6 Option Description print_coinbase_tx_sum [] Show a sum of all emitted coins and paid fees within specified range. Example: ./monerod print_coinbase_tx_sum 0 1000000000000 print_tx [+hex] [+json] Show specified transaction as JSON and/or HEX. relay_tx Force relaying the transaction. Useful if you want to rebroadcast the transaction for any reason or if transaction was previously created with \"do_not_relay\":true. Blockchain \u00b6 Option Description print_height Show local blockchain height. sync_info Show blockchain sync progress and connected peers along with download / upload stats. print_bc [] Show blocks in range .. . The information will include block id, height, timestamp, version, size, weight, number of non-coinbase transactions, difficulty, nonce, and reward. print_block | Show detailed data of specified block. hard_fork_info Show current consensus version and future hard fork block height, if any. is_key_image_spent Check if specified key image is spent. Key image is a hash. Manage daemon \u00b6 Option Description exit , stop_daemon Ask daemon to exit gracefully. The exit and stop_daemon are identical (one is alias of the other). set_log |<{+,-,}categories> Set the current log level/categories where is a number 0-4. print_status Show if daemon is running. update (check|download) Check if update is available and optionally download it. The hash is SHA-256. On linux use sha256sum to verify. Example output: Update available: v0.13.0.4: https://downloads.getmonero.org/cli/monero-linux-x64-v0.13.0.4.tar.bz2, hash 693e1a0210201f65138ace679d1ab1928aca06bb6e679c20d8b4d2d8717e50d6 Update downloaded to: /opt/monero-v0.13.0.2/monero-linux-x64-v0.13.0.4.tar.bz2 Mining \u00b6 Option Description show_hr Ask monerod daemon to print current hash rate. Relevant only if monerod is mining. hide_hr Ask monerod daemon to stop printing current hash rate. Relevant only if monerod is mining. start_mining [] [do_background_mining] [ignore_battery] Ask monerod daemon to start mining. Block reward will go to . stop_mining Ask monerod daemon to stop mining. Testing Monero itself \u00b6 Option Description start_save_graph Start saving data for dr Monero. stop_save_graph Stop saving data for dr Monero. Legacy \u00b6 Option Description save Flush blockchain data to disk. This is normally no longer necessary as monerod saves the blockchain automatically on exit. output_histogram [@] [] Show number of outputs for each amount denomination. This was only relevant in the pre-RingCT era. The old wallet used this to determine which outputs can be used for the requested mixin. With RingCT denominations are irrelevant as amounts are hidden. More info in these SA answers .","title":"monerod"},{"location":"interacting/monerod-reference/#monerod-reference","text":"","title":"monerod - Reference"},{"location":"interacting/monerod-reference/#overview","text":"","title":"Overview"},{"location":"interacting/monerod-reference/#connects-you-to-monero-network","text":"The Monero daemon monerod keeps your computer synced up with the Monero network. It downloads and validates the blockchain from the p2p network.","title":"Connects you to Monero network"},{"location":"interacting/monerod-reference/#not-aware-of-your-private-keys","text":"monerod is entirely decoupled from your wallet. monerod does not access your private keys - it is not aware of your transactions and balance. This allows you to run monerod on a separate computer or in the cloud. In fact, you can connect to a remote monerod instance provided by a semi-trusted 3rd party. Such 3rd party will not be able to steal your funds. This is very handy for learning and experimentation. However, there are privacy and reliability implications to using a remote, untrusted node. For any real business you should be running your own full node .","title":"Not aware of your private keys"},{"location":"interacting/monerod-reference/#syntax","text":"./monerod [options] [command] Options define how the daemon should be working. Their names follow the --option-name pattern. Commands give access to specific services provided by the daemon. Commands are executed against the running daemon. Their names follow the command_name pattern.","title":"Syntax"},{"location":"interacting/monerod-reference/#running","text":"Go to directory where you unpacked Monero. The stagenet is what your should be using for learning and experimentation. ./monerod --stagenet --detach # run as a daemon in background tail -f ~/.bitmonero/stagenet/bitmonero.log # watch the logs ./monerod --stagenet exit # ask daemon to exit gracefully The mainnnet is when you want to deal with the real XMR. ./monerod --detach # run as a daemon in background tail -f ~/.bitmonero/bitmonero.log # watch the logs ./monerod exit # ask daemon to exit gracefully","title":"Running"},{"location":"interacting/monerod-reference/#options","text":"Options define how the daemon should be working. Their names follow the --option-name pattern. The following groups are only to make reference easier to follow. The daemon itself does not group options in any way.","title":"Options"},{"location":"interacting/monerod-reference/#help-and-version","text":"Option Description --help Enlist available options. --version Show monerod version to stdout. Example output: Monero 'Oxygen Orion' (v0.17.1.8-release) --os-version Show build timestamp and target operating system. Example output: OS: Linux #65-Ubuntu SMP Thu Dec 10 12:01:51 UTC 2020 5.4.0-59-generic . --check-updates One of: disabled | notify | download (= notify by default). Check for new versions of Monero and optionally download it. You should probably prefer your OS package manager to do the update, if possible. There is also unimplemented update option shown by the help system.","title":"Help and version"},{"location":"interacting/monerod-reference/#pick-network","text":"Option Description (missing) By default monerod assumes mainnet . --stagenet Run on stagenet . Remember to run your wallet with --stagenet as well. --testnet Run on testnet . Remember to run your wallet with --testnet as well.","title":"Pick network"},{"location":"interacting/monerod-reference/#logging","text":"Option Description --log-file Full path to the log file. Example (mind file permissions): ./monerod --log-file=/var/log/monero/mainnet/monerod.log --log-level 0-4 with 0 being minimal logging and 4 being full tracing. Defaults to 0 . These are general presets and do not directly map to severity levels. For example, even with minimal 0 , you may see some most important INFO entries. Temporarily changing to 1 allows for much better understanding of how the full node operates. Example: ./monerod --log-level=1 --max-log-file-size Soft limit in bytes for the log file (=104850000 by default, which is just under 100MB). Once log file grows past that limit, monerod creates the next log file with a UTC timestamp postfix -YYYY-MM-DD-HH-MM-SS . In production deployments, you would probably prefer to use established solutions like logrotate instead. In that case, set --max-log-file-size=0 to prevent monerod from managing the log files. --max-log-files Limit on the number of log files (=50 by default). The oldest log files are removed. In production deployments, you would probably prefer to use established solutions like logrotate instead.","title":"Logging"},{"location":"interacting/monerod-reference/#server","text":"monerod defaults are adjusted for running it occasionally on the same computer as your Monero wallet. The following options will be helpful if you intend to have an always running node \u2014 most likely on a remote server or your own separate PC. Option Description --config-file Full path to the configuration file . By default monerod looks for bitmonero.conf in Monero data directory . --data-dir Full path to data directory. This is where the blockchain, log files, and p2p network memory are stored. For defaults and details see data directory . --pidfile Full path to the PID file. Works only with --detach . Example: ./monerod --detach --pidfile=/run/monero/monerod.pid --detach Go to background (decouple from the terminal). This is useful for long-running / server scenarios. Typically, you will also want to manage monerod daemon with systemd or similar. By default monerod runs in a foreground. --non-interactive Do not require tty in a foreground mode. Helpful when running in a container. By default monerod runs in a foreground and opens stdin for reading. This breaks containerization because no tty gets assigned and monerod process crashes. You can make it run in a background with --detach but this is inconvenient in a containerized environment because the canonical usage is that the container waits on the main process to exist (forking makes things more complicated). --no-zmq Disable ZMQ RPC server. You should use this option to limit attack surface and number of unnecessarily open ports (the ZMQ server is unfinished thing and you are unlikely to ever use it). --no-igd Disable UPnP port mapping on the router (\"Internet Gateway Device\"). Add this option to improve security if you are not behind a NAT (you can bind directly to public IP or you run through Tor). --max-txpool-weight Set maximum transactions pool size in bytes. By default 648000000 (~618MB). These are transactions pending for confirmations (not included in any block). --enforce-dns-checkpointing The emergency checkpoints set by MoneroPulse operators will be enforced. It is probably a good idea to set enforcing for unattended nodes. If encountered block hash does not match corresponding checkpoint, the local blockchain will be rolled back a few blocks, effectively blocking following what MoneroPulse operators consider invalid fork. The log entry will be produced: ERROR Local blockchain failed to pass a checkpoint, rolling back! Eventually, the alternative (\"fixed\") fork will get heavier and the node will follow it, leaving the \"invalid\" fork behind. By default checkpointing only notifies about discrepancy by producing the following log entry: ERROR WARNING: local blockchain failed to pass a MoneroPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option . Reference: source code . --disable-dns-checkpoints The MoneroPulse checkpoints set by core developers will be discarded. The checkpoints are apparently still fetched though.","title":"Server"},{"location":"interacting/monerod-reference/#p2p-network","text":"The following options define how your node participates in Monero peer-to-peer network. This is for node-to-node communication. The following options do not affect wallet-to-node interface. The node and peer words are used interchangeably. Option Description --p2p-bind-ip IPv4 network interface to bind to for p2p network protocol. Default value 0.0.0.0 binds to all network interfaces. This is typically what you want. You must change this if you want to constrain binding, for example to force working through Tor via torsocks: DNS_PUBLIC=tcp://1.1.1.1 TORSOCKS_ALLOW_INBOUND=1 torsocks ./monerod --p2p-bind-ip 127.0.0.1\u200a --no-igd\u200a --hide-my-port --p2p-bind-port TCP port to listen for p2p network connections. Defaults to 18080 for mainnet, 28080 for testnet, and 38080 for stagenet. You normally wouldn't change that. This is helpful to run several nodes on your machine to simulate private Monero p2p network (likely using private Testnet). Example: ./monerod --p2p-bind-port=48080 --p2p-external-port TCP port to listen for p2p network connections on your router. Relevant if you are behind a NAT and still want to accept incoming connections. You must then set this to relevant port on your router. This is to let monerod know what to advertise on the network. Default is 0 . --p2p-use-ipv6 Enable IPv6 for p2p (disabled by default). --p2p-bind-ipv6-address IPv6 network interface to bind to for p2p network protocol. Default value :: binds to all network interfaces. --p2p-ignore-ipv4 Ignore unsuccessful IPv4 bind for p2p. Useful if you only want to use IPv6. --igd Set UPnP port mapping on the router (\"Internet Gateway Device\"). One of: disabled | enabled | delayed (= delayed by default). Relevant if you are behind NAT and want to accept incoming P2P network connections. The delayed value means it will wait for incoming connections in hope UPnP may not be necessary. After a while w/o incoming connections found it will attempt to map ports with UPnP. If you know you need UPnP change it to enabled to fast track the process. --hide-my-port monerod will still open and listen on the p2p port. However, it will not announce itself as a peer list candidate. Technically, it will return port 0 in a response to p2p handshake ( node_data.my_port = 0 in get_local_node_data function). In effect nodes you connect to won't spread your IP to other nodes. To sum up, it is not really hiding, it is more like \"do not advertise\". --seed-node Connect to a node to retrieve other nodes' addresses, and disconnect. If not specified, monerod will use hardcoded seed nodes on the first run, and peers cached on disk on subsequent runs. --add-peer Manually add node to local peer list, host:port . Syntax supports IP addresses, domain names, onion and i2p hosts. --add-priority-node Specify list of nodes to connect to and then attempt to keep the connection open. To add multiple nodes use the option several times. Example: ./monerod --add-priority-node=178.128.192.138:18081 --add-priority-node=144.76.202.167:18081 --add-exclusive-node Specify list of nodes to connect to only. If this option is given the options --add-priority-node and --seed-node are ignored. To add multiple nodes use the option several times. Example: ./monerod --add-exclusive-node=178.128.192.138:18081 --add-exclusive-node=144.76.202.167:18081 --out-peers Set max number of outgoing connections to other nodes. By default 12. Value -1 represents the code default. --in-peers Set max number of incoming connections (nodes actively connecting to you). By default unlimited. Value -1 represents the code default. --limit-rate-up Set outgoing data transfer limit [kB/s]. By default 2048 kB/s. Value -1 represents the code default. --limit-rate-down Set incoming data transfer limit [kB/s]. By default 8192 kB/s. Value -1 represents the code default. --limit-rate Set the same limit value for incoming and outgoing data transfer. By default ( -1 ) the individual up/down default limits will be used. It is better to use --limit-rate-up and --limit-rate-down instead to avoid confusion. --offline Do not listen for peers, nor connect to any. Useful for working with a local, archival blockchain. --allow-local-ip Allow adding local IP to peer list. Useful mostly for debug purposes when you may want to have multiple nodes on a single machine.","title":"P2P network"},{"location":"interacting/monerod-reference/#tori2p","text":"This is experimental. It may be best to start with this guide . Option Description --tx-proxy Send out your local transactions through SOCKS5 proxy (Tor or I2P). Format: ,[,max_connections][,disable_noise] Example: ./monerod --tx-proxy \"tx-proxy=tor,127.0.0.1:9050,16\" This was introduced to make publishing transactions over Tor easier (no need for torsocks) while allowing clearnet for blocks at the same time (while torsocks affected everything). Adding ,disable_noise disables Dandelion++ (will speed up tx broadcast but is otherwise not recommended). Note that forwarded transactions (those not originating from connected wallet) will still be relayed over clearnet. Requires multiple --add-peer to manually add onion-enabled p2p seed nodes - see Tor onion seed nodes for Monero P2P network . See this guide and commit . --anonymous-inbound Allow anonymous incoming connections to your onionized P2P interface. Format: ,<[bind-ip:]port>[,max_connections] Example: ./monerod --anonymous-inbound \"rveahdfho7wo4b2m.onion:18083,127.0.0.1:18083,100\" . Obviously, you first need to setup the hidden service in your Tor config. See the guide . --pad-transactions Pad relayed transactions to next 1024 bytes to help defend against traffic volume analysis. This only makes sense if you are behind Tor or I2P. See commit .","title":"Tor/I2P"},{"location":"interacting/monerod-reference/#node-rpc-api","text":"monerod node offers powerful API. It serves 3 purposes: provides network data (stats, blocks, transactions, ...) provides local node information (peer list, hash rate if mining, ...) provides interface for wallets (send transactions, ...) This API is typically referred to as \"RPC\" because it is mostly based on JSON/RPC standard. The following options define how the API behaves. Option Description --public-node Advertise to other users they can use this node as a remote one for connecting their wallets. Requires --restricted-rpc , --rpc-bind-ip and --confirm-external-bind . Without --public-node the node can still be public (assuming other relevant options are set) but won't be advertised as such on the P2P network. This option will allow wallets to auto-discover public nodes (instead of requiring user to manually find one). --rpc-bind-ip IP to listen on. By default 127.0.0.1 because API gives full administrative capabilities over the node. Set it to 0.0.0.0 to listen on all interfaces - but only in connection with one of *-restricted-* options and --confirm-external-bind . --rpc-bind-port TCP port to listen on. By default 18081 (mainnet), 28081 (testnet), 38081 (stagenet). --rpc-bind-ipv6-address IPv6 to listen on. By default ::1 (localhost). All remarks for --rpc-bind-ip are applicable here as well. --rpc-use-ipv6 Enable IPv6 for RPC server (disabled by default). --rpc-ignore-ipv4 Ignore unsuccessful IPv4 bind for RPC. Useful if you only want to use IPv6. --rpc-restricted-bind-ip IP to listen on with the limited version of API. The limited API can be made public to create an Open Node. --rpc-restricted-bind-port TCP port to listen on with the limited version of API. To be used in combination with `--rpc-restricted-bind-port . --confirm-external-bind Confirm you consciously set --rpc-bind-ip to non-localhost IP and you understand the consequences. --restricted-rpc Restrict API to view only commands and do not return privacy sensitive data. Note this does not make sense with --rpc-restricted-bind-port because you would end up with two restricted APIs. --rpc-ssl Enable TLS on RPC connections. One of: enabled | disabled | autodetect ( =autodetect by default). You should enable this if you connect a remote wallet. --rpc-ssl-private-key Path to server's private key in PEM format. Generate it with monero-gen-ssl-cert tool. This is to facilitate server authentication to client. --rpc-ssl-certificate Path to server's certificate in PEM format. Generate it with monero-gen-ssl-cert tool. This is to facilitate server authentication to client. --rpc-ssl-allowed-fingerprints List of certificate fingerprints to accept. This is a way to authenticate clients. --rpc-ssl-allow-any-cert Allow any certificate of connecting client. --rpc-ssl-ca-certificates Path to file containing concatenated PEM format certificate(s) to replace system CA(s). --rpc-ssl-allow-chained Allow user chained certificates. This is only applicable if user has a \"real\" CA issued certificate. --rpc-login Specify username[:password] required to connect to API. --rpc-access-control-origins Specify a comma separated list of origins to allow cross origin resource sharing. This is useful if you want to use monerod API directly from a web browser via JavaScript (say in a pure-fronted web appp scenario). With this option monerod will put proper HTTP CORS headers to its responses. You will also need to set --rpc-login if you use this option. Normally though, the API is used by backend app and this option isn't necessary.","title":"Node RPC API"},{"location":"interacting/monerod-reference/#accepting-monero","text":"These are network notifications offered by monerod . There are also wallet notifications like --tx-notify offered by monero-wallet-rpc here . Option Description --block-notify Run a program for each new block. The must be a full path . If the contains %s it will be replaced by the block hash. Example: ./monerod --block-notify=\"/usr/bin/echo %s\" Block notifications are good for immediate reaction. However, you should always assume you will miss some block notifications and you should independently poll the API to cover this up. Mind blockchain reorganizations. Block notifications can revert to same and past heights. Small reorganizations are natural and happen every day. --block-rate-notify Run a program when the number of blocks received in the recent past deviates significantly from the expectation. The must be a full path . The can contain any of %t , %b , %e symbols to interpolate: %t : the number of minutes in the observation window %b : the number of blocks observed in that window %e : the ideal number of blocks expected in that window The option will let you know if the network hash rate drops by a lot. This may be indicative of a large section of the network miners moving off to mine a private chain, to be later released to the network. Note that if this event triggers, it is not incontrovertible proof that this is happening. It might just be chance. The longer the window (the %t parameter), and the larger the distance between actual and expected number of blocks, the more indicative it is of a possible chain reorg double-spend attack being prepared. Recommendation: unless you run economically significant Monero exchange or operation, do not act on this data. It is hard to calibrate and easy to misinterpret. If this is a real attack, it will target high-liquidity entities and not small merchants. --reorg-notify Run a program when reorganization happens (ie, at least one block is removed from the top of the blockchain). The must be a full path . The can contain any of %s , %h , %n symbols to interpolate: %s : the height at which the split occurs %h : the height of the new blockchain %d : the number of blocks discarded from the old chain %n : the number of blocks being added The option will let you know when a block is removed from the chain to be replaced by other blocks. This happens when a 51% attack occurs, but small reorgs also happen in the normal course of things. The %d parameter will be set to the number of blocks discarded from the old chain (so if this is higher than the number of confirmations you wait to act upon an incoming payment, that payment might have been cancelled). The %n parameter wil be set to the number of blocks in the new chain (so if this is higher than the number of confirmations you wait to act upon an incoming payment, any incoming payment in the first block will be automatically acted upon by your platform). Recommendation : unless you run economically significant Monero exchange or operation, you do not need to bother with this option. Simply account for reorganizations by requiring at least 10 confirmations before shipping valuable goods.","title":"Accepting Monero"},{"location":"interacting/monerod-reference/#performance","text":"These are advanced options that allow you to optimize performance of your monerod node, sometimes at the expense of reliability. Option Description --prune-blockchain Pruning saves 2/3 of disk space w/o degrading functionality. For maximum effect this should be used already on the first sync . If you add this option later the past data will only be pruned logically w/o shrinking the file size and the gain will be delayed. If you already have unpruned blockchain, see the monero-blockchain-prune tool. The drawback is that you will contribute less to Monero P2P network in terms of helping new nodes to sync up (up to 1/8 of normal contribution). You will still be useful regarding relaying new transactions and blocks though. --sync-pruned-blocks Accept pruned blocks instead of pruning yourself. It should save network transfer when used with --prune-blockchain . See the commit and comments . --db-sync-mode Specify sync option, using format: [safe|fast|fastest]:[sync|async]:[[blocks]|[bytes]] The default is fast:async:250000000bytes . The fast:async:* can corrupt blockchain database in case of a system crash. It should not corrupt if just monerod crashes. If you are concerned with system crashes use safe:sync . --max-concurrency Max number of threads to use for parallel jobs. The default value 0 uses the number of CPU threads. --prep-blocks-threads Max number of threads to use when computing block hashes (PoW) in groups. Defaults to 4. Decrease this if you don't want monerod hog your computer when syncing. --fast-block-sync Sync up most of the way by using embedded, \"known\" block hashes. Pass 1 to turn on and 0 to turn off. This is on ( 1 ) by default. Normally, for every block the full node must calculate the block hash to verify miner's proof of work. Because the CryptoNight PoW used in Monero is very expensive (even for verification), monerod offers skipping these calculations for old blocks. In other words, it's a mechanism to trust monerod binary regarding old blocks' PoW validity, to sync up faster. --block-sync-size How many blocks are processed in a single batch during chain synchronization. By default this is 20 blocks for newer history and 100 blocks for older history (\"pre v4\"). Default behavior is represented by value 0 . Intuitively, the more resources you have, the bigger batch size you may want to try out. Example: ./monerod --block-sync-size=500 --bootstrap-daemon-address The host:port of a \"bootstrap\" remote open node that the connected wallets can use while this node is still not fully synced. Example: ./monerod --bootstrap-daemon-address=opennode.xmr-tw.org:18089 . The node will forward selected RPC calls to the bootstrap node. The wallet will handle this automatically and transparently. Obviously, such bootstraping phase has privacy implications similar to directly using a remote node. --bootstrap-daemon-login Specify username:password for the bootstrap daemon login (if required). This considers the RPC interface used by the wallet. Normally, open nodes do not require any credentials. --no-sync Do not sync up. Continue using bootstrap daemon instead (if set). See commit .","title":"Performance"},{"location":"interacting/monerod-reference/#mining","text":"The following options configure solo mining using CPU with the standard software stack monerod . This is mostly useful for: generating your stagenet or testnet coins experimentation and learning if you have super cheap access to vast CPU resources Be advised though that real mining happens in pools and with high-end GPU-s instead of CPU-s. Option Description --start-mining Specify wallet address to mining for. This must be a standard address ! It can be neither a subaddres nor integrated address. --mining-threads Specify mining threads count. By default ony one thread will be used. For best results, set it to number of your physical cores. --extra-messages-file Specify file for extra messages to include into coinbase transactions. --bg-mining-enable Enable unobtrusive mining. In this mode mining will use a small percentage of your system resources to never noticeably slow down your computer. This is intended to encourage people to mine to improve decentralization. That being said chances of finding a block are diminishingly small with solo CPU mining, and even lesser with its unobtrusive version. You can tweak the unobtrusivness / power trade-offs with the further --bg-* options below. --bg-mining-ignore-battery If true, assumes plugged in when unable to query system power status. --bg-mining-min-idle-interval Specify min lookback interval in seconds for determining idle state. --bg-mining-idle-threshold Specify minimum avg idle percentage over lookback interval. --bg-mining-miner-target Specify maximum percentage cpu use by miner(s).","title":"Mining"},{"location":"interacting/monerod-reference/#testing-monero-itself","text":"These options are useful for Monero project developers and testers. Normal users shouldn't be concerned with these. Option Description --keep-alt-blocks Keep alternative blocks on restart. May help with researching reorgs etc. Commit . Research project by noncesense research lab . --test-drop-download For net tests: in download, discard ALL blocks instead checking/saving them (very fast). --test-drop-download-height Like test-drop-download but discards only after around certain height. By default 0 . --regtest Run in a regression testing mode. --keep-fakechain Don't delete any existing database when in fakechain mode. --fixed-difficulty Fixed difficulty used for testing. By default 0 . --test-dbg-lock-sleep Sleep time in ms, defaults to 0 (off), used to debug before/after locking mutex. Values 100 to 1000 are good for tests. --save-graph Save data for dr Monero.","title":"Testing Monero itself"},{"location":"interacting/monerod-reference/#legacy","text":"These options should no longer be necessary. They are still present in monerod for backwards compatibility. Option Description --ban-list Specify ban list file, one IP address per line. This was introduced as an emergency measure to deal with large DDoS attacks on Monero p2p network in Dec 2020 / Jan 2021. Example: ./monerod --ban-list=block_tor.txt . Here is the popular block_tor.txt file. It is not recommended to statically ban any IP addresses unless you absolutely need to. Banning IPs often excludes the most vulnerable users who are forced to operate entirely behind Tor or other anonymity networks. --enable-dns-blocklist Similar to --ban-list but instead of a static file uses dynamic IP blocklist available as DNS TXT entries. The DNS blocklist is centrally managed by Monero contributors. It is not recommended unless in emergency situations. --fluffy-blocks Relay compact blocks. Default. Compact block is just a header and a list of transaction IDs. --no-fluffy-blocks Relay classic full blocks. Classic block contains all transactions. --show-time-stats Official docs say \"Show time-stats when processing blocks/txs and disk synchronization\" but it does not seem to produce any output during usual blockchain synchronization. --zmq-rpc-bind-ip IP for ZMQ RPC server to listen on. By default 127.0.0.1 . This is not yet widely used as ZMQ interface currently does not provide meaningful advantage over classic JSON-RPC interface. --zmq-rpc-bind-port Port for ZMQ RPC server to listen on. By default 18082 for mainnet, 38082 for stagenet, and 28082 for testnet. --zmq-pub Address for ZMQ pub - tcp://ip:port or ipc://path --db-type Specify database type. The default and only available: lmdb .","title":"Legacy"},{"location":"interacting/monerod-reference/#commands","text":"Commands give access to specific services provided by the daemon. Commands are executed against the running daemon. Their names follow the command_name pattern. The following groups are only to make reference easier to follow. The daemon itself does not group commands in any way. See running for example usage. You can also type commands directly in the console of the running monerod (if not detached).","title":"Commands"},{"location":"interacting/monerod-reference/#help-version-status","text":"Option Description help [] Show help for . version Show version information. Example output: Monero 'Boron Butterfly' (v0.14.0.0-release) status Show status. Example output: Height: 186754/186754 (100.0%) on stagenet, not mining, net hash 317 H/s, v9, up to date, 8(out)+0(in) connections, uptime 0d 3h 48m 47s","title":"Help, version, status"},{"location":"interacting/monerod-reference/#p2p-network_1","text":"Option Description print_pl Show the full peer list. print_pl_stats Show the full peer list statistics (white vs gray peers). White peers are online and reachable. Grey peers are offline but your monerod remembers them from past sessions. print_cn Show connected peers with connection initiative (incoming/outgoing) and other stats. ban [] Ban a given for a given amount of . By default the ban is for 24h. Example: ./monerod ban 187.63.135.161 . unban Unban a given . bans Show the currently banned IPs. Example output: 187.63.135.161 banned for 86397 seconds . in_peers Set the of incoming connections from other peers. out_peers Set the of outgoing connections to other peers. limit [] Get or set the download and upload limit. limit_down [] Get or set the download limit. limit_up [] Get or set the upload limit.","title":"P2P network"},{"location":"interacting/monerod-reference/#transaction-pool","text":"Option Description flush_txpool [] Flush specified transaction from transactions pool, or flush the whole transactions pool if was not provided. print_pool Print the transaction pool using a verbose format. print_pool_sh Print the transaction pool using a short format. print_pool_stats Print the transaction pool's statistics (number of transactions, memory size, fees, double spend attempts etc).","title":"Transaction pool"},{"location":"interacting/monerod-reference/#transactions","text":"Option Description print_coinbase_tx_sum [] Show a sum of all emitted coins and paid fees within specified range. Example: ./monerod print_coinbase_tx_sum 0 1000000000000 print_tx [+hex] [+json] Show specified transaction as JSON and/or HEX. relay_tx Force relaying the transaction. Useful if you want to rebroadcast the transaction for any reason or if transaction was previously created with \"do_not_relay\":true.","title":"Transactions"},{"location":"interacting/monerod-reference/#blockchain","text":"Option Description print_height Show local blockchain height. sync_info Show blockchain sync progress and connected peers along with download / upload stats. print_bc [] Show blocks in range .. . The information will include block id, height, timestamp, version, size, weight, number of non-coinbase transactions, difficulty, nonce, and reward. print_block | Show detailed data of specified block. hard_fork_info Show current consensus version and future hard fork block height, if any. is_key_image_spent Check if specified key image is spent. Key image is a hash.","title":"Blockchain"},{"location":"interacting/monerod-reference/#manage-daemon","text":"Option Description exit , stop_daemon Ask daemon to exit gracefully. The exit and stop_daemon are identical (one is alias of the other). set_log |<{+,-,}categories> Set the current log level/categories where is a number 0-4. print_status Show if daemon is running. update (check|download) Check if update is available and optionally download it. The hash is SHA-256. On linux use sha256sum to verify. Example output: Update available: v0.13.0.4: https://downloads.getmonero.org/cli/monero-linux-x64-v0.13.0.4.tar.bz2, hash 693e1a0210201f65138ace679d1ab1928aca06bb6e679c20d8b4d2d8717e50d6 Update downloaded to: /opt/monero-v0.13.0.2/monero-linux-x64-v0.13.0.4.tar.bz2","title":"Manage daemon"},{"location":"interacting/monerod-reference/#mining_1","text":"Option Description show_hr Ask monerod daemon to print current hash rate. Relevant only if monerod is mining. hide_hr Ask monerod daemon to stop printing current hash rate. Relevant only if monerod is mining. start_mining [] [do_background_mining] [ignore_battery] Ask monerod daemon to start mining. Block reward will go to . stop_mining Ask monerod daemon to stop mining.","title":"Mining"},{"location":"interacting/monerod-reference/#testing-monero-itself_1","text":"Option Description start_save_graph Start saving data for dr Monero. stop_save_graph Stop saving data for dr Monero.","title":"Testing Monero itself"},{"location":"interacting/monerod-reference/#legacy_1","text":"Option Description save Flush blockchain data to disk. This is normally no longer necessary as monerod saves the blockchain automatically on exit. output_histogram [@] [] Show number of outputs for each amount denomination. This was only relevant in the pre-RingCT era. The old wallet used this to determine which outputs can be used for the requested mixin. With RingCT denominations are irrelevant as amounts are hidden. More info in these SA answers .","title":"Legacy"},{"location":"interacting/overview/","text":"Interacting with Monero \u00b6 You can interact with Monero via desktop GUI, commandline interface, and programming API. On top of that, Monero nodes interact with each other in a peer-to-peer network. Installation directory overview \u00b6 Once unpacked you will see several executable files. You will also find a nice PDF guide for the GUI wallet. Monero project nicely decouples network node logic from wallet logic. Wallet logic is offered through three independent user interfaces - the GUI, the CLI, and the HTTP API. # cd monero-gui-v0.17.1.9 # ---- guide to Monero GUI ---- monero-gui-wallet-guide.pdf # ---- main executable files ----------- monerod monero-wallet-gui # ---- extra executable files ----------- extras/monero-wallet-cli extras/monero-wallet-rpc extras/monero-blockchain-prune extras/monero-gen-trusted-multisig extras/monero-gen-ssl-cert extras/monero-blockchain-export extras/monero-blockchain-import # ---- don't bother with these ---------- extras/monero-blockchain-stats extras/monero-blockchain-mark-spent-outputs extras/monero-blockchain-prune-known-spent-data extras/monero-blockchain-usage extras/monero-blockchain-ancestry extras/monero-blockchain-depth Executables \u00b6 Executable Description monerod The full node daemon. Does not require a wallet. Documentation . monero-wallet-gui Wallet logic and graphical user interface. Requires monerod running. monero-wallet-cli Wallet logic and commandline user interface. Requires monerod running. monero-wallet-rpc Wallet logic and HTTP API (JSON-RPC protocol). Requires monerod running. monero-blockchain-prune Prune existing local blockchain. This saves 2/3 of disk space (down to 31GB as of Jan 2021). This is preferable over monerod --prune-blockchain which only logically releases space inside the file while the file remains large. The monero-blockchain-prune creates a shrinked copy of the blockchain file. See tutorial1 , tutorial2 . monero-gen-ssl-cert Generate 4096 bit RSA private key and self signed TLS certificate for use with monerod RPC interface. Note, Monero daemon automatically generates TLS certificate on each restart. Manual generation with this tool is only useful if you want to pin TLS certificate fingerprint in your monero wallet. See the pull request . monero-gen-trusted-multisig Tool to generate a set of multisig wallets. See chapter on multisignatures . monero-blockchain-export Tool to export blockchain to blockchain.raw file. monero-blockchain-import Tool to import blockchain.raw - ideally your own trusted copy. Executables - legacy \u00b6 You most likely should not bother with these legacy or very specialized tools. Executable Description monero-blockchain-stats Generate stats like tx/day, blocks/day, bytes/day based on your local blockchain. monero-blockchain-mark-spent-outputs Advanced tool to mitigate potential privacy issues related to Monero forks. You normally shouldn't be concerned with that. See the commit and pull request . monero-blockchain-prune-known-spent-data Previous limited pruning tool to prune select \"known spent\" transaction outputs (from the before RCT era). Nowadays prefer monero-blockchain-prune . This only saves ~200 MB. See the commit . monero-blockchain-usage Advanced tool to mitigate potential privacy issues related to Monero forks. You normally shouldn't be concerned with that. See the commit and the pull request . monero-blockchain-ancestry Advanced research tool to learn ancestors of a transaction, block or chain. Irrelevant for normal users. See this pull request . monero-blockchain-depth Advanced research tool to learn depth of a transaction, block or chain. Irrelevant for normal users. See this commit . Interacting \u00b6 There are quite a few ways you can interact with Monero software. Perhaps the most surprising for newcomers is that monerod daemon accepts interactive keyboard commands while it is running. Also, please note that HTTP API is split across monerod and monero-wallet-rpc . You need to run and call both daemons to explore the full API. This follows the node-logic vs wallet-logic split mentioned earlier. All wallet implementations depend on the monerod running. Executable p2p network node commands via keyboard node HTTP API wallet commands via keyboard wallet HTTP API wallet via GUI monerod \u2714 \u2714 \u2714 monero-wallet-cli \u2714 monero-wallet-rpc \u2714 monero-wallet-gui \u2714 Data directory \u00b6 This is where the blockchain, log files, and p2p network memory are stored. By default data directory is at: $HOME/.bitmonero/ on Linux and macOS C:\\ProgramData\\bitmonero\\ on Windows Please mind: data directory is hidden as per OS convention the bitmonero directory name is historical artefact from before Monero forked away from Bitmonero, about 2000 years Before Christ Data directory contains: lmdb/ - the blockchain database directory p2pstate.bin - saved memory of discovered and rated peers bitmonero.log - log file It can also contain subdirectories for stagenet and testnet, mirroring the same structure: stagenet/ - data directory for Stagenet testnet/ - data directory for Testnet","title":"Overview"},{"location":"interacting/overview/#interacting-with-monero","text":"You can interact with Monero via desktop GUI, commandline interface, and programming API. On top of that, Monero nodes interact with each other in a peer-to-peer network.","title":"Interacting with Monero"},{"location":"interacting/overview/#installation-directory-overview","text":"Once unpacked you will see several executable files. You will also find a nice PDF guide for the GUI wallet. Monero project nicely decouples network node logic from wallet logic. Wallet logic is offered through three independent user interfaces - the GUI, the CLI, and the HTTP API. # cd monero-gui-v0.17.1.9 # ---- guide to Monero GUI ---- monero-gui-wallet-guide.pdf # ---- main executable files ----------- monerod monero-wallet-gui # ---- extra executable files ----------- extras/monero-wallet-cli extras/monero-wallet-rpc extras/monero-blockchain-prune extras/monero-gen-trusted-multisig extras/monero-gen-ssl-cert extras/monero-blockchain-export extras/monero-blockchain-import # ---- don't bother with these ---------- extras/monero-blockchain-stats extras/monero-blockchain-mark-spent-outputs extras/monero-blockchain-prune-known-spent-data extras/monero-blockchain-usage extras/monero-blockchain-ancestry extras/monero-blockchain-depth","title":"Installation directory overview"},{"location":"interacting/overview/#executables","text":"Executable Description monerod The full node daemon. Does not require a wallet. Documentation . monero-wallet-gui Wallet logic and graphical user interface. Requires monerod running. monero-wallet-cli Wallet logic and commandline user interface. Requires monerod running. monero-wallet-rpc Wallet logic and HTTP API (JSON-RPC protocol). Requires monerod running. monero-blockchain-prune Prune existing local blockchain. This saves 2/3 of disk space (down to 31GB as of Jan 2021). This is preferable over monerod --prune-blockchain which only logically releases space inside the file while the file remains large. The monero-blockchain-prune creates a shrinked copy of the blockchain file. See tutorial1 , tutorial2 . monero-gen-ssl-cert Generate 4096 bit RSA private key and self signed TLS certificate for use with monerod RPC interface. Note, Monero daemon automatically generates TLS certificate on each restart. Manual generation with this tool is only useful if you want to pin TLS certificate fingerprint in your monero wallet. See the pull request . monero-gen-trusted-multisig Tool to generate a set of multisig wallets. See chapter on multisignatures . monero-blockchain-export Tool to export blockchain to blockchain.raw file. monero-blockchain-import Tool to import blockchain.raw - ideally your own trusted copy.","title":"Executables"},{"location":"interacting/overview/#executables-legacy","text":"You most likely should not bother with these legacy or very specialized tools. Executable Description monero-blockchain-stats Generate stats like tx/day, blocks/day, bytes/day based on your local blockchain. monero-blockchain-mark-spent-outputs Advanced tool to mitigate potential privacy issues related to Monero forks. You normally shouldn't be concerned with that. See the commit and pull request . monero-blockchain-prune-known-spent-data Previous limited pruning tool to prune select \"known spent\" transaction outputs (from the before RCT era). Nowadays prefer monero-blockchain-prune . This only saves ~200 MB. See the commit . monero-blockchain-usage Advanced tool to mitigate potential privacy issues related to Monero forks. You normally shouldn't be concerned with that. See the commit and the pull request . monero-blockchain-ancestry Advanced research tool to learn ancestors of a transaction, block or chain. Irrelevant for normal users. See this pull request . monero-blockchain-depth Advanced research tool to learn depth of a transaction, block or chain. Irrelevant for normal users. See this commit .","title":"Executables - legacy"},{"location":"interacting/overview/#interacting","text":"There are quite a few ways you can interact with Monero software. Perhaps the most surprising for newcomers is that monerod daemon accepts interactive keyboard commands while it is running. Also, please note that HTTP API is split across monerod and monero-wallet-rpc . You need to run and call both daemons to explore the full API. This follows the node-logic vs wallet-logic split mentioned earlier. All wallet implementations depend on the monerod running. Executable p2p network node commands via keyboard node HTTP API wallet commands via keyboard wallet HTTP API wallet via GUI monerod \u2714 \u2714 \u2714 monero-wallet-cli \u2714 monero-wallet-rpc \u2714 monero-wallet-gui \u2714","title":"Interacting"},{"location":"interacting/overview/#data-directory","text":"This is where the blockchain, log files, and p2p network memory are stored. By default data directory is at: $HOME/.bitmonero/ on Linux and macOS C:\\ProgramData\\bitmonero\\ on Windows Please mind: data directory is hidden as per OS convention the bitmonero directory name is historical artefact from before Monero forked away from Bitmonero, about 2000 years Before Christ Data directory contains: lmdb/ - the blockchain database directory p2pstate.bin - saved memory of discovered and rated peers bitmonero.log - log file It can also contain subdirectories for stagenet and testnet, mirroring the same structure: stagenet/ - data directory for Stagenet testnet/ - data directory for Testnet","title":"Data directory"},{"location":"interacting/verify-monero-binaries/","text":"Verify Monero Binaries \u00b6 Verification must be carried on before extracting the archive and before using Monero . Instructions were tested on Linux. They should also work on macOS with slight modifications. 1. Import lead maintainer PGP key \u00b6 This is a one time action. Skip this step for subsequent Monero releases. Monero core developers sign a list of hashes of released binaries. BinaryFate is Monero core developer who signs the releases. His public key is available on GitHub in the project source code. Import binaryFate's public key to your keyring: curl https://raw.githubusercontent.com/monero-project/monero/master/utils/gpg_keys/binaryfate.asc | gpg --import Trust binaryFate's public key (fingerprint must be exactly this): gpg --edit-key '81AC591FE9C4B65C5806AFC3F0AF4D462A0BDF92' trust 4 Danger If key with this fingerprint was not found then remove imported key immediately (gpg --delete-keys ...). That would mean the key changed (likely was compromised). 2. Verify signature of hash list (hashes.txt) \u00b6 The list of binaries and their hashes is published on getmonero.org and a few other places like release notes on r/monero . Please note the publication channel does not matter as long as you properly verify the signature! u To verify these are real hashes (not tampered with) run: curl https://www.getmonero.org/downloads/hashes.txt | gpg --verify The expected output should contain the line: gpg: Good signature from \"binaryFate \" 3. Verify the hash \u00b6 By this step we checked that published hashes were not tampered with. The last step is to compare published hash with downloaded archive SHA-256 hash. Download Monero if you didn't already (but do not unpack). Replace the example file name with actual one: file_name=monero-gui-linux-x64-v0.17.1.9.tar.bz2 file_hash=`sha256sum $file_name | cut -c 1-64` curl https://www.getmonero.org/downloads/hashes.txt > /tmp/reference-hashes.txt # verify the signature (previous step is repeated here for completeness) gpg --verify /tmp/reference-hashes.txt # grep must print the hash (output cannot be empty) grep $file_hash /tmp/reference-hashes.txt Danger If the grep output is empty then double check everything because apparently the hashes don't match. If grep printed filename and hash then everything is alright!","title":"Verify"},{"location":"interacting/verify-monero-binaries/#verify-monero-binaries","text":"Verification must be carried on before extracting the archive and before using Monero . Instructions were tested on Linux. They should also work on macOS with slight modifications.","title":"Verify Monero Binaries"},{"location":"interacting/verify-monero-binaries/#1-import-lead-maintainer-pgp-key","text":"This is a one time action. Skip this step for subsequent Monero releases. Monero core developers sign a list of hashes of released binaries. BinaryFate is Monero core developer who signs the releases. His public key is available on GitHub in the project source code. Import binaryFate's public key to your keyring: curl https://raw.githubusercontent.com/monero-project/monero/master/utils/gpg_keys/binaryfate.asc | gpg --import Trust binaryFate's public key (fingerprint must be exactly this): gpg --edit-key '81AC591FE9C4B65C5806AFC3F0AF4D462A0BDF92' trust 4 Danger If key with this fingerprint was not found then remove imported key immediately (gpg --delete-keys ...). That would mean the key changed (likely was compromised).","title":"1. Import lead maintainer PGP key"},{"location":"interacting/verify-monero-binaries/#2-verify-signature-of-hash-list-hashestxt","text":"The list of binaries and their hashes is published on getmonero.org and a few other places like release notes on r/monero . Please note the publication channel does not matter as long as you properly verify the signature! u To verify these are real hashes (not tampered with) run: curl https://www.getmonero.org/downloads/hashes.txt | gpg --verify The expected output should contain the line: gpg: Good signature from \"binaryFate \"","title":"2. Verify signature of hash list (hashes.txt)"},{"location":"interacting/verify-monero-binaries/#3-verify-the-hash","text":"By this step we checked that published hashes were not tampered with. The last step is to compare published hash with downloaded archive SHA-256 hash. Download Monero if you didn't already (but do not unpack). Replace the example file name with actual one: file_name=monero-gui-linux-x64-v0.17.1.9.tar.bz2 file_hash=`sha256sum $file_name | cut -c 1-64` curl https://www.getmonero.org/downloads/hashes.txt > /tmp/reference-hashes.txt # verify the signature (previous step is repeated here for completeness) gpg --verify /tmp/reference-hashes.txt # grep must print the hash (output cannot be empty) grep $file_hash /tmp/reference-hashes.txt Danger If the grep output is empty then double check everything because apparently the hashes don't match. If grep printed filename and hash then everything is alright!","title":"3. Verify the hash"},{"location":"proof-of-work/cryptonight/","text":"CryptoNight \u00b6 CryptoNight is a memory hard hash function Background \u00b6 CryptoNight was originally designed around 2013 as part of the CryptoNote suite. One design goal was to make it very friendly for the off-the-shelf CPU-s, by employing: native AES encryption fast 64 bit multipliers scratchpad fitting exactly the size of the per-core L3 cache on Intel CPUs (about 2MB) More ambitious design goal was to make it inefficiently computable on ASIC-s. This goal has since failed, as it inevitably happens with \"ASIC hard\" algorithms. Efficient CryptoNight ASIC was developed in 2017 by Bitmain. Monero inherited CryptoNight as its proof of work in 2014. Since then Monero slightly evolved the algorithm to intentionally break compatibility with released ASIC-s. Currently Monero implements CryptoNight v2, a third iteration of original CryptoNight (v0, v1, v2). The goal is to find small-enough hash \u00b6 In hashing based PoW algorithms the goal is to find small-enough hash. Hash is simply an integer (normally, a very large integer). Most hashing functions result in 256-bit hashes (integers between 0 and 2^256). This includes Bitcoin's double-SHA-256 and Monero's CryptoNight. Miner randomly tweaks input data until the hash fits under specified threshold. The threshold (also a large integer) is established collectively by the network as part of the consensus mechanism. The PoW is only considered valid (solved) if hash fits under the threshold. Because hash functions are one-way, it is not possible to analytically calculate input data that would result in a small-enough hash. The solution must be brute-forced by tweaking the input data and recalculating the hash over and over again. Miners have a few areas of flexibility regarding input data - most importantly they can iterate with the nonce value. They also have a power over which transactions are included in the block and how they are put together in a merkle tree. Cryptographic primitives \u00b6 CryptoNight is based on: AES encryption 5 hashing functions, all of which were finalists in NIST SHA-3 competition: Keccak (the primary one) BLAKE Groestl JH Skein Input data \u00b6 In Monero the input to hashing function is concatenation of: serialized block header (around 46 bytes; subject to varint representation) merkle tree root (32 bytes) number of transactions included in the block (around 1-2 bytes; subject to varint representation) See get_block_hashing_blob() function to dig further. Algorithm \u00b6 Warning The article attempts to give reader a high-level understanding of the CryptoNight algorithm. For implementation details refer to CryptoNote Standard and Monero source code. See references at the bottom. Overview \u00b6 CryptoNight attempts to make memory access a bottleneck for performance (\"memory hardness\"). It has three steps: Initialize large area of memory with pseudo-random data. This memory is known as the scratchpad. Perform numerous read/write operations at pseudo-random (but deterministic) addresses on the scratchpad. Hash the entire scratchpad to produce the resulting value. Step 1: scratchpad initialization \u00b6 Firstly, the input data is hashed with Keccak-1600. This results in 200 bytes of pseudorandom data (1600 bits == 200 bytes). These 200 bytes become a seed to generate a larger, 2MB-wide buffer of pseudorandom data, by applying AES-256 encryption. The first 0..31 bytes of Keccak-1600 hash are used as AES key. The encryption is performed on 128 bytes-long payloads until 2MB is ready. The first payload are Keccak-1600 bytes 66..191. The next payload is encryption result of the previous payload. Each 128-byte payload is actually encrypted 10 times. The details are a bit more nuanced, see \"Scratchpad Initialization\" in CryptoNote Standard . Step 2: memory-hard loop \u00b6 The second step is basically 524288 iterations of a simple stateful algorithm. Each algorithm iteration reads from and writes back to the scratchpad, at pseudorandom-but-deterministic locations. Critically, next iteration depends on the state prepared by previous iterations. It is not possible to directly calculate state of future iterations. The specific operations include AES, XOR, 8byte_mul, 8byte_add - operations that are CPU-friendly (highly optimized on modern CPU-s). The goal here is to make memory latency the bottleneck in attempt to close the gap between potential ASIC-s and general purpose CPU-s. Step 3: hashing \u00b6 The final step (simplifying) is to: combine original Keccak-1600 output with the whole scratchpad pick the hashing algorithm based on 2 low-order bits of the result 0=BLAKE-256 1=Groestl-256 2=JH-256 3=Skein-256 hash the result with selected function The resulting 256-bit hash is the final output of CryptoNight algorithm. Monero specific modifications \u00b6 CryptoNight v0 \u00b6 This is how Monero community refers to original implementation of CryptoNight. CryptoNight v1 \u00b6 See the source code diff . CryptoNight v2 \u00b6 See the rationale and the source code diff . CryptoNight v3 aka CryptoNightR \u00b6 See the rationale and the source code diff . Critique \u00b6 CryptoNight hash is relatively expensive to verify. This poses a risk of DoS-ing nodes with incorrect proofs to process. See strong asymmetry requirement. The hash function was designed from scratch with limited peer review. While CryptoNight is composed of proven and peer-reviewed primitives, combining secure primitives doesn't necessarily result in a secure cryptosystem. CryptoNight ultimately failed to prevent ASIC-s. Complexity of CryptoNight kills competition in ASIC manufacturing. CryptoNight proof of work remains one of the most controversial aspect of Monero. Reference \u00b6 CryptoNight hash function description in the CryptoNote Standard CryptoNight v2 source code The entry point is cn_slow_hash() function. Manually removing support and optimizations for multiple architectures should help you understand the actual code. \"Egalitarian Proof of Work\" chapter in CryptoNote whitepaper First days of Monero mining by dr David Andersen Some test vectors in Monero source code","title":"CryptoNight"},{"location":"proof-of-work/cryptonight/#cryptonight","text":"CryptoNight is a memory hard hash function","title":"CryptoNight"},{"location":"proof-of-work/cryptonight/#background","text":"CryptoNight was originally designed around 2013 as part of the CryptoNote suite. One design goal was to make it very friendly for the off-the-shelf CPU-s, by employing: native AES encryption fast 64 bit multipliers scratchpad fitting exactly the size of the per-core L3 cache on Intel CPUs (about 2MB) More ambitious design goal was to make it inefficiently computable on ASIC-s. This goal has since failed, as it inevitably happens with \"ASIC hard\" algorithms. Efficient CryptoNight ASIC was developed in 2017 by Bitmain. Monero inherited CryptoNight as its proof of work in 2014. Since then Monero slightly evolved the algorithm to intentionally break compatibility with released ASIC-s. Currently Monero implements CryptoNight v2, a third iteration of original CryptoNight (v0, v1, v2).","title":"Background"},{"location":"proof-of-work/cryptonight/#the-goal-is-to-find-small-enough-hash","text":"In hashing based PoW algorithms the goal is to find small-enough hash. Hash is simply an integer (normally, a very large integer). Most hashing functions result in 256-bit hashes (integers between 0 and 2^256). This includes Bitcoin's double-SHA-256 and Monero's CryptoNight. Miner randomly tweaks input data until the hash fits under specified threshold. The threshold (also a large integer) is established collectively by the network as part of the consensus mechanism. The PoW is only considered valid (solved) if hash fits under the threshold. Because hash functions are one-way, it is not possible to analytically calculate input data that would result in a small-enough hash. The solution must be brute-forced by tweaking the input data and recalculating the hash over and over again. Miners have a few areas of flexibility regarding input data - most importantly they can iterate with the nonce value. They also have a power over which transactions are included in the block and how they are put together in a merkle tree.","title":"The goal is to find small-enough hash"},{"location":"proof-of-work/cryptonight/#cryptographic-primitives","text":"CryptoNight is based on: AES encryption 5 hashing functions, all of which were finalists in NIST SHA-3 competition: Keccak (the primary one) BLAKE Groestl JH Skein","title":"Cryptographic primitives"},{"location":"proof-of-work/cryptonight/#input-data","text":"In Monero the input to hashing function is concatenation of: serialized block header (around 46 bytes; subject to varint representation) merkle tree root (32 bytes) number of transactions included in the block (around 1-2 bytes; subject to varint representation) See get_block_hashing_blob() function to dig further.","title":"Input data"},{"location":"proof-of-work/cryptonight/#algorithm","text":"Warning The article attempts to give reader a high-level understanding of the CryptoNight algorithm. For implementation details refer to CryptoNote Standard and Monero source code. See references at the bottom.","title":"Algorithm"},{"location":"proof-of-work/cryptonight/#overview","text":"CryptoNight attempts to make memory access a bottleneck for performance (\"memory hardness\"). It has three steps: Initialize large area of memory with pseudo-random data. This memory is known as the scratchpad. Perform numerous read/write operations at pseudo-random (but deterministic) addresses on the scratchpad. Hash the entire scratchpad to produce the resulting value.","title":"Overview"},{"location":"proof-of-work/cryptonight/#step-1-scratchpad-initialization","text":"Firstly, the input data is hashed with Keccak-1600. This results in 200 bytes of pseudorandom data (1600 bits == 200 bytes). These 200 bytes become a seed to generate a larger, 2MB-wide buffer of pseudorandom data, by applying AES-256 encryption. The first 0..31 bytes of Keccak-1600 hash are used as AES key. The encryption is performed on 128 bytes-long payloads until 2MB is ready. The first payload are Keccak-1600 bytes 66..191. The next payload is encryption result of the previous payload. Each 128-byte payload is actually encrypted 10 times. The details are a bit more nuanced, see \"Scratchpad Initialization\" in CryptoNote Standard .","title":"Step 1: scratchpad initialization"},{"location":"proof-of-work/cryptonight/#step-2-memory-hard-loop","text":"The second step is basically 524288 iterations of a simple stateful algorithm. Each algorithm iteration reads from and writes back to the scratchpad, at pseudorandom-but-deterministic locations. Critically, next iteration depends on the state prepared by previous iterations. It is not possible to directly calculate state of future iterations. The specific operations include AES, XOR, 8byte_mul, 8byte_add - operations that are CPU-friendly (highly optimized on modern CPU-s). The goal here is to make memory latency the bottleneck in attempt to close the gap between potential ASIC-s and general purpose CPU-s.","title":"Step 2: memory-hard loop"},{"location":"proof-of-work/cryptonight/#step-3-hashing","text":"The final step (simplifying) is to: combine original Keccak-1600 output with the whole scratchpad pick the hashing algorithm based on 2 low-order bits of the result 0=BLAKE-256 1=Groestl-256 2=JH-256 3=Skein-256 hash the result with selected function The resulting 256-bit hash is the final output of CryptoNight algorithm.","title":"Step 3: hashing"},{"location":"proof-of-work/cryptonight/#monero-specific-modifications","text":"","title":"Monero specific modifications"},{"location":"proof-of-work/cryptonight/#cryptonight-v0","text":"This is how Monero community refers to original implementation of CryptoNight.","title":"CryptoNight v0"},{"location":"proof-of-work/cryptonight/#cryptonight-v1","text":"See the source code diff .","title":"CryptoNight v1"},{"location":"proof-of-work/cryptonight/#cryptonight-v2","text":"See the rationale and the source code diff .","title":"CryptoNight v2"},{"location":"proof-of-work/cryptonight/#cryptonight-v3-aka-cryptonightr","text":"See the rationale and the source code diff .","title":"CryptoNight v3 aka CryptoNightR"},{"location":"proof-of-work/cryptonight/#critique","text":"CryptoNight hash is relatively expensive to verify. This poses a risk of DoS-ing nodes with incorrect proofs to process. See strong asymmetry requirement. The hash function was designed from scratch with limited peer review. While CryptoNight is composed of proven and peer-reviewed primitives, combining secure primitives doesn't necessarily result in a secure cryptosystem. CryptoNight ultimately failed to prevent ASIC-s. Complexity of CryptoNight kills competition in ASIC manufacturing. CryptoNight proof of work remains one of the most controversial aspect of Monero.","title":"Critique"},{"location":"proof-of-work/cryptonight/#reference","text":"CryptoNight hash function description in the CryptoNote Standard CryptoNight v2 source code The entry point is cn_slow_hash() function. Manually removing support and optimizations for multiple architectures should help you understand the actual code. \"Egalitarian Proof of Work\" chapter in CryptoNote whitepaper First days of Monero mining by dr David Andersen Some test vectors in Monero source code","title":"Reference"},{"location":"proof-of-work/pow-in-cryptocurrencies/","text":"Proof of Work in Cryptocurrencies \u00b6 Proof of work is a Sybil protection mechanism PoW protects against Sybil attack \u00b6 In decentralized cryptocurrencies untrusted actors confirm (blocks of) transactions. If threshold voting was employed then the scheme would break immediately. This is because nothing prevents a single actor from creating arbitrary number of pseudonyms and take over the voting. In distributed systems this is known as Sybil attack. Instead, cryptocurrencies employ proof of work. In the proof of work scheme, it is not the number of actors that counts. It is the amount of committed computational resources. This, of course, is much harder to game. To endanger the scheme, an attacker would have to actually control majority (>50%) of computational resources. In practice, attacker would need this control over significant period of time. PoW is a leader election mechanism \u00b6 In distributed systems \"leader election\" is a process of establishing which node is responsible for (temporarily) coordinating the system. In cryptocurrencies PoW is used to elect the node that \"wins\" the next block. Using PoW for leader election was one of the key inventions introduced by Bitcoin. Competing nodes (known as \"miners\") work on a solution to artificial problem. Every now and then, someone randomly finds the solution. Chances are linearly proportional to committed computing power. The winner uses its solution to \"underwrite\" the block it assembled. Only blocks with valid solutions are accepted by the network. The winner also gets a reward for its work. The reward is a specific amount of cryptocurrency created \"out of thin air\" and assigned to self. The winner also gets all fees coming from transactions included in the block. The difficulty of the PoW problem is dynamically adjusted by the network, with the goal of finding blocks with a roughly constant rate (typically, every couple of minutes).","title":"PoW in Cryptocurrencies"},{"location":"proof-of-work/pow-in-cryptocurrencies/#proof-of-work-in-cryptocurrencies","text":"Proof of work is a Sybil protection mechanism","title":"Proof of Work in Cryptocurrencies"},{"location":"proof-of-work/pow-in-cryptocurrencies/#pow-protects-against-sybil-attack","text":"In decentralized cryptocurrencies untrusted actors confirm (blocks of) transactions. If threshold voting was employed then the scheme would break immediately. This is because nothing prevents a single actor from creating arbitrary number of pseudonyms and take over the voting. In distributed systems this is known as Sybil attack. Instead, cryptocurrencies employ proof of work. In the proof of work scheme, it is not the number of actors that counts. It is the amount of committed computational resources. This, of course, is much harder to game. To endanger the scheme, an attacker would have to actually control majority (>50%) of computational resources. In practice, attacker would need this control over significant period of time.","title":"PoW protects against Sybil attack"},{"location":"proof-of-work/pow-in-cryptocurrencies/#pow-is-a-leader-election-mechanism","text":"In distributed systems \"leader election\" is a process of establishing which node is responsible for (temporarily) coordinating the system. In cryptocurrencies PoW is used to elect the node that \"wins\" the next block. Using PoW for leader election was one of the key inventions introduced by Bitcoin. Competing nodes (known as \"miners\") work on a solution to artificial problem. Every now and then, someone randomly finds the solution. Chances are linearly proportional to committed computing power. The winner uses its solution to \"underwrite\" the block it assembled. Only blocks with valid solutions are accepted by the network. The winner also gets a reward for its work. The reward is a specific amount of cryptocurrency created \"out of thin air\" and assigned to self. The winner also gets all fees coming from transactions included in the block. The difficulty of the PoW problem is dynamically adjusted by the network, with the goal of finding blocks with a roughly constant rate (typically, every couple of minutes).","title":"PoW is a leader election mechanism"},{"location":"proof-of-work/random-x/","text":"RandomX \u00b6 For general information about RandomX you can read this article .","title":"RandomX"},{"location":"proof-of-work/random-x/#randomx","text":"For general information about RandomX you can read this article .","title":"RandomX"},{"location":"proof-of-work/what-is-pow/","text":"Proof of Work \u00b6 Proof of work is a way to legitimize untrusted party What exactly is proof of work? \u00b6 Proof of work is a cryptographic proof that untrusted party committed significant computational resources to solve artificial problem. Technically, the \"proof\" is simply a solution to the problem at hand. It's all about legitimizing untrusted party \u00b6 How an untrusted party on the Internet could earn any level of your trust? It can prove its commitment by solving agreed computationally hard problem. For example, by requiring untrusted party to perform a hard computation before you accept their connection, you limit connections only to \"committed\" parties. In another example, you could require PoW to be attached to incoming e-mails to make spam prohibitively expensive. Work must be otherwise useless \u00b6 The work on and solution to \"computationally hard problem\" cannot be useful in any other way than to prove the commitment. If the work is useful elsewhere then it doesn't prove commitment to you. The problem must be artificial. Otherwise incentives are skewed and the whole scheme breaks. Strong asymmetry \u00b6 The requirement for proof of work scheme is strong asymmetry for work vs verification resources. The work must be arbitrarily hard. At the same time proof verification must remain dirt cheap (in terms of computational resources). Cheap verification is critical because at this stage we are dealing with potentially huge number of untrusted parties, who could DoS the verifier by submitting invalid proofs. Such proofs should be trivial to discard.","title":"What is PoW?"},{"location":"proof-of-work/what-is-pow/#proof-of-work","text":"Proof of work is a way to legitimize untrusted party","title":"Proof of Work"},{"location":"proof-of-work/what-is-pow/#what-exactly-is-proof-of-work","text":"Proof of work is a cryptographic proof that untrusted party committed significant computational resources to solve artificial problem. Technically, the \"proof\" is simply a solution to the problem at hand.","title":"What exactly is proof of work?"},{"location":"proof-of-work/what-is-pow/#its-all-about-legitimizing-untrusted-party","text":"How an untrusted party on the Internet could earn any level of your trust? It can prove its commitment by solving agreed computationally hard problem. For example, by requiring untrusted party to perform a hard computation before you accept their connection, you limit connections only to \"committed\" parties. In another example, you could require PoW to be attached to incoming e-mails to make spam prohibitively expensive.","title":"It's all about legitimizing untrusted party"},{"location":"proof-of-work/what-is-pow/#work-must-be-otherwise-useless","text":"The work on and solution to \"computationally hard problem\" cannot be useful in any other way than to prove the commitment. If the work is useful elsewhere then it doesn't prove commitment to you. The problem must be artificial. Otherwise incentives are skewed and the whole scheme breaks.","title":"Work must be otherwise useless"},{"location":"proof-of-work/what-is-pow/#strong-asymmetry","text":"The requirement for proof of work scheme is strong asymmetry for work vs verification resources. The work must be arbitrarily hard. At the same time proof verification must remain dirt cheap (in terms of computational resources). Cheap verification is critical because at this stage we are dealing with potentially huge number of untrusted parties, who could DoS the verifier by submitting invalid proofs. Such proofs should be trivial to discard.","title":"Strong asymmetry"},{"location":"public-address/integrated-address/","text":"Integrated Address \u00b6 Integrated addresses are ideal for accepting Monero in an automated fashion - like in online stores and exchanges. Monero integrated address embeds a payment ID. This allows you to learn for what you are being paid. Please note these are Monero technical payment IDs and must not be confused with business identifiers like order number or invoice number. The transaction to integrated address will not reveal the payment ID publicly. Payment ID in a transaction will be encrypted with a shared secret (one-time random key known only to sender and recipient). Only the recipient will be able to match the transaction against payment ID. Monero integrated address obsoletes the former practice of using full 32-bytes payment ID in a transaction extra field (where it was not encrypted). Data structure ( src ): Index Size in bytes Description 0 1 identifies the network and address type; 19 - main chain; 54 - test chain 1 32 public spend key 33 32 public view key 65 8 compact payment ID - 8 bytes randomly generated by the recipient; note that it does not need encryption in the address itself but it is hidden in a transaction paying to integrated address to prevent linking payment with the address by external observers 73 4 checksum ( Keccak-f[1600] hash of the previous 73 bytes, trimmed to first 4 bytes) It totals to 77 bytes. The bytes are then encoded ( src ) in Monero specific Base58 format, resulting in a 106 chars long string. Example integrated address: 4LL9oSLmtpccfufTMvppY6JwXNouMBzSkbLYfpAV5Usx3skxNgYeYTRj5UzqtReoS44qo9mtmXCqY45DJ852K5Jv2bYXZKKQePHES9khPK Integrated addresses vs subaddresses \u00b6 Both types allow you to learn for what you are being paid. Individuals should prefer subaddresses to receive payments. This is to improve privacy in certain scenarios. See article on subaddresses for details. Businesses accepting payments in an automated way should prefer integrated addresses . The rationale is as follows: Scenario where subaddresses improve privacy is not applicable to businesses b/c businesses have the same identity over time. Consequently, subaddresses provide no benefits over integrated addresses. No private key is necessary to generate integrated address. This provides a strong security advantage because services that generate integrated addresses need no access to wallet. In contrast, to generate a subaddress, one needs a private view key. No shared counter is necessary to generate integrated address. This allows individual services to independently generate integrated addresses w/o synchronizing on a common sequence. In contrast, subaddresses are generated sequentially, and so the sequence (the counter or index) is a coupling point between the wallet and all services that need to generate the address. Back to integrated addresses, note that embedded payment IDs are 64-bit. This means the space is large enough that one can simply generate them randomly and reliably assume uniqueness. In very specific scenarios, preparation effort to monitor a very huge number of subaddresses, could became an issue. See this reddit thread for details. Caveats \u00b6 There are some caveats: Single transaction cannot pay to multiple integrated addresses. As individual running a wallet you should generally prefer subaddresses. However, if you happen to use integrated addresses, you should allow Monero software to generate integrated addresses for you (instead of forcing your own payment IDs). Reference \u00b6 question on StackExchange","title":"Integrated"},{"location":"public-address/integrated-address/#integrated-address","text":"Integrated addresses are ideal for accepting Monero in an automated fashion - like in online stores and exchanges. Monero integrated address embeds a payment ID. This allows you to learn for what you are being paid. Please note these are Monero technical payment IDs and must not be confused with business identifiers like order number or invoice number. The transaction to integrated address will not reveal the payment ID publicly. Payment ID in a transaction will be encrypted with a shared secret (one-time random key known only to sender and recipient). Only the recipient will be able to match the transaction against payment ID. Monero integrated address obsoletes the former practice of using full 32-bytes payment ID in a transaction extra field (where it was not encrypted). Data structure ( src ): Index Size in bytes Description 0 1 identifies the network and address type; 19 - main chain; 54 - test chain 1 32 public spend key 33 32 public view key 65 8 compact payment ID - 8 bytes randomly generated by the recipient; note that it does not need encryption in the address itself but it is hidden in a transaction paying to integrated address to prevent linking payment with the address by external observers 73 4 checksum ( Keccak-f[1600] hash of the previous 73 bytes, trimmed to first 4 bytes) It totals to 77 bytes. The bytes are then encoded ( src ) in Monero specific Base58 format, resulting in a 106 chars long string. Example integrated address: 4LL9oSLmtpccfufTMvppY6JwXNouMBzSkbLYfpAV5Usx3skxNgYeYTRj5UzqtReoS44qo9mtmXCqY45DJ852K5Jv2bYXZKKQePHES9khPK","title":"Integrated Address"},{"location":"public-address/integrated-address/#integrated-addresses-vs-subaddresses","text":"Both types allow you to learn for what you are being paid. Individuals should prefer subaddresses to receive payments. This is to improve privacy in certain scenarios. See article on subaddresses for details. Businesses accepting payments in an automated way should prefer integrated addresses . The rationale is as follows: Scenario where subaddresses improve privacy is not applicable to businesses b/c businesses have the same identity over time. Consequently, subaddresses provide no benefits over integrated addresses. No private key is necessary to generate integrated address. This provides a strong security advantage because services that generate integrated addresses need no access to wallet. In contrast, to generate a subaddress, one needs a private view key. No shared counter is necessary to generate integrated address. This allows individual services to independently generate integrated addresses w/o synchronizing on a common sequence. In contrast, subaddresses are generated sequentially, and so the sequence (the counter or index) is a coupling point between the wallet and all services that need to generate the address. Back to integrated addresses, note that embedded payment IDs are 64-bit. This means the space is large enough that one can simply generate them randomly and reliably assume uniqueness. In very specific scenarios, preparation effort to monitor a very huge number of subaddresses, could became an issue. See this reddit thread for details.","title":"Integrated addresses vs subaddresses"},{"location":"public-address/integrated-address/#caveats","text":"There are some caveats: Single transaction cannot pay to multiple integrated addresses. As individual running a wallet you should generally prefer subaddresses. However, if you happen to use integrated addresses, you should allow Monero software to generate integrated addresses for you (instead of forcing your own payment IDs).","title":"Caveats"},{"location":"public-address/integrated-address/#reference","text":"question on StackExchange","title":"Reference"},{"location":"public-address/main-address/","text":"","title":"Main address"},{"location":"public-address/standard-address/","text":"Address \u00b6 Monero public address is what you publish to get paid. An address can be generated offline and for free. It boils down to generating a large random number representing your private spending key. Publishing your Monero address does not endanger your privacy. That's because in Monero transactions go to stealth addresses which are decoupled from your public address. There are a few types of public addresses in Monero: Standard address - basic type of an address, also referred to as raw address Subaddress - what you should be using by default Integrated address - relevant for exchanges, merchants, and other businesses accepting Monero in a fully automated way Standard address \u00b6 Historically, raw address was the only available option. For that reason it is the most widely adopted and supported address type. Its strength is simplicity. However, these days users should prefer receiving to subaddresses instead. Technically, raw address is also a basis for creating subaddresses and integrated addresses. Raw address is still useful for : accepting block reward in a solo-mining scenario as other addresses are not supported accepting from senders who batch payouts (like mining pools); in this scenario the sender is paying multiple parties using a single transaction; such transaction has multiple outputs; subaddresses do not work in this scenario accepting from senders who use legacy wallets (can't send to subaddress) Monero raw address is composed of two public keys: public spend key public view key It also contains a checksum and a \"network byte\" which actually identifies both the network and the address type. Data structure \u00b6 Index Size in bytes Description 0 1 identifies the network and address type; 18 - main chain; 53 - test chain 1 32 public spend key 33 32 public view key 65 4 checksum ( Keccak-f[1600] hash of the previous 65 bytes, trimmed to first 4 bytes) It totals to 69 bytes. The bytes are then encoded ( src ) in Monero specific Base58 format, resulting in a 95 chars long string. Example standard address: 4AdUndXHHZ6cfufTMvppY6JwXNouMBzSkbLYfpAV5Usx3skxNgYeYTRj5UzqtReoS44qo9mtmXCqY45DJ852K5Jv2684Rge See the source code . Generating \u00b6 Standard address is derived from the root private key. TODO. Reference \u00b6 StackExchenge answer https://xmr.llcoins.net/addresstests.html","title":"Standard"},{"location":"public-address/standard-address/#address","text":"Monero public address is what you publish to get paid. An address can be generated offline and for free. It boils down to generating a large random number representing your private spending key. Publishing your Monero address does not endanger your privacy. That's because in Monero transactions go to stealth addresses which are decoupled from your public address. There are a few types of public addresses in Monero: Standard address - basic type of an address, also referred to as raw address Subaddress - what you should be using by default Integrated address - relevant for exchanges, merchants, and other businesses accepting Monero in a fully automated way","title":"Address"},{"location":"public-address/standard-address/#standard-address","text":"Historically, raw address was the only available option. For that reason it is the most widely adopted and supported address type. Its strength is simplicity. However, these days users should prefer receiving to subaddresses instead. Technically, raw address is also a basis for creating subaddresses and integrated addresses. Raw address is still useful for : accepting block reward in a solo-mining scenario as other addresses are not supported accepting from senders who batch payouts (like mining pools); in this scenario the sender is paying multiple parties using a single transaction; such transaction has multiple outputs; subaddresses do not work in this scenario accepting from senders who use legacy wallets (can't send to subaddress) Monero raw address is composed of two public keys: public spend key public view key It also contains a checksum and a \"network byte\" which actually identifies both the network and the address type.","title":"Standard address"},{"location":"public-address/standard-address/#data-structure","text":"Index Size in bytes Description 0 1 identifies the network and address type; 18 - main chain; 53 - test chain 1 32 public spend key 33 32 public view key 65 4 checksum ( Keccak-f[1600] hash of the previous 65 bytes, trimmed to first 4 bytes) It totals to 69 bytes. The bytes are then encoded ( src ) in Monero specific Base58 format, resulting in a 95 chars long string. Example standard address: 4AdUndXHHZ6cfufTMvppY6JwXNouMBzSkbLYfpAV5Usx3skxNgYeYTRj5UzqtReoS44qo9mtmXCqY45DJ852K5Jv2684Rge See the source code .","title":"Data structure"},{"location":"public-address/standard-address/#generating","text":"Standard address is derived from the root private key. TODO.","title":"Generating"},{"location":"public-address/standard-address/#reference","text":"StackExchenge answer https://xmr.llcoins.net/addresstests.html","title":"Reference"},{"location":"public-address/subaddress/","text":"Subaddress \u00b6 Subaddress is what you should be using by default to receive Monero. Learn for what you are being paid \u00b6 By providing a unique subaddress for each anticipated payment you will know for what you are being paid. This use case overlaps with integrated addresses. Subaddresses are generally prefered for reasons outlined below. Prevent payer from linking your payouts together \u00b6 To prevent the payer from linking your payouts together simply generate a new subaddress for each payout. This way specific service (like anonymous exchange) that sends you Monero won't (easilly) know it is you again receving Monero. The exception to this is when a service (or group of colluding services) decides to actively attack you, one address at the time, with the so cold Janus attack , which risks them losing funds. If you need perfect unlinkability of your receivables, the only solution remains to use a separate seed (separate Monero wallet). Also, note it won't help if you have an account with the service. Then your payouts are already linked in the service database, regardless of Monero. Group funds into accounts \u00b6 Accounts are a convenience wallet-level feature to group subaddresses under one label and balance. You may want to organize your funds into accounts like \"cash\", \"work\", \"trading\", \"mining\", \"donations\", etc. As accounts are only groupings of subaddresses, they themselves do not have an address. Accounts are deterministically derived from the root private key along with subaddresses. Accounts are similar to subaccounts in your classic bank account. There is a very important difference though. In Monero funds don't really sit on accounts or public addresses. Public addresses are conceptually a gateway or a routing mechanism. Funds sit on transactions' unspent outputs. Thus, a single transaction can - in principle - aggregate and spend outputs from multiple addresses (and by extension from multiple accounts). The CLI or GUI wallet may not directly support creating such transactions for simplicity. In short, think of accounts as a soft grouping of your funds. Why not multiple wallets? \u00b6 The advantage over creating multiple wallets is that you only have a single seed to manage. All subaddresses can be derived from the wallet seed. Additionally, you conveniently manage your subaddresses within a single user interface. Wallet level feature \u00b6 Subaddresses and accounts are a wallet-level feature to construct and interpret transactions. They do not affect the consensus. Data structure \u00b6 Subaddress has a dedicated \"network byte\": Index Size in bytes Description 0 1 identifies the network and address type; 42 - mainnet; 36 - stagenet; 63 - testnet Otherwise the data structure is the same as for the standard address . Generating \u00b6 Each subaddress conceptually has: account index (also known as \"major\" index) subaddress index within the account (also known as \"minor\" index) The indexes are 0-based. By default wallets use account index 0. The indexes are not directly included in the subaddress data structure. Instead, they are used as input to generating subaddress keys. Private view key \u00b6 A per-subaddress scalar m is derived as follows: m = Hs(\"SubAddr\" || a || account_index || subaddress_index_within_account) Where: Hs is a Keccak-256 hash function interpreted as integer and modulo l (maximum edwards25519 scalar) || is a byte array concatenation operator SubAddr is a 0-terminated fixed string (8 bytes total) a is a private view key of the standard address (a 32 byte little endian unsigned integer) account_index is index of an account (a 32 bit little endian unsigned integer) subaddress_index_within_account is index of the subaddress within the account (a 32 bit little endian unsigned integer) Deriving \"sub view keys\" from the main view key allows for creating a view only wallet that monitors the entire wallet including subaddresses. Public spend key \u00b6 The subaddress public spend key D is derived as follows: D = B + m*G Where: B is standard address public spend key m is a per-subaddress scalar that is derived from the private spend key G is the \"base point\"; this is simply a constant specific to edwards25519 Public view key \u00b6 The subaddress public view key C is derived as follows: C = a*D Where: a is a private view key of the standard address D is a public spend key of the subaddress Special case for (0, 0) \u00b6 The subaddress #0 on the account #0 is the standard address . As standard address has different generation rules, this is simply implemented via an if statement. Building the address string \u00b6 The procedure is the same as for the standard address . Caveats \u00b6 It is not recommended to sweep all the balances of subaddress to standard address in a single transaction. That links the subaddresses together on the blockchain. However, this only concerns privacy against specific sender and the situation will never get worse than not using subaddresses in the first place. If you need to join funds while preserving maximum privacy do it with individual transactions (one per subaddress). Convenience labels are not preserved when recreating from seed. Reference \u00b6 monero-python - the easiest to follow implementation by Micha\u0142 Sa\u0142aban get_subaddress_spend_public_key() - Monero reference implementation historical discussion on Github - gives context but is not up to date with all details StackExchange answer - excellent summary by knaccc","title":"Subaddress"},{"location":"public-address/subaddress/#subaddress","text":"Subaddress is what you should be using by default to receive Monero.","title":"Subaddress"},{"location":"public-address/subaddress/#learn-for-what-you-are-being-paid","text":"By providing a unique subaddress for each anticipated payment you will know for what you are being paid. This use case overlaps with integrated addresses. Subaddresses are generally prefered for reasons outlined below.","title":"Learn for what you are being paid"},{"location":"public-address/subaddress/#prevent-payer-from-linking-your-payouts-together","text":"To prevent the payer from linking your payouts together simply generate a new subaddress for each payout. This way specific service (like anonymous exchange) that sends you Monero won't (easilly) know it is you again receving Monero. The exception to this is when a service (or group of colluding services) decides to actively attack you, one address at the time, with the so cold Janus attack , which risks them losing funds. If you need perfect unlinkability of your receivables, the only solution remains to use a separate seed (separate Monero wallet). Also, note it won't help if you have an account with the service. Then your payouts are already linked in the service database, regardless of Monero.","title":"Prevent payer from linking your payouts together"},{"location":"public-address/subaddress/#group-funds-into-accounts","text":"Accounts are a convenience wallet-level feature to group subaddresses under one label and balance. You may want to organize your funds into accounts like \"cash\", \"work\", \"trading\", \"mining\", \"donations\", etc. As accounts are only groupings of subaddresses, they themselves do not have an address. Accounts are deterministically derived from the root private key along with subaddresses. Accounts are similar to subaccounts in your classic bank account. There is a very important difference though. In Monero funds don't really sit on accounts or public addresses. Public addresses are conceptually a gateway or a routing mechanism. Funds sit on transactions' unspent outputs. Thus, a single transaction can - in principle - aggregate and spend outputs from multiple addresses (and by extension from multiple accounts). The CLI or GUI wallet may not directly support creating such transactions for simplicity. In short, think of accounts as a soft grouping of your funds.","title":"Group funds into accounts"},{"location":"public-address/subaddress/#why-not-multiple-wallets","text":"The advantage over creating multiple wallets is that you only have a single seed to manage. All subaddresses can be derived from the wallet seed. Additionally, you conveniently manage your subaddresses within a single user interface.","title":"Why not multiple wallets?"},{"location":"public-address/subaddress/#wallet-level-feature","text":"Subaddresses and accounts are a wallet-level feature to construct and interpret transactions. They do not affect the consensus.","title":"Wallet level feature"},{"location":"public-address/subaddress/#data-structure","text":"Subaddress has a dedicated \"network byte\": Index Size in bytes Description 0 1 identifies the network and address type; 42 - mainnet; 36 - stagenet; 63 - testnet Otherwise the data structure is the same as for the standard address .","title":"Data structure"},{"location":"public-address/subaddress/#generating","text":"Each subaddress conceptually has: account index (also known as \"major\" index) subaddress index within the account (also known as \"minor\" index) The indexes are 0-based. By default wallets use account index 0. The indexes are not directly included in the subaddress data structure. Instead, they are used as input to generating subaddress keys.","title":"Generating"},{"location":"public-address/subaddress/#private-view-key","text":"A per-subaddress scalar m is derived as follows: m = Hs(\"SubAddr\" || a || account_index || subaddress_index_within_account) Where: Hs is a Keccak-256 hash function interpreted as integer and modulo l (maximum edwards25519 scalar) || is a byte array concatenation operator SubAddr is a 0-terminated fixed string (8 bytes total) a is a private view key of the standard address (a 32 byte little endian unsigned integer) account_index is index of an account (a 32 bit little endian unsigned integer) subaddress_index_within_account is index of the subaddress within the account (a 32 bit little endian unsigned integer) Deriving \"sub view keys\" from the main view key allows for creating a view only wallet that monitors the entire wallet including subaddresses.","title":"Private view key"},{"location":"public-address/subaddress/#public-spend-key","text":"The subaddress public spend key D is derived as follows: D = B + m*G Where: B is standard address public spend key m is a per-subaddress scalar that is derived from the private spend key G is the \"base point\"; this is simply a constant specific to edwards25519","title":"Public spend key"},{"location":"public-address/subaddress/#public-view-key","text":"The subaddress public view key C is derived as follows: C = a*D Where: a is a private view key of the standard address D is a public spend key of the subaddress","title":"Public view key"},{"location":"public-address/subaddress/#special-case-for-0-0","text":"The subaddress #0 on the account #0 is the standard address . As standard address has different generation rules, this is simply implemented via an if statement.","title":"Special case for (0, 0)"},{"location":"public-address/subaddress/#building-the-address-string","text":"The procedure is the same as for the standard address .","title":"Building the address string"},{"location":"public-address/subaddress/#caveats","text":"It is not recommended to sweep all the balances of subaddress to standard address in a single transaction. That links the subaddresses together on the blockchain. However, this only concerns privacy against specific sender and the situation will never get worse than not using subaddresses in the first place. If you need to join funds while preserving maximum privacy do it with individual transactions (one per subaddress). Convenience labels are not preserved when recreating from seed.","title":"Caveats"},{"location":"public-address/subaddress/#reference","text":"monero-python - the easiest to follow implementation by Micha\u0142 Sa\u0142aban get_subaddress_spend_public_key() - Monero reference implementation historical discussion on Github - gives context but is not up to date with all details StackExchange answer - excellent summary by knaccc","title":"Reference"},{"location":"r/accepting-monero-comparison-matrix/","text":"","title":"Accepting monero comparison matrix"},{"location":"running-node/open-node-tor-onion/","text":"Running Monero Open Node + Tor Onion \u00b6 Powerful setup This is great contribution to Monero network and also a pretty sophisticated personal setup. If you are a beginner, you don't need this. The end goal You will publicly offer the following services, where xxx.yyy.zzz.vvv is your server IP address. xxx.yyy.zzz.vvv:18080 - clearnet P2P service (for other nodes) xxx.yyy.zzz.vvv:18081 - clearnet RPC service (for wallets) yourlongv3onionaddress.onion:18083 - onion P2P service (for other onion nodes) yourlongv3onionaddress.onion:18081 - onion RPC service (for wallets connecting over Tor) Why different P2P ports for clearnet and onion? This is a monerod requirement. Broadcasting bad transactions from your IP As with any public data broadcast or relay service, \"bad traffic\" or in this case \"bad transactions\" may appear to originate from your server IP address from an outside observer perspective - even though they really originate from a remote wallet user. This is a potential risk you need to keep in mind. Why run this specific setup? \u00b6 You will be able to connect your desktop and mobile Monero wallets to your own trusted Monero node, in a secure and private way over Tor. Your node will be always ready w/o delays (always synced up, contrary to intermittently running node on a laptop). Serving blocks and transactions in Monero P2P network helps new users to bootstrap and sync up their nodes. It also strenghtens Monero P2P network against DDoS attacks and network partitioning. Open wallet inteface (the \"RPC\") allows anyone to connect their wallets to Monero network through your node. This is useful for beginner users who don't run their own nodes yet. Tor onion for wallet interface is useful for wallet users connecting over Tor because it mitigates Tor exit nodes MiTM risks (which are very real). By connecting wallet to an onion service, no MiTM attack is realistic because within the Tor network connections are end-to-end TLS-ed. Tor onion for P2P network is useful for other full node users as it allows them to broadcast transactions over Tor (using --tx-proxy option). Assumptions \u00b6 You understand basic Linux administration. You seek Monero specific guidance. You have root access to a Linux server with 2GB+ RAM and 120GB+ SSD (or 50GB+ for the pruned node version). This is current for Jan 2021. Some commands assume Ubuntu but you will easily translate them to your distribution. Install Tor \u00b6 Install Tor . Modify /etc/tor/torrc as shown below. Enable tor service with systemctl enable tor and restart it via systemctl restart tor Verify the Tor is up systemctl status tor@default A fresh onion address and corresponding key pair got created for you by the tor daemon in /var/lib/tor/monero/ . You may want to backup these to secure control over your onion address. This happens on restart whenever you add new HiddenServiceDir to torrc config. Monero daemon itself is not necessary at this point. The onion services (AKA hidden services) will just wait until localhost monerod shows up at specified ports 18081 and 18083. /etc/tor/torrc \u00b6 HiddenServiceDir /var/lib/tor/monero HiddenServicePort 18081 127.0.0.1 :18081 # interface for wallet ( \"RPC\" ) HiddenServicePort 18083 127.0.0.1 :18083 # interface for P2P network How Tor onion services work? The tor daemon will simply pass over the traffic from virtual onion port to actual localhost port, where some service is listening (in our case, this will be monerod ). A single onion address can offer multiple services at various virtual ports. We will use this to expose both P2P and RPC monerod services on a single onion. You could host any number of onion addresses at single server or IP address but we won't need that here. Install Monero \u00b6 Create monero user and group useradd --system monero Create monero binaries directory (empty for now) mkdir -p /opt/monero and chown -R monero:monero /opt/monero Create monero data directory mkdir -p /srv/monero and chown -R monero:monero /srv/monero Create monero log directory mkdir -p /var/log/monero and chown -R monero:monero /var/log/monero Feel free to adjust above to your preferred conventions, just remember to adjust the paths accordingly. Download and verify the file. Extract tar -xf monero-linux-x64-v0.17.1.9.tar.bz2 (adjust filename). Move binaries to /opt/monero/ with mv monero-x86_64-linux-gnu-v0.17.1.9/* /opt/monero/ then chown -R monero:monero /opt/monero Create /etc/monero.conf as shown below and paste your values in placeholders . Create /etc/systemd/system/monero.service as shown below. Enable monero service with systemctl enable monero and restart it with systemctl restart monero Verify it is up systemctl status monero Verify it is working as intended tail -n100 /var/log/monero/monero.log /etc/monero.conf \u00b6 This is just an example configuration and it is by no means authoritative. Feel free to modify, see monerod reference . Modify paths if you changed them. Print your onion address with cat /var/lib/tor/monero/hostname and paste it to anonymous-inbound option. # /etc/monero.conf # # Configuration file for monerod. For all available options see the MoneroDocs: # https://monerodocs.org/interacting/monerod-reference/ # Data directory (blockchain db and indices) data-dir=/srv/monero # Optional prunning # prune-blockchain=1 # Pruning saves 2/3 of disk space w/o degrading functionality but contributes less to the network # sync-pruned-blocks=1 # Allow downloading pruned blocks instead of prunning them yourself check-updates=disabled # Do not check DNS TXT records for a new version # Log file log-file=/var/log/monero/monero.log log-level=0 # Minimal logs, WILL NOT log peers or wallets connecting max-log-file-size=2147483648 # Set to 2GB to mitigate log trimming by monerod; configure logrotate instead # P2P full node p2p-bind-ip=0.0.0.0 # Bind to all interfaces (the default) p2p-bind-port=18080 # Bind to default port # RPC open node public-node=1 # Advertise to other users they can use this node as a remote one for connecting their wallets confirm-external-bind=1 # Open Node (confirm) rpc-bind-ip=0.0.0.0 # Bind to all interfaces (the Open Node) rpc-bind-port=18081 # Bind to default port (the Open Node) restricted-rpc=1 # Obligatory for Open Node interface no-igd=1 # Disable UPnP port mapping no-zmq=1 # Disable ZMQ RPC server to decrease attack surface (it's not used) # RPC TLS rpc-ssl=autodetect # Use TLS if client wallet supports it (the default behavior); the certificate will be generated on the fly on every restart # Mempool size max-txpool-weight=268435456 # Maximum unconfirmed transactions pool size in bytes (here 256MB, default ~618MB) # Slow but reliable db writes db-sync-mode=safe out-peers=64 # This will enable much faster sync and tx awareness; the default 8 is suboptimal nowadays in-peers=64 # The default is unlimited; we prefer to put a cap on this limit-rate-up=1048576 # 1048576 kB/s == 1GB/s; a raise from default 2048 kB/s; contribute more to p2p network limit-rate-down=1048576 # 1048576 kB/s == 1GB/s; a raise from default 8192 kB/s; allow for faster initial sync # Tor: broadcast transactions originating from connected wallets over Tor (does not concern relayed transactions) tx-proxy=tor,127.0.0.1:9050,16 # Tor : add P2P seed nodes for the Tor network add-peer=moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18080 add-peer=monerozf6koypqrt.onion:18080 add-peer=zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083 # https://github.com/monero-project/monero/blob/master/src/p2p/net_node.inl add-peer=rno75kjcw3ein6i446sqby2xkyqjarb75oq36ah6c2mribyklzhurpyd.onion:28083 # it's mainnet despite the weird port, according to reddit add-peer=sqzrokz36lgkng2i2nlzgzns2ugcxqosflygsxbkybb4xn6gq3ouugqd.onion:18083 # very flaky, works 1 in 3 times # Tor: tell monerod your onion address so it can be advertised on P2P network anonymous-inbound=PASTE_YOUR_ONION_HOSTNAME:18083,127.0.0.1:18083,64 # Tor: be forgiving to connecting wallets; suggested by http://xmrguide42y34onq.onion/remote_nodes disable-rpc-ban=1 /etc/.../monero.service \u00b6 # /etc/systemd/system/monero.service [Unit] Description = Monero Daemon After = network.target Wants = network.target [Service] ExecStart = /opt/monero/monerod --detach --config-file /etc/monero.conf --pidfile /run/monero/monerod.pid ExecStartPost = /bin/sleep 0.1 Type = forking PIDFile = /run/monero/monerod.pid Restart = always RestartSec = 16 User = monero Group = monero RuntimeDirectory = monero StandardOutput = journal StandardError = journal [Install] WantedBy = multi-user.target Open firewall ports \u00b6 If you use a firewall (and you should), open 18080 and 18081 ports for incoming TCP connections. These are for the incoming clearnet connections, P2P and RPC respectively. You do not need to open any ports for Tor. The onion services work with virtual ports. The tor daemon does not directly accept incoming connections and so it needs no open ports. For example, for popular ufw firewall, that would be: ufw allow 18080 /tcp ufw allow 18081 /tcp To verify, use ufw status . The output should be similar to the following (the 22 being default SSH port, unrelated to Monero): To Action From -- ------ ---- 22/tcp LIMIT Anywhere 18080/tcp ALLOW Anywhere 18081/tcp ALLOW Anywhere 22/tcp (v6) LIMIT Anywhere (v6) 18080/tcp (v6) ALLOW Anywhere (v6) 18081/tcp (v6) ALLOW Anywhere (v6) Testing \u00b6 On server \u00b6 List all services listening on ports and make sure it is what you expect: sudo netstat -lntpu The output should include these (in any order); obviously the PID values will differ. Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name ... tcp 0 0 0.0.0.0:18080 0.0.0.0:* LISTEN 259255/monerod tcp 0 0 0.0.0.0:18081 0.0.0.0:* LISTEN 259255/monerod tcp 0 0 127.0.0.1:18083 0.0.0.0:* LISTEN 259255/monerod tcp 0 0 127.0.0.1:9050 0.0.0.0:* LISTEN 258786/tor On client machine \u00b6 Finally, we want to test connections from your client machine. Install tor and torsocks on your laptop, you will want them anyway for Monero wallet. Just for testing, you will also need nmap and proxychains . Test clearnet P2P connection: nmap -Pn -p 18080 YOUR_IP_ADDRESS_HERE Test clearnet RPC connection: curl --digest -X POST http://YOUR_IP_ADDRESS_HERE:18081/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}' -H 'Content-Type: application/json' Test onion P2P connection (skip if you don't have proxychains): proxychains nmap -Pn -p 18083 YOUR_ONION_ADDRESS_HERE.onion Test onion RPC connection: torsocks curl --digest -X POST http://YOUR_ONION_ADDRESS_HERE.onion:18081/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}' -H 'Content-Type: application/json' Debugging \u00b6 Tor: Status: systemctl status tor@default Logs: journalctl -xe --unit tor@default Monero: Status: systemctl status monero Logs: tail -n100 /var/log/monero/monero.log Logs more info: change log-level=0 to log-level=1 in monero.conf (remember to revert once solved) Further improvements \u00b6 Periodic restarts \u00b6 It's likely worthwhile to add peridic auto-restarting to both tor and monerod every couple hours. Neither daemon is perfect; they can get stuck or leak memory in edge case situations, like the recent attacks on Tor v3 or DDoS attacks on the Monero network. One possible way would be to use systemd timers.","title":"Open Node + Tor Onion"},{"location":"running-node/open-node-tor-onion/#running-monero-open-node-tor-onion","text":"Powerful setup This is great contribution to Monero network and also a pretty sophisticated personal setup. If you are a beginner, you don't need this. The end goal You will publicly offer the following services, where xxx.yyy.zzz.vvv is your server IP address. xxx.yyy.zzz.vvv:18080 - clearnet P2P service (for other nodes) xxx.yyy.zzz.vvv:18081 - clearnet RPC service (for wallets) yourlongv3onionaddress.onion:18083 - onion P2P service (for other onion nodes) yourlongv3onionaddress.onion:18081 - onion RPC service (for wallets connecting over Tor) Why different P2P ports for clearnet and onion? This is a monerod requirement. Broadcasting bad transactions from your IP As with any public data broadcast or relay service, \"bad traffic\" or in this case \"bad transactions\" may appear to originate from your server IP address from an outside observer perspective - even though they really originate from a remote wallet user. This is a potential risk you need to keep in mind.","title":"Running Monero Open Node + Tor Onion"},{"location":"running-node/open-node-tor-onion/#why-run-this-specific-setup","text":"You will be able to connect your desktop and mobile Monero wallets to your own trusted Monero node, in a secure and private way over Tor. Your node will be always ready w/o delays (always synced up, contrary to intermittently running node on a laptop). Serving blocks and transactions in Monero P2P network helps new users to bootstrap and sync up their nodes. It also strenghtens Monero P2P network against DDoS attacks and network partitioning. Open wallet inteface (the \"RPC\") allows anyone to connect their wallets to Monero network through your node. This is useful for beginner users who don't run their own nodes yet. Tor onion for wallet interface is useful for wallet users connecting over Tor because it mitigates Tor exit nodes MiTM risks (which are very real). By connecting wallet to an onion service, no MiTM attack is realistic because within the Tor network connections are end-to-end TLS-ed. Tor onion for P2P network is useful for other full node users as it allows them to broadcast transactions over Tor (using --tx-proxy option).","title":"Why run this specific setup?"},{"location":"running-node/open-node-tor-onion/#assumptions","text":"You understand basic Linux administration. You seek Monero specific guidance. You have root access to a Linux server with 2GB+ RAM and 120GB+ SSD (or 50GB+ for the pruned node version). This is current for Jan 2021. Some commands assume Ubuntu but you will easily translate them to your distribution.","title":"Assumptions"},{"location":"running-node/open-node-tor-onion/#install-tor","text":"Install Tor . Modify /etc/tor/torrc as shown below. Enable tor service with systemctl enable tor and restart it via systemctl restart tor Verify the Tor is up systemctl status tor@default A fresh onion address and corresponding key pair got created for you by the tor daemon in /var/lib/tor/monero/ . You may want to backup these to secure control over your onion address. This happens on restart whenever you add new HiddenServiceDir to torrc config. Monero daemon itself is not necessary at this point. The onion services (AKA hidden services) will just wait until localhost monerod shows up at specified ports 18081 and 18083.","title":"Install Tor"},{"location":"running-node/open-node-tor-onion/#etctortorrc","text":"HiddenServiceDir /var/lib/tor/monero HiddenServicePort 18081 127.0.0.1 :18081 # interface for wallet ( \"RPC\" ) HiddenServicePort 18083 127.0.0.1 :18083 # interface for P2P network How Tor onion services work? The tor daemon will simply pass over the traffic from virtual onion port to actual localhost port, where some service is listening (in our case, this will be monerod ). A single onion address can offer multiple services at various virtual ports. We will use this to expose both P2P and RPC monerod services on a single onion. You could host any number of onion addresses at single server or IP address but we won't need that here.","title":"/etc/tor/torrc"},{"location":"running-node/open-node-tor-onion/#install-monero","text":"Create monero user and group useradd --system monero Create monero binaries directory (empty for now) mkdir -p /opt/monero and chown -R monero:monero /opt/monero Create monero data directory mkdir -p /srv/monero and chown -R monero:monero /srv/monero Create monero log directory mkdir -p /var/log/monero and chown -R monero:monero /var/log/monero Feel free to adjust above to your preferred conventions, just remember to adjust the paths accordingly. Download and verify the file. Extract tar -xf monero-linux-x64-v0.17.1.9.tar.bz2 (adjust filename). Move binaries to /opt/monero/ with mv monero-x86_64-linux-gnu-v0.17.1.9/* /opt/monero/ then chown -R monero:monero /opt/monero Create /etc/monero.conf as shown below and paste your values in placeholders . Create /etc/systemd/system/monero.service as shown below. Enable monero service with systemctl enable monero and restart it with systemctl restart monero Verify it is up systemctl status monero Verify it is working as intended tail -n100 /var/log/monero/monero.log","title":"Install Monero"},{"location":"running-node/open-node-tor-onion/#etcmoneroconf","text":"This is just an example configuration and it is by no means authoritative. Feel free to modify, see monerod reference . Modify paths if you changed them. Print your onion address with cat /var/lib/tor/monero/hostname and paste it to anonymous-inbound option. # /etc/monero.conf # # Configuration file for monerod. For all available options see the MoneroDocs: # https://monerodocs.org/interacting/monerod-reference/ # Data directory (blockchain db and indices) data-dir=/srv/monero # Optional prunning # prune-blockchain=1 # Pruning saves 2/3 of disk space w/o degrading functionality but contributes less to the network # sync-pruned-blocks=1 # Allow downloading pruned blocks instead of prunning them yourself check-updates=disabled # Do not check DNS TXT records for a new version # Log file log-file=/var/log/monero/monero.log log-level=0 # Minimal logs, WILL NOT log peers or wallets connecting max-log-file-size=2147483648 # Set to 2GB to mitigate log trimming by monerod; configure logrotate instead # P2P full node p2p-bind-ip=0.0.0.0 # Bind to all interfaces (the default) p2p-bind-port=18080 # Bind to default port # RPC open node public-node=1 # Advertise to other users they can use this node as a remote one for connecting their wallets confirm-external-bind=1 # Open Node (confirm) rpc-bind-ip=0.0.0.0 # Bind to all interfaces (the Open Node) rpc-bind-port=18081 # Bind to default port (the Open Node) restricted-rpc=1 # Obligatory for Open Node interface no-igd=1 # Disable UPnP port mapping no-zmq=1 # Disable ZMQ RPC server to decrease attack surface (it's not used) # RPC TLS rpc-ssl=autodetect # Use TLS if client wallet supports it (the default behavior); the certificate will be generated on the fly on every restart # Mempool size max-txpool-weight=268435456 # Maximum unconfirmed transactions pool size in bytes (here 256MB, default ~618MB) # Slow but reliable db writes db-sync-mode=safe out-peers=64 # This will enable much faster sync and tx awareness; the default 8 is suboptimal nowadays in-peers=64 # The default is unlimited; we prefer to put a cap on this limit-rate-up=1048576 # 1048576 kB/s == 1GB/s; a raise from default 2048 kB/s; contribute more to p2p network limit-rate-down=1048576 # 1048576 kB/s == 1GB/s; a raise from default 8192 kB/s; allow for faster initial sync # Tor: broadcast transactions originating from connected wallets over Tor (does not concern relayed transactions) tx-proxy=tor,127.0.0.1:9050,16 # Tor : add P2P seed nodes for the Tor network add-peer=moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18080 add-peer=monerozf6koypqrt.onion:18080 add-peer=zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083 # https://github.com/monero-project/monero/blob/master/src/p2p/net_node.inl add-peer=rno75kjcw3ein6i446sqby2xkyqjarb75oq36ah6c2mribyklzhurpyd.onion:28083 # it's mainnet despite the weird port, according to reddit add-peer=sqzrokz36lgkng2i2nlzgzns2ugcxqosflygsxbkybb4xn6gq3ouugqd.onion:18083 # very flaky, works 1 in 3 times # Tor: tell monerod your onion address so it can be advertised on P2P network anonymous-inbound=PASTE_YOUR_ONION_HOSTNAME:18083,127.0.0.1:18083,64 # Tor: be forgiving to connecting wallets; suggested by http://xmrguide42y34onq.onion/remote_nodes disable-rpc-ban=1","title":"/etc/monero.conf"},{"location":"running-node/open-node-tor-onion/#etcmoneroservice","text":"# /etc/systemd/system/monero.service [Unit] Description = Monero Daemon After = network.target Wants = network.target [Service] ExecStart = /opt/monero/monerod --detach --config-file /etc/monero.conf --pidfile /run/monero/monerod.pid ExecStartPost = /bin/sleep 0.1 Type = forking PIDFile = /run/monero/monerod.pid Restart = always RestartSec = 16 User = monero Group = monero RuntimeDirectory = monero StandardOutput = journal StandardError = journal [Install] WantedBy = multi-user.target","title":"/etc/.../monero.service"},{"location":"running-node/open-node-tor-onion/#open-firewall-ports","text":"If you use a firewall (and you should), open 18080 and 18081 ports for incoming TCP connections. These are for the incoming clearnet connections, P2P and RPC respectively. You do not need to open any ports for Tor. The onion services work with virtual ports. The tor daemon does not directly accept incoming connections and so it needs no open ports. For example, for popular ufw firewall, that would be: ufw allow 18080 /tcp ufw allow 18081 /tcp To verify, use ufw status . The output should be similar to the following (the 22 being default SSH port, unrelated to Monero): To Action From -- ------ ---- 22/tcp LIMIT Anywhere 18080/tcp ALLOW Anywhere 18081/tcp ALLOW Anywhere 22/tcp (v6) LIMIT Anywhere (v6) 18080/tcp (v6) ALLOW Anywhere (v6) 18081/tcp (v6) ALLOW Anywhere (v6)","title":"Open firewall ports"},{"location":"running-node/open-node-tor-onion/#testing","text":"","title":"Testing"},{"location":"running-node/open-node-tor-onion/#on-server","text":"List all services listening on ports and make sure it is what you expect: sudo netstat -lntpu The output should include these (in any order); obviously the PID values will differ. Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name ... tcp 0 0 0.0.0.0:18080 0.0.0.0:* LISTEN 259255/monerod tcp 0 0 0.0.0.0:18081 0.0.0.0:* LISTEN 259255/monerod tcp 0 0 127.0.0.1:18083 0.0.0.0:* LISTEN 259255/monerod tcp 0 0 127.0.0.1:9050 0.0.0.0:* LISTEN 258786/tor","title":"On server"},{"location":"running-node/open-node-tor-onion/#on-client-machine","text":"Finally, we want to test connections from your client machine. Install tor and torsocks on your laptop, you will want them anyway for Monero wallet. Just for testing, you will also need nmap and proxychains . Test clearnet P2P connection: nmap -Pn -p 18080 YOUR_IP_ADDRESS_HERE Test clearnet RPC connection: curl --digest -X POST http://YOUR_IP_ADDRESS_HERE:18081/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}' -H 'Content-Type: application/json' Test onion P2P connection (skip if you don't have proxychains): proxychains nmap -Pn -p 18083 YOUR_ONION_ADDRESS_HERE.onion Test onion RPC connection: torsocks curl --digest -X POST http://YOUR_ONION_ADDRESS_HERE.onion:18081/json_rpc -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}' -H 'Content-Type: application/json'","title":"On client machine"},{"location":"running-node/open-node-tor-onion/#debugging","text":"Tor: Status: systemctl status tor@default Logs: journalctl -xe --unit tor@default Monero: Status: systemctl status monero Logs: tail -n100 /var/log/monero/monero.log Logs more info: change log-level=0 to log-level=1 in monero.conf (remember to revert once solved)","title":"Debugging"},{"location":"running-node/open-node-tor-onion/#further-improvements","text":"","title":"Further improvements"},{"location":"running-node/open-node-tor-onion/#periodic-restarts","text":"It's likely worthwhile to add peridic auto-restarting to both tor and monerod every couple hours. Neither daemon is perfect; they can get stuck or leak memory in edge case situations, like the recent attacks on Tor v3 or DDoS attacks on the Monero network. One possible way would be to use systemd timers.","title":"Periodic restarts"},{"location":"todo/bulletproofs/","text":"Pieter Wuille on Bulletproofs: Bulletproofs is a general technology to implement zero-knowledge proofs. Bitcoin does not use zero-knowledge proofs. There is no way you can just \"plug in\" Bulletproofs anywhere in Bitcoin. Perhaps you are talking about confidential transactions (CT). This is a technique to permit a public ledger that makes the amounts hidden while still permitting everyone to verify the balances adds up. If that sounds like magic, that's because it is. CT rely on zero-knowledge proofs. They could use Bulletproofs. They could also use other types of zero-knowledge proofs (there are several, zk-SNARKS is the well known, each with their own trade-offs). Certainly the invention of Bulletproofs made CT more accessible. However... CT is still very different from how Bitcoin works right now. There is no obvious way to integrate them. My best hope would be using something like an extension block, where you can have coins on the \"legacy\" side or coins on the confidential side - with explicit operations to move them between the two. However, that is far from simple, and AFAIK nobody is really working on it. Much as I love this technique and would be very excited to see it in Bitcoin, it's unrealistic to think that it will be usable anytime soon there. Every system must lack at least one of unconditional soundness and unconditional blindness. It's perfectly possible to build a system that lacks both. Bulletproofs are a general zero-knowledge proof technique. That means that they can be used to prove any statement over secret data without revealing that data. You could prove you know 2 numbers that add up to 7. You could prove that you know a string whose SHA256 hash is 16c28109a2719ebd4a123db11ff966f02d814354e3dc932449484f1c5a804af4, without revealing anything else about that string. They could be used instead of zk-SNARKs in Zero-Knowledge Contingent Payments (swapping money for solutions to a problem). These can be done without any changes to Bitcoin. You could (in theory, read on) use them to build a blockchain similar to ZCash (which heavily relies on zk-SNARKs for proving that their ledger makes sense), but without the trusted setup procedure or novel cryptography (Bulletproofs use very conservative security assumptions). Unfortunately, Bulletproof validation is much slower than zk-SNARK validation for complex problems, so it's not really comparable. I expect that the most interesting applications are things we haven't considered yet. They suddenly bring zero-knowledge proofs into scope for a lot of problems and protocols where it wasn't really reasonable to go through the effort of using one of the existing proof systems. ++++ I'm pretty sure that Monero is not unconditionally sound. Even if it is, after switching to Bulletproofs they won't be (Bulletproofs cannot be made unconditionally sound). Yes, with the old rangeproof construction there was an alternative that was unconditionally sound, but not unconditionally private. This is not possible with Bulletproofs (and theoretically impossible with anything with similar compactness; unconditionally sound proofs cannot be small). ++++ Bulletproofs are a general zero-knowledge proof technique. That means that they can be used to prove any statement over secret data without revealing that data. You could prove you know 2 numbers that add up to 7. You could prove that you know a string whose SHA256 hash is 16c28109a2719ebd4a123db11ff966f02d814354e3dc932449484f1c5a804af4, without revealing anything else about that string. They could be used instead of zk-SNARKs in Zero-Knowledge Contingent Payments (swapping money for solutions to a problem). These can be done without any changes to Bitcoin. You could (in theory, read on) use them to build a blockchain similar to ZCash (which heavily relies on zk-SNARKs for proving that their ledger makes sense), but without the trusted setup procedure or novel cryptography (Bulletproofs use very conservative security assumptions). Unfortunately, Bulletproof validation is much slower than zk-SNARK validation for complex problems, so it's not really comparable. I expect that the most interesting applications are things we haven't considered yet. They suddenly bring zero-knowledge proofs into scope for a lot of problems and protocols where it wasn't really reasonable to go through the effort of using one of the existing proof systems. ++++ Practical zero-knowledge proofs have existed for a few years now, and ZKCPs are indeed an application of them. Bulletproofs are just a new type of zero-knowledge proof. Compared to zk-SNARKS, they're much more conservative in their security assumptions, and don't need a complicated setup procedure before proofs can be created. On the other hand, they're also larger and slower for complicated problsms. And they don't do anything that couldn't be done before - they're just more practical depending on your requirements.","title":"Bulletproofs"},{"location":"todo/confidential-transactions/","text":"Pieter Wuille on CT: In a system that uses CT, if someone finds a break in the fundamental security of elliptic curve cryptography (ECC), he can print money. Worse, because the amounts are all private, he can do so undetectably. That's an existential threat for a currency which has controlled inflation as prime goal. Such a break would be dangerous for Bitcoin (even without CT) regardless, as it relies on ECC for protecting against theft. However, Bitcoin can migrate to use a different signature scheme if necessary. It would be chaotic, but not necessarily pose an existential risk. There are people who agree with this perspective. It's a mathematical fact that any privacy system that hides amounts and is built on top of ECC will at least have one of the properties below: An ECC break will permit printing money undetectaby. An ECC break will permit deanonymizing amounts in the historical chain. In other words: An ECC break means the currency can undetectably be inflated (going forward). An ECC break means the ledger's history can retroactively be deanonymized (goin backward). So we are faced with a choice between those two regardless if we want better privacy. Some people believe the second is worse than the first, and choosing the first actually allows for more efficient technology. This is a choice that Zcash, Monero, Grin, all make. CT with Bulletproofs would do the same. However, regardless of your own opinion in this matter, Bitcoin's evolution is a large collaborative process, where such fundamental changes need buy-in from large parts of the ecosystem. My fear is that the question of giving up the ability to exactly audit the monetary supply is going to make it hard to make CT acceptable. Furthermore, there are other challenges. CT makes transactions larger, slower to verify, and poses a very significant engineering challenge to incorporate into Bitcoin without breaking backward compatibility. ++++ Also, is there any possible system that can have unconditional soundness and privacy at the same time (something other than ECC obviously)? No, that's mathematically impossible.","title":"Confidential transactions"},{"location":"todo/p2p/","text":"","title":"P2p"},{"location":"todo/pedersen-commitment/","text":"Pedersen Commitment \u00b6 https://www.reddit.com/r/Monero/comments/9ed7vb/pedersen_commitment/ https://monero.stackexchange.com/questions/10177/who-generates-parameters-g-h-for-pedersen-commitment-in-monero","title":"Pedersen Commitment"},{"location":"todo/pedersen-commitment/#pedersen-commitment","text":"https://www.reddit.com/r/Monero/comments/9ed7vb/pedersen_commitment/ https://monero.stackexchange.com/questions/10177/who-generates-parameters-g-h-for-pedersen-commitment-in-monero","title":"Pedersen Commitment"},{"location":"todo/risks-of-using-remote-node/","text":"Risks of using remote node \u00b6 https://monero.stackexchange.com/questions/38/what-privacy-or-security-trade-offs-are-associated-with-not-running-your-own-ful/ https://monero.stackexchange.com/questions/1482/how-much-information-is-passed-from-the-daemon-to-simplewallet-when-scanning-for?rq=1%20 https://monero.stackexchange.com/questions/1134/is-it-safe-to-share-a-daemon-with-a-roommate?noredirect=1&lq=1 Reference \u00b6 Reddit answer SE 1 SE 2","title":"Risks of using remote node"},{"location":"todo/risks-of-using-remote-node/#risks-of-using-remote-node","text":"https://monero.stackexchange.com/questions/38/what-privacy-or-security-trade-offs-are-associated-with-not-running-your-own-ful/ https://monero.stackexchange.com/questions/1482/how-much-information-is-passed-from-the-daemon-to-simplewallet-when-scanning-for?rq=1%20 https://monero.stackexchange.com/questions/1134/is-it-safe-to-share-a-daemon-with-a-roommate?noredirect=1&lq=1","title":"Risks of using remote node"},{"location":"todo/risks-of-using-remote-node/#reference","text":"Reddit answer SE 1 SE 2","title":"Reference"},{"location":"todo/stealth-address/","text":"Stealth Address \u00b6 Hides recipient \u00b6 Stealth address is a privacy technique to hide the recipient. Even though blockchain is public, observer has no way to link the payment to the recipient. Payments simply do not go to recipient address. Instead payments go to one-time \"stealth\" addresses. One-time, per payment \u00b6 Stealth address is generated for each individual payment and must not be reused. In Bitcoin, should stealth address be reused, the payments are linked. Observer would learn these payments were to the same person. This wouldn't be end of the world though, as most users would link the outputs anyway when spending from the wallet. In Monero, stealth address reuse leads to lose of funds. If sender re-uses stealth address, then recipient will only be able to claim one of the payments. See key image to learn why this is the case. Practically, to re-use stealth address, sender would have to manually craft a malicious transaction. Recipient would simply not acknowledge receiving the payment, as if sender never paid. Wallet level feature \u00b6 Stealth addresses are not part of the consensus layer. For transaction to be valid, it does not matter how the key pairs were generated. Stealth address is non-interactive protocol between sender and recipient. Elliptic curves magic properties \u00b6 Before going further understand the following properties of elliptic curves. Once you internalize these critical properties, you will be able to easily come up with a stealth address scheme yourself. It is possible to establish a shared secret without sharing a secret \u00b6 Two parties can come up with the same secret number w/o sending anything except their public keys. Specifically, having 2 unrelated key pairs, you can exchange public keys, and then each party can independently calculate the same secret number, simply by multiplying own private key with other party's public key: s = aB = bA , where: s - the secret (256-bit number) a - Alice private key A - Alice public key b - Bob private key B - Bob public key A new key pair can be derived by multiplying both keys \u00b6 Having a key pair, you can derive a new key pair, simply by multiplying both keys by an integer. Surprisingly, the new key pair will be valid, i.e. the private key will match the public key. Stealth address protocol \u00b6 Sender Alice generates a new key pair. Note this is entirely local to the sender. a - private key A - public key Sender Alice gets receiver's (Bob) public key from his address, B . Sender calculates the secret: s = rB Reference \u00b6 http://www.scitepress.org/DigitalLibrary/Link.aspx?doi=10.5220/0006270005590566","title":"Stealth Address"},{"location":"todo/stealth-address/#stealth-address","text":"","title":"Stealth Address"},{"location":"todo/stealth-address/#hides-recipient","text":"Stealth address is a privacy technique to hide the recipient. Even though blockchain is public, observer has no way to link the payment to the recipient. Payments simply do not go to recipient address. Instead payments go to one-time \"stealth\" addresses.","title":"Hides recipient"},{"location":"todo/stealth-address/#one-time-per-payment","text":"Stealth address is generated for each individual payment and must not be reused. In Bitcoin, should stealth address be reused, the payments are linked. Observer would learn these payments were to the same person. This wouldn't be end of the world though, as most users would link the outputs anyway when spending from the wallet. In Monero, stealth address reuse leads to lose of funds. If sender re-uses stealth address, then recipient will only be able to claim one of the payments. See key image to learn why this is the case. Practically, to re-use stealth address, sender would have to manually craft a malicious transaction. Recipient would simply not acknowledge receiving the payment, as if sender never paid.","title":"One-time, per payment"},{"location":"todo/stealth-address/#wallet-level-feature","text":"Stealth addresses are not part of the consensus layer. For transaction to be valid, it does not matter how the key pairs were generated. Stealth address is non-interactive protocol between sender and recipient.","title":"Wallet level feature"},{"location":"todo/stealth-address/#elliptic-curves-magic-properties","text":"Before going further understand the following properties of elliptic curves. Once you internalize these critical properties, you will be able to easily come up with a stealth address scheme yourself.","title":"Elliptic curves magic properties"},{"location":"todo/stealth-address/#it-is-possible-to-establish-a-shared-secret-without-sharing-a-secret","text":"Two parties can come up with the same secret number w/o sending anything except their public keys. Specifically, having 2 unrelated key pairs, you can exchange public keys, and then each party can independently calculate the same secret number, simply by multiplying own private key with other party's public key: s = aB = bA , where: s - the secret (256-bit number) a - Alice private key A - Alice public key b - Bob private key B - Bob public key","title":"It is possible to establish a shared secret without sharing a secret"},{"location":"todo/stealth-address/#a-new-key-pair-can-be-derived-by-multiplying-both-keys","text":"Having a key pair, you can derive a new key pair, simply by multiplying both keys by an integer. Surprisingly, the new key pair will be valid, i.e. the private key will match the public key.","title":"A new key pair can be derived by multiplying both keys"},{"location":"todo/stealth-address/#stealth-address-protocol","text":"Sender Alice generates a new key pair. Note this is entirely local to the sender. a - private key A - public key Sender Alice gets receiver's (Bob) public key from his address, B . Sender calculates the secret: s = rB","title":"Stealth address protocol"},{"location":"todo/stealth-address/#reference","text":"http://www.scitepress.org/DigitalLibrary/Link.aspx?doi=10.5220/0006270005590566","title":"Reference"},{"location":"todo/tx/","text":"Monero transaction \u00b6 https://monero.stackexchange.com/questions/2136/understanding-the-structure-of-a-monero-transaction?noredirect=1&lq=1 https://monero.stackexchange.com/questions/6736/how-does-input-reference-the-output-of-some-transaction?noredirect=1&lq=1","title":"Transaction"},{"location":"todo/tx/#monero-transaction","text":"https://monero.stackexchange.com/questions/2136/understanding-the-structure-of-a-monero-transaction?noredirect=1&lq=1 https://monero.stackexchange.com/questions/6736/how-does-input-reference-the-output-of-some-transaction?noredirect=1&lq=1","title":"Monero transaction"}]} \ No newline at end of file diff --git a/public/sitemap.xml b/public/sitemap.xml new file mode 100644 index 0000000..0703662 --- /dev/null +++ b/public/sitemap.xml @@ -0,0 +1,139 @@ + + + https://monerodocs.org/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/download-monero-binaries/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/verify-monero-binaries/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/overview/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/monero-config-file/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/monerod-reference/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/monero-wallet-cli-reference/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/monero-wallet-gui-reference/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/monero-wallet-rpc-reference/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/monero-blockchain-export-reference/ + 2021-01-21 + daily + + https://monerodocs.org/interacting/monero-blockchain-import-reference/ + 2021-01-21 + daily + + https://monerodocs.org/technical-specs/ + 2021-01-21 + daily + + https://monerodocs.org/cryptography/introduction/ + 2021-01-21 + daily + + https://monerodocs.org/cryptography/asymmetric/introduction/ + 2021-01-21 + daily + + https://monerodocs.org/cryptography/asymmetric/private-key/ + 2021-01-21 + daily + + https://monerodocs.org/cryptography/asymmetric/public-key/ + 2021-01-21 + daily + + https://monerodocs.org/cryptography/asymmetric/edwards25519/ + 2021-01-21 + daily + + https://monerodocs.org/cryptography/asymmetric/key-image/ + 2021-01-21 + daily + + https://monerodocs.org/cryptography/base58/ + 2021-01-21 + daily + + https://monerodocs.org/cryptography/prng/ + 2021-01-21 + daily + + https://monerodocs.org/cryptography/keccak-256/ + 2021-01-21 + daily + + https://monerodocs.org/public-address/standard-address/ + 2021-01-21 + daily + + https://monerodocs.org/public-address/subaddress/ + 2021-01-21 + daily + + https://monerodocs.org/public-address/integrated-address/ + 2021-01-21 + daily + + https://monerodocs.org/proof-of-work/what-is-pow/ + 2021-01-21 + daily + + https://monerodocs.org/proof-of-work/pow-in-cryptocurrencies/ + 2021-01-21 + daily + + https://monerodocs.org/proof-of-work/cryptonight/ + 2021-01-21 + daily + + https://monerodocs.org/proof-of-work/random-x/ + 2021-01-21 + daily + + https://monerodocs.org/multisignature/ + 2021-01-21 + daily + + https://monerodocs.org/infrastructure/networks/ + 2021-01-21 + daily + + https://monerodocs.org/infrastructure/tor-onion-p2p-seed-nodes/ + 2021-01-21 + daily + + https://monerodocs.org/infrastructure/monero-pulse/ + 2021-01-21 + daily + + https://monerodocs.org/running-node/open-node-tor-onion/ + 2021-01-21 + daily + + https://monerodocs.org/accepting-monero/overview/ + 2021-01-21 + daily + + \ No newline at end of file diff --git a/public/sitemap.xml.gz b/public/sitemap.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..088f92a7c362cb7f43832d3984726083e742dc5d GIT binary patch literal 559 zcmV+~0?_>*iwFpElnG!0|8r?{Wo=<_E_iKh0M(e$uA49nhVT0n756DEQm1n!%DLMU zY!8qo2BL;Ib3!R^Khv_K?QSKM>h4xZSdPGP;wYf#bLKEwh#3u1|YO(9)0U_Y5eV{Qy$PZ)xJ8Y{Xta+ZeDGxi|KXfpe6X(Snd2=mw#C9 zK6SZ_{Ex%Ckb$(x{N1I+DR|UYJ$%&J1x*f;Bu1Vx*Upj&krA&BCP_@ITn0nyI@LN4 z^60E0Xn{Bi1;VLGdkxf)CC2%h?HN2)(x^~GnhU&qrFNI z%+t4PLvzg7k&gYmD9KGDONl`gm`?LBKqhBif-#c2>I~`vvslFO?46NJ2zJtBQ*}HZ z-la0Ke7wQv4nzT-b%NuYD5OZC69seuWAsH;$1l&uS|d?gOOUv5$~stH_@4%0c;i_n z*pdbC+-8uY93i%f&k5;LPQA{`B^7a!1;#*%^Q1>~n30w&NkAR>H{^pZxUSE#z=)$2 z2X%Wk)iC<(lIw!bBMC^!TjBwT)3k*qKwiX3!mu)u;x&aq#VV=r`TdaKBTZN + + + + + + + + + + + + + + + + + + + + + Monero Technical Specification - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + + + + +
    +
    + + + + + + + +

    Monero Technical Specs

    +

    Live

    +
      +
    • Monero blockchain is live since 18 April 2014
    • +
    +

    No premine, no instamine, no ICO, no token

    +
      +
    • Monero had no premine or instamine
    • +
    • Monero did not sell any token
    • +
    • Monero had no presale of any kind
    • +
    +

    Proof of Work

    +
      +
    • CryptoNight
        +
      • v0 since block height 0
      • +
      • v1 since block height 1546000 (forked on 2018-04-06)
      • +
      • v2 since block height 1685555 (forked on 2018-10-18)
      • +
      • v3 since block height 1788000 (forked on 2019-03-09); "CryptonightR"
      • +
      +
    • +
    • RandomX
        +
      • v0 since block height 1978433 (forked on 2019-11-30)
      • +
      +
    • +
    +

    Difficulty retarget

    +
      +
    • every block
    • +
    • based on the last 720 blocks (24h), excluding 20% of the timestamp outliers
    • +
    +

    Block time

    +
      +
    • 2 minutes
    • +
    • may change in the future as long as emission curve is preserved
    • +
    +

    Block reward

    +
      +
    • smoothly decreasing and subject to penalties for blocks greater then median size of the last 100 blocks (M100)
    • +
    • ~1.6 XMR as of June 2020; for the current reward check the coinbase transaction of the latest block
    • +
    +

    Block size

    +
      +
    • dynamic
    • +
    • maximum of two times the median size of the last 100 blocks (2 * M100)
    • +
    • ~50KB as of June 2020; check the latest block size
    • +
    +

    Emission curve

    +

    Main emission

    +
      +
    • first, the main emission is about to produce ~18.132 million coins by the end of May 2022
    • +
    • as of June 2020 the emission is about 8 XMR per 10 minutes
    • +
    • see charts and details
    • +
    +

    Tail emission

    +
      +
    • the tail emission kicks in once main emission is done
    • +
    • it will produce 0.6 XMR per 2-minute block
    • +
    • this translates to <1% inflation decreasing over time
    • +
    +

    Max supply

    +
      +
    • ~18.132 million XMR + 0.6 XMR per 2 minutes
    • +
    • technically infinite but practically deflationary if accounted for lost coins
    • +
    +

    Divisibility

    +
      +
    • Monero is divisible up to 12 digits
    • +
    • The smallest unit is called piconero and equals 1e-12 XMR, or 0.000000000001 XMR
    • +
    +

    Sender privacy

    +
      +
    • ring signatures
        +
      • the ring size is 11 (10 decoys)
      • +
      +
    • +
    • assurance: probabilistic / plausible deniability
    • +
    +

    Recipient privacy

    +
      +
    • stealth addresses
    • +
    • assurance: strong
    • +
    +

    Amount privacy

    +
      +
    • ring confidential transactions
    • +
    • assurance: strong
    • +
    +

    IP address privacy

    +

    For the full node (monerod):

    +
      +
    • dandelion++
    • +
    • assurance: won't protect against ISP/VPN provider, won't protect against the very first remote node in Dandellion++ protocol
    • +
    • for the full protection user must manually wrap monerod with Tor
    • +
    +

    For the wallet (monero-wallet-gui or monero-wallet-cli):

    +
      +
    • typically wallet runs on the same machine as full node so there is no risk
    • +
    • if wallet connects to remote full node, there is no IP protection by default
        +
      • user must manually wrap wallet with Tor
      • +
      +
    • +
    + + + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/todo/bulletproofs/index.html b/public/todo/bulletproofs/index.html new file mode 100644 index 0000000..152516c --- /dev/null +++ b/public/todo/bulletproofs/index.html @@ -0,0 +1,961 @@ + + + + + + + + + + + + + + + + + + + + + + + Bulletproofs - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    + + + + + + + +

    Bulletproofs

    + +

    Pieter Wuille on Bulletproofs:

    +

    Bulletproofs is a general technology to implement zero-knowledge proofs.

    +

    Bitcoin does not use zero-knowledge proofs. There is no way you can just "plug in" Bulletproofs anywhere in Bitcoin.

    +

    Perhaps you are talking about confidential transactions (CT). This is a technique to permit a public ledger that makes the amounts hidden while still permitting everyone to verify the balances adds up. If that sounds like magic, that's because it is.

    +

    CT rely on zero-knowledge proofs. They could use Bulletproofs. They could also use other types of zero-knowledge proofs (there are several, zk-SNARKS is the well known, each with their own trade-offs). Certainly the invention of Bulletproofs made CT more accessible.

    +

    However... CT is still very different from how Bitcoin works right now. There is no obvious way to integrate them. My best hope would be using something like an extension block, where you can have coins on the "legacy" side or coins on the confidential side - with explicit operations to move them between the two.

    +

    However, that is far from simple, and AFAIK nobody is really working on it. Much as I love this technique and would be very excited to see it in Bitcoin, it's unrealistic to think that it will be usable anytime soon there.

    +

    Every system must lack at least one of unconditional soundness and unconditional blindness. It's perfectly possible to build a system that lacks both.

    +

    Bulletproofs are a general zero-knowledge proof technique. That means that they can be used to prove any statement over secret data without revealing that data.

    +

    You could prove you know 2 numbers that add up to 7.

    +

    You could prove that you know a string whose SHA256 hash is 16c28109a2719ebd4a123db11ff966f02d814354e3dc932449484f1c5a804af4, without revealing anything else about that string.

    +

    They could be used instead of zk-SNARKs in Zero-Knowledge Contingent Payments (swapping money for solutions to a problem). These can be done without any changes to Bitcoin.

    +

    You could (in theory, read on) use them to build a blockchain similar to ZCash (which heavily relies on zk-SNARKs for proving that their ledger makes sense), but without the trusted setup procedure or novel cryptography (Bulletproofs use very conservative security assumptions). Unfortunately, Bulletproof validation is much slower than zk-SNARK validation for complex problems, so it's not really comparable.

    +

    I expect that the most interesting applications are things we haven't considered yet. They suddenly bring zero-knowledge proofs into scope for a lot of problems and protocols where it wasn't really reasonable to go through the effort of using one of the existing proof systems.

    +

    ++++

    +

    I'm pretty sure that Monero is not unconditionally sound. Even if it is, after switching to Bulletproofs they won't be (Bulletproofs cannot be made unconditionally sound).

    +

    Yes, with the old rangeproof construction there was an alternative that was unconditionally sound, but not unconditionally private.

    +

    This is not possible with Bulletproofs (and theoretically impossible with anything with similar compactness; unconditionally sound proofs cannot be small).

    +

    ++++

    +

    Bulletproofs are a general zero-knowledge proof technique. That means that they can be used to prove any statement over secret data without revealing that data.

    +

    You could prove you know 2 numbers that add up to 7.

    +

    You could prove that you know a string whose SHA256 hash is 16c28109a2719ebd4a123db11ff966f02d814354e3dc932449484f1c5a804af4, without revealing anything else about that string.

    +

    They could be used instead of zk-SNARKs in Zero-Knowledge Contingent Payments (swapping money for solutions to a problem). These can be done without any changes to Bitcoin.

    +

    You could (in theory, read on) use them to build a blockchain similar to ZCash (which heavily relies on zk-SNARKs for proving that their ledger makes sense), but without the trusted setup procedure or novel cryptography (Bulletproofs use very conservative security assumptions). Unfortunately, Bulletproof validation is much slower than zk-SNARK validation for complex problems, so it's not really comparable.

    +

    I expect that the most interesting applications are things we haven't considered yet. They suddenly bring zero-knowledge proofs into scope for a lot of problems and protocols where it wasn't really reasonable to go through the effort of using one of the existing proof systems.

    +

    ++++

    +

    Practical zero-knowledge proofs have existed for a few years now, and ZKCPs are indeed an application of them.

    +

    Bulletproofs are just a new type of zero-knowledge proof. Compared to zk-SNARKS, they're much more conservative in their security assumptions, and don't need a complicated setup procedure before proofs can be created. On the other hand, they're also larger and slower for complicated problsms. And they don't do anything that couldn't be done before - they're just more practical depending on your requirements.

    + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/todo/confidential-transactions.txt b/public/todo/confidential-transactions.txt new file mode 100644 index 0000000..2ff0b8f --- /dev/null +++ b/public/todo/confidential-transactions.txt @@ -0,0 +1,18 @@ + +Pieter Wuille on CT: + +In a system that uses CT, if someone finds a break in the fundamental security of elliptic curve cryptography (ECC), he can print money. Worse, because the amounts are all private, he can do so undetectably. That's an existential threat for a currency which has controlled inflation as prime goal. + +Such a break would be dangerous for Bitcoin (even without CT) regardless, as it relies on ECC for protecting against theft. However, Bitcoin can migrate to use a different signature scheme if necessary. It would be chaotic, but not necessarily pose an existential risk. + +There are people who agree with this perspective. It's a mathematical fact that any privacy system that hides amounts and is built on top of ECC will at least have one of the properties below: + + An ECC break will permit printing money undetectaby. + + An ECC break will permit deanonymizing amounts in the historical chain. + +So we are faced with a choice between those two regardless if we want better privacy. Some people believe the second is worse than the first, and choosing the first actually allows for more efficient technology. This is a choice that Zcash, Monero, Grin, all make. CT with Bulletproofs would do the same. + +However, regardless of your own opinion in this matter, Bitcoin's evolution is a large collaborative process, where such fundamental changes need buy-in from large parts of the ecosystem. My fear is that the question of giving up the ability to exactly audit the monetary supply is going to make it hard to make CT acceptable. + +Furthermore, there are other challenges. CT makes transactions larger, slower to verify, and poses a very significant engineering challenge to incorporate into Bitcoin without breaking backward compatibility. diff --git a/public/todo/confidential-transactions/index.html b/public/todo/confidential-transactions/index.html new file mode 100644 index 0000000..a13aab2 --- /dev/null +++ b/public/todo/confidential-transactions/index.html @@ -0,0 +1,954 @@ + + + + + + + + + + + + + + + + + + + + + + + Confidential transactions - Monero Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    +
    + +
    + + + +
    + +
    + +
    + + + + +
    +
    + + + +
    +
    +
    + + + + + + +
    +
    +
    + + + +
    +
    + + + + + + + +

    Confidential transactions

    + +

    Pieter Wuille on CT:

    +

    In a system that uses CT, if someone finds a break in the fundamental security of elliptic curve cryptography (ECC), he can print money. Worse, because the amounts are all private, he can do so undetectably. That's an existential threat for a currency which has controlled inflation as prime goal.

    +

    Such a break would be dangerous for Bitcoin (even without CT) regardless, as it relies on ECC for protecting against theft. However, Bitcoin can migrate to use a different signature scheme if necessary. It would be chaotic, but not necessarily pose an existential risk.

    +

    There are people who agree with this perspective. It's a mathematical fact that any privacy system that hides amounts and is built on top of ECC will at least have one of the properties below:

    +
    An ECC break will permit printing money undetectaby.
    +
    +An ECC break will permit deanonymizing amounts in the historical chain.
    +
    +

    In other words:

    +
    An ECC break means the currency can undetectably be inflated (going forward).
    +
    +An ECC break means the ledger's history can retroactively be deanonymized (goin backward).
    +
    +

    So we are faced with a choice between those two regardless if we want better privacy. Some people believe the second is worse than the first, and choosing the first actually allows for more efficient technology. This is a choice that Zcash, Monero, Grin, all make. CT with Bulletproofs would do the same.

    +

    However, regardless of your own opinion in this matter, Bitcoin's evolution is a large collaborative process, where such fundamental changes need buy-in from large parts of the ecosystem. My fear is that the question of giving up the ability to exactly audit the monetary supply is going to make it hard to make CT acceptable.

    +

    Furthermore, there are other challenges. CT makes transactions larger, slower to verify, and poses a very significant engineering challenge to incorporate into Bitcoin without breaking backward compatibility.

    +

    ++++

    +
    +

    Also, is there any possible system that can have unconditional soundness and privacy at the same time (something other than ECC obviously)?

    +
    +

    No, that's mathematically impossible.

    + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/public/todo/monero-wallet-cli__remaining_commands.txt b/public/todo/monero-wallet-cli__remaining_commands.txt new file mode 100644 index 0000000..efdeeff --- /dev/null +++ b/public/todo/monero-wallet-cli__remaining_commands.txt @@ -0,0 +1,21 @@ + +### TODO + + payment_id + payments [ ... ] + print_ring | + save_known_rings + save_watch_only + set