diff --git a/assets/global-DvdzMk0y.css b/assets/global-DvdzMk0y.css new file mode 100644 index 0000000..06602d2 --- /dev/null +++ b/assets/global-DvdzMk0y.css @@ -0,0 +1 @@ +/*! tailwindcss v2.2.19 | MIT License | https://tailwindcss.com *//*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */*,:before,:after{box-sizing:border-box}html{-moz-tab-size:4;-o-tab-size:4;tab-size:4}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"}hr{height:0;color:inherit}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}button,[type=button]{-webkit-appearance:button}::-moz-focus-inner{border-style:none;padding:0}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}button{background-color:transparent;background-image:none}fieldset{margin:0;padding:0}ol,ul{list-style:none;margin:0;padding:0}html{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}body{font-family:inherit;line-height:inherit}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:currentColor}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}pre,code,kbd,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}*,:before,:after{--tw-border-opacity: 1;border-color:rgba(229,231,235,var(--tw-border-opacity))}.relative{position:relative}.mx-auto{margin-left:auto;margin-right:auto}.block{display:block}.table{display:table}.contents{display:contents}.h-40{height:10rem}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{transform:scale(2);opacity:0}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}.px-4{padding-left:1rem;padding-right:1rem}.pt-20{padding-top:5rem}.pb-10{padding-bottom:2.5rem}*,:before,:after{--tw-shadow: 0 0 #0000}*,:before,:after{--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgba(59, 130, 246, .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000}.filter{--tw-blur: var(--tw-empty, );--tw-brightness: var(--tw-empty, );--tw-contrast: var(--tw-empty, );--tw-grayscale: var(--tw-empty, );--tw-hue-rotate: var(--tw-empty, );--tw-invert: var(--tw-empty, );--tw-saturate: var(--tw-empty, );--tw-sepia: var(--tw-empty, );--tw-drop-shadow: var(--tw-empty, );filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.kdl-section{color:#374151;max-width:65ch}.kdl-section [class~=lead]{color:#4b5563;font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.kdl-section a{color:#111827;text-decoration:underline;font-weight:500}.kdl-section strong{color:#111827;font-weight:600}.kdl-section ol{counter-reset:list-counter;margin-top:1.25em;margin-bottom:1.25em}.kdl-section ol>li{position:relative;counter-increment:list-counter;padding-left:1.75em}.kdl-section ol>li:before{content:counter(list-counter) ".";position:absolute;font-weight:400;color:#6b7280;left:0}.kdl-section ul>li{position:relative;padding-left:1.75em}.kdl-section ul>li:before{content:"";position:absolute;background-color:#d1d5db;border-radius:50%;width:.375em;height:.375em;top:.6875em;left:.25em}.kdl-section hr{border-color:#e5e7eb;border-top-width:1px;margin-top:3em;margin-bottom:3em}.kdl-section blockquote{font-weight:500;font-style:italic;color:#111827;border-left-width:.25rem;border-left-color:#e5e7eb;quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.kdl-section blockquote p:first-of-type:before{content:open-quote}.kdl-section blockquote p:last-of-type:after{content:close-quote}.kdl-section h1{color:#111827;font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.kdl-section h2{color:#111827;font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.kdl-section h3{color:#111827;font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.kdl-section h4{color:#111827;font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.kdl-section figure figcaption{color:#6b7280;font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.kdl-section code{color:#111827;font-weight:600;font-size:.875em}.kdl-section code:before{content:none}.kdl-section code:after{content:none}.kdl-section a code{color:#111827}.kdl-section pre{color:#e5e7eb;background-color:#1f2937;overflow-x:auto;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding:.8571429em 1.1428571em}.kdl-section pre code{background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:400;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.kdl-section pre code:before{content:""}.kdl-section pre code:after{content:none}.kdl-section table{width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.kdl-section thead{color:#111827;font-weight:600;border-bottom-width:1px;border-bottom-color:#d1d5db}.kdl-section thead th{vertical-align:bottom;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.kdl-section tbody tr{border-bottom-width:1px;border-bottom-color:#e5e7eb}.kdl-section tbody tr:last-child{border-bottom-width:0}.kdl-section tbody td{vertical-align:top;padding:.5714286em}.kdl-section{font-size:1rem;line-height:1.75}.kdl-section p{margin-top:1.25em;margin-bottom:1.25em}.kdl-section h2 code{font-size:.875em}.kdl-section ul{margin-top:1.25em;margin-bottom:1.25em}.kdl-section li{margin-top:.5em;margin-bottom:.5em}.kdl-section>ul>li p{margin-top:.75em;margin-bottom:.75em}.kdl-section>ul>li>*:first-child{margin-top:1.25em}.kdl-section>ul>li>*:last-child{margin-bottom:1.25em}.kdl-section>ol>li>*:first-child{margin-top:1.25em}.kdl-section>ol>li>*:last-child{margin-bottom:1.25em}.kdl-section ul ul,.kdl-section ul ol,.kdl-section ol ul,.kdl-section ol ol,.prose ul ul,.prose ul ol,.prose ol ul,.prose ol ol{margin-top:.75em;margin-bottom:.75em}.kdl-section{font-size:1.25rem;line-height:1.8}.kdl-section p{margin-top:1.2em;margin-bottom:1.2em}.kdl-section [class~=lead]{font-size:1.2em;line-height:1.5;margin-top:1em;margin-bottom:1em}.kdl-section blockquote{margin-top:1.6em;margin-bottom:1.6em;padding-left:1.0666667em}.kdl-section h1{font-size:2.8em;margin-top:0;margin-bottom:.8571429em;line-height:1}.kdl-section h2{font-size:1.8em;margin-top:1.5555556em;margin-bottom:.8888889em;line-height:1.1111111}.kdl-section h3{font-size:1.5em;margin-top:1.6em;margin-bottom:.6666667em;line-height:1.3333333}.kdl-section h4{margin-top:1.8em;margin-bottom:.6em;line-height:1.6}.kdl-section img{margin-top:2em;margin-bottom:2em}.kdl-section video{margin-top:2em;margin-bottom:2em}.kdl-section figure{margin-top:2em;margin-bottom:2em}.kdl-section figure>*{margin-top:0;margin-bottom:0}.kdl-section figure figcaption{font-size:.9em;line-height:1.5555556;margin-top:1em}.kdl-section code{font-size:.9em}.kdl-section h2 code{font-size:.8611111em}.kdl-section h3 code{font-size:.9em}.kdl-section pre{font-size:.9em;line-height:1.7777778;margin-top:2em;margin-bottom:2em;border-radius:.5rem;padding:1.1111111em 1.3333333em}.kdl-section ol,.kdl-section ul{margin-top:1.2em;margin-bottom:1.2em}.kdl-section li{margin-top:.6em;margin-bottom:.6em}.kdl-section ol>li{padding-left:1.8em}.kdl-section ol>li:before{left:0}.kdl-section ul>li{padding-left:1.8em}.kdl-section ul>li:before{width:.35em;height:.35em;top:calc(.9em - .175em);left:.25em}.kdl-section>ul>li p{margin-top:.8em;margin-bottom:.8em}.kdl-section>ul>li>*:first-child{margin-top:1.2em}.kdl-section>ul>li>*:last-child{margin-bottom:1.2em}.kdl-section>ol>li>*:first-child{margin-top:1.2em}.kdl-section>ol>li>*:last-child{margin-bottom:1.2em}.kdl-section ul ul,.kdl-section ul ol,.kdl-section ol ul,.kdl-section ol ol,.prose-xl ul ul,.prose-xl ul ol,.prose-xl ol ul,.prose-xl ol ol{margin-top:.8em;margin-bottom:.8em}.kdl-section hr{margin-top:2.8em;margin-bottom:2.8em}.kdl-section hr+*{margin-top:0}.kdl-section h2+*{margin-top:0}.kdl-section h3+*{margin-top:0}.kdl-section h4+*{margin-top:0}.kdl-section table{font-size:.9em;line-height:1.5555556}.kdl-section thead th{padding-right:.6666667em;padding-bottom:.8888889em;padding-left:.6666667em}.kdl-section thead th:first-child{padding-left:0}.kdl-section thead th:last-child{padding-right:0}.kdl-section tbody td{padding:.8888889em .6666667em}.kdl-section tbody td:first-child{padding-left:0}.kdl-section tbody td:last-child{padding-right:0}.kdl-section>:first-child{margin-top:0}.kdl-section>:last-child{margin-bottom:0}.kdl-section{margin-left:auto;margin-right:auto;padding:2.5rem 1rem}code{background-color:#efefef;padding:.1em .5em;border-radius:4px} diff --git a/assets/index-D8sN9JUE.css b/assets/index-D8sN9JUE.css deleted file mode 100644 index 2d2fa9d..0000000 --- a/assets/index-D8sN9JUE.css +++ /dev/null @@ -1 +0,0 @@ -/*! tailwindcss v2.2.19 | MIT License | https://tailwindcss.com *//*! modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */*,:before,:after{box-sizing:border-box}html{-moz-tab-size:4;-o-tab-size:4;tab-size:4}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"}hr{height:0;color:inherit}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}button,[type=button]{-webkit-appearance:button}::-moz-focus-inner{border-style:none;padding:0}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}button{background-color:transparent;background-image:none}fieldset{margin:0;padding:0}ol,ul{list-style:none;margin:0;padding:0}html{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}body{font-family:inherit;line-height:inherit}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:currentColor}hr{border-top-width:1px}img{border-style:solid}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button{cursor:pointer}table{border-collapse:collapse}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input,optgroup,select,textarea{padding:0;line-height:inherit;color:inherit}pre,code,kbd,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}*,:before,:after{--tw-border-opacity: 1;border-color:rgba(229,231,235,var(--tw-border-opacity))}.mx-auto{margin-left:auto;margin-right:auto}.table{display:table}.contents{display:contents}.h-40{height:10rem}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{transform:scale(2);opacity:0}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{transform:translateY(-25%);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:none;animation-timing-function:cubic-bezier(0,0,.2,1)}}.px-4{padding-left:1rem;padding-right:1rem}.pt-20{padding-top:5rem}.pb-10{padding-bottom:2.5rem}*,:before,:after{--tw-shadow: 0 0 #0000}*,:before,:after{--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgba(59, 130, 246, .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000}.filter{--tw-blur: var(--tw-empty, );--tw-brightness: var(--tw-empty, );--tw-contrast: var(--tw-empty, );--tw-grayscale: var(--tw-empty, );--tw-hue-rotate: var(--tw-empty, );--tw-invert: var(--tw-empty, );--tw-saturate: var(--tw-empty, );--tw-sepia: var(--tw-empty, );--tw-drop-shadow: var(--tw-empty, );filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.kdl-section{color:#374151;max-width:65ch}.kdl-section [class~=lead]{color:#4b5563;font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.kdl-section a{color:#111827;text-decoration:underline;font-weight:500}.kdl-section strong{color:#111827;font-weight:600}.kdl-section ol{counter-reset:list-counter;margin-top:1.25em;margin-bottom:1.25em}.kdl-section ol>li{position:relative;counter-increment:list-counter;padding-left:1.75em}.kdl-section ol>li:before{content:counter(list-counter) ".";position:absolute;font-weight:400;color:#6b7280;left:0}.kdl-section ul>li{position:relative;padding-left:1.75em}.kdl-section ul>li:before{content:"";position:absolute;background-color:#d1d5db;border-radius:50%;width:.375em;height:.375em;top:.6875em;left:.25em}.kdl-section hr{border-color:#e5e7eb;border-top-width:1px;margin-top:3em;margin-bottom:3em}.kdl-section blockquote{font-weight:500;font-style:italic;color:#111827;border-left-width:.25rem;border-left-color:#e5e7eb;quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.kdl-section blockquote p:first-of-type:before{content:open-quote}.kdl-section blockquote p:last-of-type:after{content:close-quote}.kdl-section h1{color:#111827;font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.kdl-section h2{color:#111827;font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.kdl-section h3{color:#111827;font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.kdl-section h4{color:#111827;font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.kdl-section figure figcaption{color:#6b7280;font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.kdl-section code{color:#111827;font-weight:600;font-size:.875em}.kdl-section code:before{content:none}.kdl-section code:after{content:none}.kdl-section a code{color:#111827}.kdl-section pre{color:#e5e7eb;background-color:#1f2937;overflow-x:auto;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding:.8571429em 1.1428571em}.kdl-section pre code{background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:400;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.kdl-section pre code:before{content:""}.kdl-section pre code:after{content:none}.kdl-section table{width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.kdl-section thead{color:#111827;font-weight:600;border-bottom-width:1px;border-bottom-color:#d1d5db}.kdl-section thead th{vertical-align:bottom;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.kdl-section tbody tr{border-bottom-width:1px;border-bottom-color:#e5e7eb}.kdl-section tbody tr:last-child{border-bottom-width:0}.kdl-section tbody td{vertical-align:top;padding:.5714286em}.kdl-section{font-size:1rem;line-height:1.75}.kdl-section p{margin-top:1.25em;margin-bottom:1.25em}.kdl-section h2 code{font-size:.875em}.kdl-section ul{margin-top:1.25em;margin-bottom:1.25em}.kdl-section li{margin-top:.5em;margin-bottom:.5em}.kdl-section>ul>li p{margin-top:.75em;margin-bottom:.75em}.kdl-section>ul>li>*:first-child{margin-top:1.25em}.kdl-section>ul>li>*:last-child{margin-bottom:1.25em}.kdl-section>ol>li>*:first-child{margin-top:1.25em}.kdl-section>ol>li>*:last-child{margin-bottom:1.25em}.kdl-section ul ul,.kdl-section ul ol,.kdl-section ol ul,.kdl-section ol ol,.prose ul ul,.prose ul ol,.prose ol ul,.prose ol ol{margin-top:.75em;margin-bottom:.75em}.kdl-section{font-size:1.25rem;line-height:1.8}.kdl-section p{margin-top:1.2em;margin-bottom:1.2em}.kdl-section [class~=lead]{font-size:1.2em;line-height:1.5;margin-top:1em;margin-bottom:1em}.kdl-section blockquote{margin-top:1.6em;margin-bottom:1.6em;padding-left:1.0666667em}.kdl-section h1{font-size:2.8em;margin-top:0;margin-bottom:.8571429em;line-height:1}.kdl-section h2{font-size:1.8em;margin-top:1.5555556em;margin-bottom:.8888889em;line-height:1.1111111}.kdl-section h3{font-size:1.5em;margin-top:1.6em;margin-bottom:.6666667em;line-height:1.3333333}.kdl-section h4{margin-top:1.8em;margin-bottom:.6em;line-height:1.6}.kdl-section img{margin-top:2em;margin-bottom:2em}.kdl-section video{margin-top:2em;margin-bottom:2em}.kdl-section figure{margin-top:2em;margin-bottom:2em}.kdl-section figure>*{margin-top:0;margin-bottom:0}.kdl-section figure figcaption{font-size:.9em;line-height:1.5555556;margin-top:1em}.kdl-section code{font-size:.9em}.kdl-section h2 code{font-size:.8611111em}.kdl-section h3 code{font-size:.9em}.kdl-section pre{font-size:.9em;line-height:1.7777778;margin-top:2em;margin-bottom:2em;border-radius:.5rem;padding:1.1111111em 1.3333333em}.kdl-section ol,.kdl-section ul{margin-top:1.2em;margin-bottom:1.2em}.kdl-section li{margin-top:.6em;margin-bottom:.6em}.kdl-section ol>li{padding-left:1.8em}.kdl-section ol>li:before{left:0}.kdl-section ul>li{padding-left:1.8em}.kdl-section ul>li:before{width:.35em;height:.35em;top:calc(.9em - .175em);left:.25em}.kdl-section>ul>li p{margin-top:.8em;margin-bottom:.8em}.kdl-section>ul>li>*:first-child{margin-top:1.2em}.kdl-section>ul>li>*:last-child{margin-bottom:1.2em}.kdl-section>ol>li>*:first-child{margin-top:1.2em}.kdl-section>ol>li>*:last-child{margin-bottom:1.2em}.kdl-section ul ul,.kdl-section ul ol,.kdl-section ol ul,.kdl-section ol ol,.prose-xl ul ul,.prose-xl ul ol,.prose-xl ol ul,.prose-xl ol ol{margin-top:.8em;margin-bottom:.8em}.kdl-section hr{margin-top:2.8em;margin-bottom:2.8em}.kdl-section hr+*{margin-top:0}.kdl-section h2+*{margin-top:0}.kdl-section h3+*{margin-top:0}.kdl-section h4+*{margin-top:0}.kdl-section table{font-size:.9em;line-height:1.5555556}.kdl-section thead th{padding-right:.6666667em;padding-bottom:.8888889em;padding-left:.6666667em}.kdl-section thead th:first-child{padding-left:0}.kdl-section thead th:last-child{padding-right:0}.kdl-section tbody td{padding:.8888889em .6666667em}.kdl-section tbody td:first-child{padding-left:0}.kdl-section tbody td:last-child{padding-right:0}.kdl-section>:first-child{margin-top:0}.kdl-section>:last-child{margin-bottom:0}.kdl-section{margin-left:auto;margin-right:auto;padding:2.5rem 1rem}code{background-color:#efefef;padding:.1em .5em;border-radius:4px} diff --git a/index.html b/index.html index e7a1084..3fd2f8c 100644 --- a/index.html +++ b/index.html @@ -15,7 +15,7 @@ - +
@@ -66,14 +66,14 @@ XML. It looks like this:

For more details, see the overview below. Play with it in your browser!

There's a living -specification, as well as +specification, as well as various implementations. You can also check out the FAQ to answer all your burning questions!

The current version of the KDL spec is -KDL 2.0.0. For legacy KDL, -please refer to the KDL 1.0.0 +KDL 2.0.0. For legacy KDL, +please refer to the KDL 1.0.0 spec. All users are -encouraged to migrate. Migration is forward-and-backward-compatible and +encouraged to migrate. Migration is forward-and-backward-compatible and safe, and can be automated.

In addition to a spec for KDL itself, there are specifications for a KDL Query diff --git a/spec-v1/index.html b/spec-v1/index.html new file mode 100644 index 0000000..82fd600 --- /dev/null +++ b/spec-v1/index.html @@ -0,0 +1,594 @@ + + + + + + + KDL v1 Specification + + + + + + + + + + +

KDL v1 Spec

+

This is the semi-formal specification for the legacy version of KDL, including +the intended data model and the grammar.

+

This document describes KDL version 1.0.0. It was released on September 11, 2021.

+

Information in this spec is intended as both an accessible historical record, +and a reference for KDL implementors who are interested in supporting both major +versions of the language.

+

The v1 spec will not receive further updates outside of minor, inconsequential +rewordings or other superficial fixes and is considered a "legacy" version.

+

Compatibility

+

KDL v2 is designed such that for any given KDL document in either v1 or v2, the +parse will either fail completely, or, if the parse succeeds, the data +represented by a v1 or v2 parser will be identical. This means that it's safe to +use a fallback parsing strategy in order to support both v1 and v2 +simultaneously. For example, node "foo" is a valid node in both versions, and +should be represented identically by parsers.

+

KDL v2 is designed such that for any given KDL document written as KDL +1.0 or KDL 2.0, +the parse will either fail completely, or, if the +parse succeeds, the data represented by a v1 or v2 parser will be identical. +This means that it's safe to use a fallback parsing strategy in order to support +both v1 and v2 simultaneously. For example, node "foo" is a valid node in both +versions, and should be represented identically by parsers.

+

A version marker /- kdl-version 1 (or 2) MAY be added to the beginning of +a KDL document, optionally preceded by the BOM, and parsers MAY use that as a +hint as to which version to parse the document as.

+

Introduction

+

KDL is a node-oriented document language. Its niche and purpose overlaps with +XML, and as do many of its semantics. You can use KDL both as a configuration +language, and a data exchange or storage format, if you so choose.

+

The bulk of this document is dedicated to a long-form description of all +Components of a KDL document. There is also a much more terse +Grammar at the end of the document that covers most of the +rules, with some semantic exceptions involving the data model.

+

KDL is designed to be easy to read and easy to implement.

+

In this document, references to "left" or "right" refer to directions in the +data stream towards the beginning or end, respectively; in other words, +the directions if the data stream were only ASCII text. They do not refer +to the writing direction of text, which can flow in either direction, +depending on the characters used.

+

Components

+

Document

+

The toplevel concept of KDL is a Document. A Document is composed of zero or +more Nodes, separated by newlines and whitespace, and eventually +terminated by an EOF.

+

All KDL documents should be UTF-8 encoded and conform to the specifications in +this document.

+

Example

+

The following is a document composed of two toplevel nodes:

+
foo {
+    bar
+}
+baz
+
+

Node

+

Being a node-oriented language means that the real core component of any KDL +document is the "node". Every node must have a name, which is an +Identifier.

+

The name may be preceded by a Type Annotation to further +clarify its type, particularly in relation to its parent node. (For example, +clarifying that a particular date child node is for the publication date, +rather than the last-modified date, with (published)date.)

+

Following the name are zero or more Arguments or +Properties, separated by either whitespace or a +slash-escaped line continuation. Arguments and Properties +may be interspersed in any order, much like is common with positional +arguments vs options in command line tools.

+

Children can be placed after the name and the optional +Arguments and Properties, possibly separated by either whitespace or a +slash-escaped line continuation.

+

Arguments are ordered relative to each other (but not relative to Properties) +and that order must be preserved in order to maintain the semantics.

+

By contrast, Property order SHOULD NOT matter to implementations. +Children should be used if an order-sensitive key/value +data structure must be represented in KDL.

+

Nodes MAY be prefixed with /- to "comment out" the entire node, including +its properties, arguments, and children, and make it act as plain whitespace, +even if it spreads across multiple lines.

+

Finally, a node is terminated by either a Newline, a semicolon (;) +or the end of the file/stream (an EOF).

+

Example

+
foo 1 key="val" 3 {
+    bar
+    (role)baz 1 2
+}
+
+

Identifier

+

An Identifier is either a Bare Identifier, which is an +unquoted string like node or item, or a String, which is quoted, +like "node" or "two words". There's no semantic difference between the +kinds of identifier; this simply allows for the use of quotes to have unusual +identifiers that are inexpressible as bare identifiers.

+

Bare Identifier

+

A Bare Identifier is composed of any Unicode codepoint other than non-initial +characters, followed by any number of Unicode +codepoints other than non-identifier characters, +so long as this doesn't produce something confusable for a Number, +Boolean, or Null. For example, both a Number +and an Identifier can start with -, but when an Identifier starts with - +the second character cannot be a digit. This is precisely specified in the +Full Grammar below.

+

Identifiers are terminated by Whitespace or +Newlines.

+

Non-initial characters

+

The following characters cannot be the first character in a +Bare Identifier:

+ +

Be aware that the - character can only be used as an initial +character if the second character is not a digit. This allows +identifiers to look like --this, and removes the ambiguity +of having an identifier look like a negative number.

+

Non-identifier characters

+

The following characters cannot be used anywhere in a Bare Identifier:

+
    +
  • Any codepoint with hexadecimal value 0x20 or below.
  • +
  • Any codepoint with hexadecimal value higher than 0x10FFFF.
  • +
  • Any of \/(){}<>;[]=,"
  • +
+

Line Continuation

+

Line continuations allow Nodes to be spread across multiple lines.

+

A line continuation is a \ character followed by zero or more whitespace +characters and an optional single-line comment. It must be terminated by a +Newline (including the Newline that is part of single-line comments).

+

Following a line continuation, processing of a Node can continue as usual.

+

Example

+
my-node 1 2 \  // comments are ok after \
+        3 4    // This is the actual end of the Node.
+
+

Property

+

A Property is a key/value pair attached to a Node. A Property is +composed of an Identifier, followed immediately by a =, and then a Value.

+

Properties should be interpreted left-to-right, with rightmost properties with +identical names overriding earlier properties. That is:

+
node a=1 a=2
+
+

In this example, the node's a value must be 2, not 1.

+

No other guarantees about order should be expected by implementers. +Deserialized representations may iterate over properties in any order and +still be spec-compliant.

+

Properties MAY be prefixed with /- to "comment out" the entire token and +make it act as plain whitespace, even if it spreads across multiple lines.

+

Argument

+

An Argument is a bare Value attached to a Node, with no +associated key. It shares the same space as Properties, and may be interleaved with them.

+

A Node may have any number of Arguments, which should be evaluated left to +right. KDL implementations MUST preserve the order of Arguments relative to +each other (not counting Properties).

+

Arguments MAY be prefixed with /- to "comment out" the entire token and +make it act as plain whitespace, even if it spreads across multiple lines.

+

Example

+
my-node 1 2 3 "a" "b" "c"
+
+

Children Block

+

A children block is a block of Nodes, surrounded by { and }. They +are an optional part of nodes, and create a hierarchy of KDL nodes.

+

Regular node termination rules apply, which means multiple nodes can be +included in a single-line children block, as long as they're all terminated by +;.

+

Example

+
parent {
+    child1
+    child2
+}
+
+parent { child1; child2; }
+
+

Value

+

A value is either: a String, a Number, a +Boolean, or Null.

+

Values MUST be either Arguments or values of +Properties.

+

Values (both as arguments and as properties) MAY be prefixed by a single +Type Annotation.

+

Type Annotation

+

A type annotation is a prefix to any Node Name or Value that +includes a suggestion of what type the value is intended to be treated as, +or as a context-specific elaboration of the more generic type the node name +indicates.

+

Type annotations are written as a set of ( and ) with an +Identifier in it. Any valid identifier is considered a valid +type annotation. There must be no whitespace between a type annotation and its +associated Node Name or Value.

+

KDL does not specify any restrictions on what implementations might do with +these annotations. They are free to ignore them, or use them to make decisions +about how to interpret a value.

+

Additionally, the following type annotations MAY be recognized by KDL parsers +and, if used, SHOULD interpret these types as follows:

+

Reserved Type Annotations for Numbers Without Decimals:

+

Signed integers of various sizes (the number is the bit size):

+
    +
  • i8
  • +
  • i16
  • +
  • i32
  • +
  • i64
  • +
+

Unsigned integers of various sizes (the number is the bit size):

+
    +
  • u8
  • +
  • u16
  • +
  • u32
  • +
  • u64
  • +
+

Platform-dependent integer types, both signed and unsigned:

+
    +
  • isize
  • +
  • usize
  • +
+

Reserved Type Annotations for Numbers With Decimals:

+

IEEE 754 floating point numbers, both single (32) and double (64) precision:

+
    +
  • f32
  • +
  • f64
  • +
+

IEEE 754-2008 decimal floating point numbers

+
    +
  • decimal64
  • +
  • decimal128
  • +
+

Reserved Type Annotations for Strings:

+
    +
  • date-time: ISO8601 date/time format.
  • +
  • time: "Time" section of ISO8601.
  • +
  • date: "Date" section of ISO8601.
  • +
  • duration: ISO8601 duration format.
  • +
  • decimal: IEEE 754-2008 decimal string format.
  • +
  • currency: ISO 4217 currency code.
  • +
  • country-2: ISO 3166-1 alpha-2 country code.
  • +
  • country-3: ISO 3166-1 alpha-3 country code.
  • +
  • country-subdivision: ISO 3166-2 country subdivision code.
  • +
  • email: RFC5322 email address.
  • +
  • idn-email: RFC6531 internationalized email address.
  • +
  • hostname: RFC1123 internet hostname (only ASCII segments)
  • +
  • idn-hostname: RFC5890 internationalized internet hostname (only xn---prefixed ASCII "punycode" segments, or non-ASCII segments)
  • +
  • ipv4: RFC2673 dotted-quad IPv4 address.
  • +
  • ipv6: RFC2373 IPv6 address.
  • +
  • url: RFC3986 URI.
  • +
  • url-reference: RFC3986 URI Reference.
  • +
  • irl: RFC3987 Internationalized Resource Identifier.
  • +
  • irl-reference: RFC3987 Internationalized Resource Identifier Reference.
  • +
  • url-template: RFC6570 URI Template.
  • +
  • uuid: RFC4122 UUID.
  • +
  • regex: Regular expression. Specific patterns may be implementation-dependent.
  • +
  • base64: A Base64-encoded string, denoting arbitrary binary data.
  • +
+

Examples

+
node (u8)123
+node prop=(regex)".*"
+(published)date "1970-01-01"
+(contributor)person name="Foo McBar"
+
+

String

+

Strings in KDL represent textual Values, or unusual identifiers. A +String is either a Quoted String or a +Raw String. Quoted Strings may include escaped characters, while +Raw Strings always contain only the literal characters that are present.

+

Quoted String

+

A Quoted String is delimited by " on either side of any number of literal +string characters except unescaped " and \. This includes literal +Newline characters, which means a String Value can encompass +multiple lines without behaving like a Newline for Node parsing +purposes.

+

Strings MUST be represented as UTF-8 values.

+

In addition to literal code points, a number of "escapes" are supported. +"Escapes" are the character \ followed by another character, and are +interpreted as described in the following table:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameEscapeCode Pt
Line Feed\nU+000A
Carriage Return\rU+000D
Character Tabulation (Tab)\tU+0009
Reverse Solidus (Backslash)\\U+005C
Solidus (Forwardslash)\/U+002F
Quotation Mark (Double Quote)\"U+0022
Backspace\bU+0008
Form Feed\fU+000C
Unicode Escape\u{(1-6 hex chars)}Code point described by hex characters, up to 10FFFF
+

Raw String

+

Raw Strings in KDL are much like Quoted Strings, except they +do not support \-escapes. They otherwise share the same properties as far as +literal Newline characters go, and the requirement of UTF-8 +representation.

+

Raw String literals are represented as r, followed by zero or more # +characters, followed by ", followed by any number of UTF-8 literals. The +string is then closed by a " followed by a matching number of # +characters. This allows them to contain raw " or # characters; only the +precise terminator (resembling "##, for example) ends the raw string. This +means that the string sequence " or "# and such must not match the closing +" with the same or more # characters as the opening r.

+

Example

+
just-escapes r"\n will be literal"
+quotes-and-escapes r#"hello\n\r\asd"world"#
+
+

Number

+

Numbers in KDL represent numerical Values. There is no logical distinction in KDL +between real numbers, integers, and floating point numbers. It's up to +individual implementations to determine how to represent KDL numbers.

+

There are four syntaxes for Numbers: Decimal, Hexadecimal, Octal, and Binary.

+
    +
  • All numbers may optionally start with one of - or +, which determine whether they'll be positive or negative.
  • +
  • Binary numbers start with 0b and only allow 0 and 1 as digits, which may be separated by _. They represent numbers in radix 2.
  • +
  • Octal numbers start with 0o and only allow digits between 0 and 7, which may be separated by _. They represent numbers in radix 8.
  • +
  • Hexadecimal numbers start with 0x and allow digits between 0 and 9, as well as letters A through F, in either lower or upper case, which may be separated by _. They represent numbers in radix 16.
  • +
  • Decimal numbers are a bit more special: +
      +
    • They have no radix prefix.
    • +
    • They use digits 0 through 9, which may be separated by _.
    • +
    • They may optionally include a decimal separator ., followed by more digits, which may again be separated by _.
    • +
    • They may optionally be followed by E or e, an optional - or +, and more digits, to represent an exponent value.
    • +
    +
  • +
+

Boolean

+

A boolean Value is either the symbol true or false. These +SHOULD be represented by implementation as boolean logical values, or some +approximation thereof.

+

Example

+
my-node true value=false
+
+

Null

+

The symbol null represents a null Value. It's up to the +implementation to decide how to represent this, but it generally signals the +"absence" of a value. It is reasonable for an implementation to ignore null +values altogether when deserializing.

+

Example

+
my-node null key=null
+
+

Whitespace

+

The following characters should be treated as non-Newline white +space:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameCode Pt
Character TabulationU+0009
SpaceU+0020
No-Break SpaceU+00A0
Ogham Space MarkU+1680
En QuadU+2000
Em QuadU+2001
En SpaceU+2002
Em SpaceU+2003
Three-Per-Em SpaceU+2004
Four-Per-Em SpaceU+2005
Six-Per-Em SpaceU+2006
Figure SpaceU+2007
Punctuation SpaceU+2008
Thin SpaceU+2009
Hair SpaceU+200A
Narrow No-Break SpaceU+202F
Medium Mathematical SpaceU+205F
Ideographic SpaceU+3000
+

Multi-line comments

+

In addition to single-line comments using //, comments can also be started +with /* and ended with */. These comments can span multiple lines. They +are allowed in all positions where Whitespace is allowed and +can be nested.

+

Newline

+

The following characters should be treated as new +lines:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AcronymNameCode Pt
CRLFCarriage Return and Line FeedU+000D + U+000A
CRCarriage ReturnU+000D
LFLine FeedU+000A
NELNext LineU+0085
FFForm FeedU+000C
LSLine SeparatorU+2028
PSParagraph SeparatorU+2029
+

Note that for the purpose of new lines, CRLF is considered a single newline. VT Vertical tab U+000B was mistakenly excluded, but the v1 spec if frozen, so it's left unchanged.

+

Full Grammar

+
nodes := linespace* (node nodes?)? linespace*
+
+node := ('/-' node-space*)? type? identifier (node-space+ node-prop-or-arg)* (node-space* node-children ws*)? node-space* node-terminator
+node-prop-or-arg := ('/-' node-space*)? (prop | value)
+node-children := ('/-' node-space*)? '{' nodes '}'
+node-space := ws* escline ws* | ws+
+node-terminator := single-line-comment | newline | ';' | eof
+
+identifier := string | bare-identifier
+bare-identifier := ((identifier-char - digit - sign) identifier-char* | sign ((identifier-char - digit) identifier-char*)?) - keyword
+identifier-char := unicode - linespace - [\/(){}<>;[]=,"]
+keyword := boolean | 'null'
+prop := identifier '=' value
+value := type? (string | number | keyword)
+type := '(' identifier ')'
+
+string := raw-string | escaped-string
+escaped-string := '"' character* '"'
+character := '\' escape | [^\"]
+escape := ["\\/bfnrt] | 'u{' hex-digit{1, 6} '}'
+hex-digit := [0-9a-fA-F]
+
+raw-string := 'r' raw-string-hash
+raw-string-hash := '#' raw-string-hash '#' | raw-string-quotes
+raw-string-quotes := '"' .* '"'
+
+number := hex | octal | binary | decimal
+
+decimal := sign? integer ('.' integer)? exponent?
+exponent := ('e' | 'E') sign? integer
+integer := digit (digit | '_')*
+digit := [0-9]
+sign := '+' | '-'
+
+hex := sign? '0x' hex-digit (hex-digit | '_')*
+octal := sign? '0o' [0-7] [0-7_]*
+binary := sign? '0b' ('0' | '1') ('0' | '1' | '_')*
+
+boolean := 'true' | 'false'
+
+escline := '\\' ws* (single-line-comment | newline)
+
+linespace := newline | ws | single-line-comment
+
+newline := See Table (All line-break white_space)
+
+ws := bom | unicode-space | multi-line-comment
+
+bom := '\u{FEFF}'
+
+unicode-space := See Table (All White_Space unicode characters which are not `newline`)
+
+single-line-comment := '//' ^newline+ (newline | eof)
+multi-line-comment := '/*' commented-block
+commented-block := '*/' | (multi-line-comment | '*' | '/' | [^*/]+) commented-block
+
+
+ +