diff --git a/Assets/css/all.css b/Assets/css/all.css index f9d6ca5f..f070425c 100644 --- a/Assets/css/all.css +++ b/Assets/css/all.css @@ -183,6 +183,7 @@ --icon-extension: url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23eca95b' height='90' rx='8' stroke='%23e89234' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cg fill='%23fff'%3E%3Cpath d='m54.43 81.93h-33.92v-63.86h33.92v12.26h-21.82v13.8h20.45v11.32h-20.45v14.22h21.82z'/%3E%3Cpath d='m68.74 74.58h-.27l-2.78 7.35h-7.28l5.59-12.61-6-12.54h8l2.74 7.3h.27l2.76-7.3h7.64l-6.14 12.54 5.89 12.61h-7.64z'/%3E%3C/g%3E%3C/svg%3E%0A"); --icon-function: url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%237ac673' height='90' rx='8' stroke='%235bb74f' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='m24.25 75.66a5.47 5.47 0 0 1 5.75-5.73c1.55 0 3.55.41 6.46.41 3.19 0 4.78-1.55 5.46-6.65l1.5-10.14h-9.34a6 6 0 1 1 0-12h11.1l1.09-7.27c1.55-10.89 8.01-16.58 17.73-16.58 6.69 0 11.74 1.77 11.74 6.64a5.47 5.47 0 0 1 -5.74 5.73c-1.55 0-3.55-.41-6.46-.41-3.14 0-4.73 1.51-5.46 6.65l-.78 5.27h11.44a6 6 0 1 1 .05 12h-13.19l-1.78 12.11c-1.59 10.92-8.1 16.61-17.82 16.61-6.7 0-11.75-1.77-11.75-6.64z' fill='%23fff'/%3E%3C/svg%3E%0A"); --icon-method: url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%235a98f8' height='90' rx='8' stroke='%232974ed' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='m70.61 81.71v-39.6h-.31l-15.69 39.6h-9.22l-15.65-39.6h-.35v39.6h-14.19v-63.42h18.63l16 41.44h.36l16-41.44h18.61v63.42z' fill='%23fff'/%3E%3C/svg%3E%0A"); + --icon-operator: url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%237ac673' height='90' rx='8' stroke='%235bb74f' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cellipse fill='%23fff' cx='50' cy='50' rx='16' ry='16'/%3E%3C/svg%3E%0A"); --icon-property: url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%2389c5e6' height='90' rx='8' stroke='%236bb7e1' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='m52.31 18.29c13.62 0 22.85 8.84 22.85 22.46s-9.71 22.37-23.82 22.37h-10.34v18.59h-16.16v-63.42zm-11.31 32.71h7c6.85 0 10.89-3.56 10.89-10.2s-4.08-10.16-10.89-10.16h-7z' fill='%23fff'/%3E%3C/svg%3E%0A"); --icon-protocol: url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23ff6682' height='90' rx='8' stroke='%23ff2d55' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cg fill='%23fff'%3E%3Cpath d='m46.28 18.29c11.84 0 20 8.66 20 21.71s-8.44 21.71-20.6 21.71h-10.81v20h-12.09v-63.42zm-11.41 33.05h8.13c6.93 0 11-4 11-11.29s-4-11.25-10.93-11.25h-8.2z'/%3E%3Cpath d='m62 57.45h8v4.77h.16c.84-3.45 2.54-5.12 5.17-5.12a5.06 5.06 0 0 1 1.92.35v7.55a5.69 5.69 0 0 0 -2.39-.51c-3.08 0-4.66 1.74-4.66 5.12v12.1h-8.2z'/%3E%3C/g%3E%3C/svg%3E%0A"); --icon-structure: url("data:image/svg+xml,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23b57edf' height='90' rx='8' stroke='%239454c2' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='m38.38 63c.74 4.53 5.62 7.16 11.82 7.16s10.37-2.81 10.37-6.68c0-3.51-2.73-5.31-10.24-6.76l-6.5-1.23c-12.66-2.35-19.21-8.49-19.21-18.21 0-12.22 10.59-20.09 25.18-20.09 16 0 25.36 7.83 25.53 19.91h-15c-.26-4.57-4.57-7.29-10.42-7.29s-9.31 2.63-9.31 6.37c0 3.34 2.9 5.18 9.8 6.5l6.5 1.23c13.56 2.6 19.71 8.09 19.71 18.09 0 12.74-10 20.83-26.72 20.83-15.82 0-26.28-7.3-26.5-19.78z' fill='%23fff'/%3E%3C/svg%3E%0A"); @@ -950,6 +951,10 @@ h1 small { color: var(--quaternary-label); } +h3 small { + color: var(--tertiary-label); +} + p code, dd code, li code { @@ -1036,6 +1041,11 @@ nav li[class] { --link: var(--system-blue); } +.operator { + --background-image: var(--icon-operator); + --link: var(--system-green); +} + .property { --background-image: var(--icon-property); --link: var(--system-teal); diff --git a/Changelog.md b/Changelog.md index 7fceb2c2..02bb4edf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for generating documentation for extensions to external types. #230 by @Lukas-Stuehrk and @mattt. +- Added support for generating documentation for operators. + #228 by @Lukas-Stuehrk and @mattt. - Added end-to-end tests for command-line interface. #199 by @MaxDesiatov and @mattt. - Added `--minimum-access-level` option to `generate` and `coverage` commands. diff --git a/Resources/all.min.css b/Resources/all.min.css index 4fc85e8f..24e852ca 100644 --- a/Resources/all.min.css +++ b/Resources/all.min.css @@ -1 +1 @@ -:root{--system-red:#ff3b30;--system-orange:#ff9500;--system-yellow:#fc0;--system-green:#34c759;--system-teal:#5ac8fa;--system-blue:#007aff;--system-indigo:#5856d6;--system-purple:#af52de;--system-pink:#ff2d55;--system-gray:#8e8e93;--system-gray2:#aeaeb2;--system-gray3:#c7c7cc;--system-gray4:#d1d1d6;--system-gray5:#e5e5ea;--system-gray6:#f2f2f7;--label:#000;--secondary-label:#3c3c43;--tertiary-label:#48484a;--quaternary-label:#636366;--placeholder-text:#8e8e93;--link:#007aff;--separator:#e5e5ea;--opaque-separator:#c6c6c8;--system-fill:#787880;--secondary-system-fill:#787880;--tertiary-system-fill:#767680;--quaternary-system-fill:#747480;--system-background:#fff;--secondary-system-background:#f2f2f7;--tertiary-system-background:#fff;--system-grouped-background:#f2f2f7;--secondary-system-grouped-background:#fff;--tertiary-system-grouped-background:#f2f2f7}@supports (color:color(display-p3 1 1 1)){:root{--system-red:color(display-p3 1 0.2314 0.1882);--system-orange:color(display-p3 1 0.5843 0);--system-yellow:color(display-p3 1 0.8 0);--system-green:color(display-p3 0.2039 0.7804 0.349);--system-teal:color(display-p3 0.3529 0.7843 0.9804);--system-blue:color(display-p3 0 0.4784 1);--system-indigo:color(display-p3 0.3451 0.3373 0.8392);--system-purple:color(display-p3 0.6863 0.3216 0.8706);--system-pink:color(display-p3 1 0.1765 0.3333);--system-gray:color(display-p3 0.5569 0.5569 0.5765);--system-gray2:color(display-p3 0.6824 0.6824 0.698);--system-gray3:color(display-p3 0.7804 0.7804 0.8);--system-gray4:color(display-p3 0.8196 0.8196 0.8392);--system-gray5:color(display-p3 0.898 0.898 0.9176);--system-gray6:color(display-p3 0.949 0.949 0.9686);--label:color(display-p3 0 0 0);--secondary-label:color(display-p3 0.2353 0.2353 0.2627);--tertiary-label:color(display-p3 0.2823 0.2823 0.2901);--quaternary-label:color(display-p3 0.4627 0.4627 0.5019);--placeholder-text:color(display-p3 0.5568 0.5568 0.5764);--link:color(display-p3 0 0.4784 1);--separator:color(display-p3 0.898 0.898 0.9176);--opaque-separator:color(display-p3 0.7765 0.7765 0.7843);--system-fill:color(display-p3 0.4706 0.4706 0.502);--secondary-system-fill:color(display-p3 0.4706 0.4706 0.502);--tertiary-system-fill:color(display-p3 0.4627 0.4627 0.502);--quaternary-system-fill:color(display-p3 0.4549 0.4549 0.502);--system-background:color(display-p3 1 1 1);--secondary-system-background:color(display-p3 0.949 0.949 0.9686);--tertiary-system-background:color(display-p3 1 1 1);--system-grouped-background:color(display-p3 0.949 0.949 0.9686);--secondary-system-grouped-background:color(display-p3 1 1 1);--tertiary-system-grouped-background:color(display-p3 0.949 0.949 0.9686)}}:root{--large-title:600 32pt/39pt sans-serif;--title-1:600 26pt/32pt sans-serif;--title-2:600 20pt/25pt sans-serif;--title-3:500 18pt/23pt sans-serif;--headline:500 15pt/20pt sans-serif;--body:300 15pt/20pt sans-serif;--callout:300 14pt/19pt sans-serif;--subhead:300 13pt/18pt sans-serif;--footnote:300 12pt/16pt sans-serif;--caption-1:300 11pt/13pt sans-serif;--caption-2:300 11pt/13pt sans-serif;--icon-associatedtype:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23ff6682' height='90' rx='8' stroke='%23ff2d55' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M42 81.71V31.3H24.47v-13h51.06v13H58v50.41z' fill='%23fff'/%3E%3C/svg%3E");--icon-case:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%2389c5e6' height='90' rx='8' stroke='%236bb7e1' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M20.21 50c0-20.7 11.9-32.79 30.8-32.79 16 0 28.21 10.33 28.7 25.32H64.19C63.4 35 58.09 30.11 51 30.11c-8.79 0-14.37 7.52-14.37 19.82s5.54 20 14.41 20c7.08 0 12.22-4.66 13.23-12.09h15.52c-.74 15.07-12.43 25-28.78 25C32 82.81 20.21 70.72 20.21 50z' fill='%23fff'/%3E%3C/svg%3E");--icon-class:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%239b98e6' height='90' rx='8' stroke='%235856d6' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='m20.21 50c0-20.7 11.9-32.79 30.8-32.79 16 0 28.21 10.33 28.7 25.32h-15.52c-.79-7.53-6.1-12.42-13.19-12.42-8.79 0-14.37 7.52-14.37 19.82s5.54 20 14.41 20c7.08 0 12.22-4.66 13.23-12.09h15.52c-.74 15.07-12.43 25-28.78 25-19.01-.03-30.8-12.12-30.8-32.84z' fill='%23fff'/%3E%3C/svg%3E");--icon-enumeration:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23eca95b' height='90' rx='8' stroke='%23e89234' stroke-miterlimit='10' stroke-width='4' width='90' x='5.17' y='5'/%3E%3Cpath d='M71.9 81.71H28.43V18.29H71.9v13H44.56v12.62h25.71v11.87H44.56V68.7H71.9z' fill='%23fff'/%3E%3C/svg%3E");--icon-extension:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23eca95b' height='90' rx='8' stroke='%23e89234' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cg fill='%23fff'%3E%3Cpath d='M54.43 81.93H20.51V18.07h33.92v12.26H32.61v13.8h20.45v11.32H32.61v14.22h21.82zM68.74 74.58h-.27l-2.78 7.35h-7.28L64 69.32l-6-12.54h8l2.74 7.3h.27l2.76-7.3h7.64l-6.14 12.54 5.89 12.61h-7.64z'/%3E%3C/g%3E%3C/svg%3E");--icon-function:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%237ac673' height='90' rx='8' stroke='%235bb74f' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M24.25 75.66A5.47 5.47 0 0130 69.93c1.55 0 3.55.41 6.46.41 3.19 0 4.78-1.55 5.46-6.65l1.5-10.14h-9.34a6 6 0 110-12h11.1l1.09-7.27C47.82 23.39 54.28 17.7 64 17.7c6.69 0 11.74 1.77 11.74 6.64A5.47 5.47 0 0170 30.07c-1.55 0-3.55-.41-6.46-.41-3.14 0-4.73 1.51-5.46 6.65l-.78 5.27h11.44a6 6 0 11.05 12H55.6l-1.78 12.11C52.23 76.61 45.72 82.3 36 82.3c-6.7 0-11.75-1.77-11.75-6.64z' fill='%23fff'/%3E%3C/svg%3E");--icon-method:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%235a98f8' height='90' rx='8' stroke='%232974ed' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M70.61 81.71v-39.6h-.31l-15.69 39.6h-9.22l-15.65-39.6h-.35v39.6H15.2V18.29h18.63l16 41.44h.36l16-41.44H84.8v63.42z' fill='%23fff'/%3E%3C/svg%3E");--icon-property:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%2389c5e6' height='90' rx='8' stroke='%236bb7e1' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M52.31 18.29c13.62 0 22.85 8.84 22.85 22.46s-9.71 22.37-23.82 22.37H41v18.59H24.84V18.29zM41 51h7c6.85 0 10.89-3.56 10.89-10.2S54.81 30.64 48 30.64h-7z' fill='%23fff'/%3E%3C/svg%3E");--icon-protocol:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23ff6682' height='90' rx='8' stroke='%23ff2d55' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cg fill='%23fff'%3E%3Cpath d='M46.28 18.29c11.84 0 20 8.66 20 21.71s-8.44 21.71-20.6 21.71H34.87v20H22.78V18.29zM34.87 51.34H43c6.93 0 11-4 11-11.29S50 28.8 43.07 28.8h-8.2zM62 57.45h8v4.77h.16c.84-3.45 2.54-5.12 5.17-5.12a5.06 5.06 0 011.92.35V65a5.69 5.69 0 00-2.39-.51c-3.08 0-4.66 1.74-4.66 5.12v12.1H62z'/%3E%3C/g%3E%3C/svg%3E");--icon-structure:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23b57edf' height='90' rx='8' stroke='%239454c2' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M38.38 63c.74 4.53 5.62 7.16 11.82 7.16s10.37-2.81 10.37-6.68c0-3.51-2.73-5.31-10.24-6.76l-6.5-1.23C31.17 53.14 24.62 47 24.62 37.28c0-12.22 10.59-20.09 25.18-20.09 16 0 25.36 7.83 25.53 19.91h-15c-.26-4.57-4.57-7.29-10.42-7.29s-9.31 2.63-9.31 6.37c0 3.34 2.9 5.18 9.8 6.5l6.5 1.23C70.46 46.51 76.61 52 76.61 62c0 12.74-10 20.83-26.72 20.83-15.82 0-26.28-7.3-26.5-19.78z' fill='%23fff'/%3E%3C/svg%3E");--icon-typealias:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%237ac673' height='90' rx='8' stroke='%235bb74f' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M42 81.71V31.3H24.47v-13h51.06v13H58v50.41z' fill='%23fff'/%3E%3C/svg%3E");--icon-variable:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%237ac673' height='90' rx='8' stroke='%235bb74f' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M39.85 81.71L19.63 18.29H38l12.18 47.64h.35L62.7 18.29h17.67L60.15 81.71z' fill='%23fff'/%3E%3C/svg%3E")}body,button,input,select,textarea{-moz-font-feature-settings:"kern";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;direction:ltr;font-synthesis:none;text-align:left}h1:first-of-type,h2:first-of-type,h3:first-of-type,h4:first-of-type,h5:first-of-type,h6:first-of-type{margin-top:0}h1 code,h2 code,h3 code,h4 code,h5 code,h6 code{font-family:inherit;font-weight:inherit}h1 img,h2 img,h3 img,h4 img,h5 img,h6 img{margin:0 .5em .2em 0;vertical-align:middle;display:inline-block}h1+*,h2+*,h3+*,h4+*,h5+*,h6+*{margin-top:.8em}img+h1{margin-top:.5em}img+h1,img+h2,img+h3,img+h4,img+h5,img+h6{margin-top:.3em}:is(h1,h2,h3,h4,h5,h6)+:is(h1,h2,h3,h4,h5,h6){margin-top:.4em}:matches(h1,h2,h3,h4,h5,h6)+:matches(h1,h2,h3,h4,h5,h6){margin-top:.4em}:is(p,ul,ol)+:is(h1,h2,h3,h4,h5,h6){margin-top:1.6em}:matches(p,ul,ol)+:matches(h1,h2,h3,h4,h5,h6){margin-top:1.6em}:is(p,ul,ol)+*{margin-top:.8em}:matches(p,ul,ol)+*{margin-top:.8em}ol,ul{margin-left:1.17647em}:matches(ul,ol) :matches(ul,ol){margin-bottom:0;margin-top:0}nav h2{color:#3c3c43;color:var(--secondary-label);font-size:1rem;font-feature-settings:"smcp";font-variant:small-caps;font-weight:600;text-transform:uppercase}nav ol,nav ul{margin:0;list-style:none}nav li li{font-size:smaller}a:link,a:visited{text-decoration:none}a:hover{text-decoration:underline}a:active{text-decoration:none}b,strong{font-weight:600}.discussion,.summary{font:300 14pt/19pt sans-serif;font:var(--callout)}article>.discussion{margin-bottom:2em}.discussion .highlight{background:transparent;border:1px solid #e5e5ea;border:1px solid var(--separator);font:300 11pt/13pt sans-serif;font:var(--caption-1);padding:1em;text-indent:0}cite,dfn,em,i{font-style:italic}:matches(h1,h2,h3) sup{font-size:.4em}sup a{color:inherit;vertical-align:inherit}sup a:hover{color:#007aff;color:var(--link);text-decoration:none}sub{line-height:1}abbr{border:0}:lang(ja),:lang(ko),:lang(th),:lang(zh){font-style:normal}:lang(ko){word-break:keep-all}form fieldset{margin:1em auto;max-width:450px;width:95%}form label{display:block;font-size:1em;font-weight:400;line-height:1.5em;margin-bottom:14px;position:relative;width:100%}input[type=email],input[type=number],input[type=password],input[type=tel],input[type=text],input[type=url],textarea{border-radius:4px;border:1px solid #e5e5ea;border:1px solid var(--separator);color:#333;font-family:inherit;font-size:100%;font-weight:400;height:34px;margin:0;padding:0 1em;position:relative;vertical-align:top;width:100%;z-index:1}input[type=email],input [type=email]:focus,input[type=number],input [type=number]:focus,input[type=password],input [type=password]:focus,input[type=tel],input [type=tel]:focus,input[type=text],input [type=text]:focus,input[type=url],input [type=url]:focus,textarea,textarea:focus{-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=email]:focus,input[type=number]:focus,input[type=password]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=url]:focus,textarea:focus{border-color:#08c;box-shadow:0 0 0 3px rgba(0,136,204,.3);outline:0;z-index:9}input[type=email]:-moz-read-only,input[type=number]:-moz-read-only,input[type=password]:-moz-read-only,input[type=tel]:-moz-read-only,input[type=text]:-moz-read-only,input[type=url]:-moz-read-only,textarea:-moz-read-only{background:none;border:none;box-shadow:none;padding-left:0}input[type=email]:read-only,input[type=number]:read-only,input[type=password]:read-only,input[type=tel]:read-only,input[type=text]:read-only,input[type=url]:read-only,textarea:read-only{background:none;border:none;box-shadow:none;padding-left:0}::-moz-placeholder{color:#8e8e93;color:var(--placeholder-text)}:-ms-input-placeholder{color:#8e8e93;color:var(--placeholder-text)}::placeholder{color:#8e8e93;color:var(--placeholder-text)}textarea{-webkit-overflow-scrolling:touch;line-height:1.4737;min-height:134px;overflow-y:auto;resize:vertical;transform:translateZ(0)}textarea,textarea:focus{-webkit-appearance:none;-moz-appearance:none;appearance:none}select{background:transparent;border-radius:4px;border:none;cursor:pointer;font-family:inherit;font-size:1em;height:34px;margin:0;padding:0 1em;width:100%}select,select:focus{-webkit-appearance:none;-moz-appearance:none;appearance:none}select:focus{border-color:#08c;box-shadow:0 0 0 3px rgba(0,136,204,.3);outline:0;z-index:9}input[type=file]{background:#fafafa;border-radius:4px;color:#333;cursor:pointer;font-family:inherit;font-size:100%;height:34px;margin:0;padding:6px 1em;position:relative;vertical-align:top;width:100%;z-index:1}input[type=file]:focus{border-color:#08c;outline:0;box-shadow:0 0 0 3px rgba(0,136,204,.3);z-index:9}button,button:focus,input[type=file]:focus,input[type=file]:focus:focus,input[type=reset],input[type=reset]:focus,input[type=submit],input[type=submit]:focus{-webkit-appearance:none;-moz-appearance:none;appearance:none}:matches(button,input[type=reset],input[type=submit]){background-color:#e3e3e3;background:linear-gradient(#fff,#e3e3e3);border-color:#d6d6d6;color:#0070c9}:matches(button,input[type=reset],input[type=submit]):hover{background-color:#eee;background:linear-gradient(#fff,#eee);border-color:#d9d9d9}:matches(button,input[type=reset],input[type=submit]):active{background-color:#dcdcdc;background:linear-gradient(#f7f7f7,#dcdcdc);border-color:#d0d0d0}:matches(button,input[type=reset],input[type=submit]):disabled{background-color:#e3e3e3;background:linear-gradient(#fff,#e3e3e3);border-color:#d6d6d6;color:#0070c9}body{background:#f2f2f7;background:var(--system-grouped-background);color:#000;color:var(--label);font-family:ui-system,-apple-system,BlinkMacSystemFont,sans-serif;font:300 15pt/20pt sans-serif;font:var(--body)}h1{font:600 32pt/39pt sans-serif;font:var(--large-title)}h2{font:600 20pt/25pt sans-serif;font:var(--title-2)}h3{font:500 18pt/23pt sans-serif;font:var(--title-3)}h4,h5,h6{font:500 15pt/20pt sans-serif;font:var(--headline)}a{color:#007aff;color:var(--link)}label{font:300 14pt/19pt sans-serif;font:var(--callout)}input,label{display:block}input{margin-bottom:1em}hr{border:none;border-top:1px solid #e5e5ea;border-top:1px solid var(--separator);margin:1em 0}table{width:100%;font:300 11pt/13pt sans-serif;font:var(--caption-1);caption-side:bottom;margin-bottom:2em}td,th{padding:0 1em}th{font-weight:600;text-align:left}thead th{border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator)}tr:last-of-type td,tr:last-of-type th{border-bottom:none}td,th{border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator);color:#3c3c43;color:var(--secondary-label)}caption{color:#48484a;color:var(--tertiary-label);font:300 11pt/13pt sans-serif;font:var(--caption-2);margin-top:2em;text-align:left}.graph text,code{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-weight:300}.graph>polygon{display:none}.graph text{fill:currentColor!important}.graph ellipse,.graph path,.graph polygon,.graph rect{stroke:currentColor!important}body{width:90vw;max-width:1280px;margin:1em auto}body>header{font:600 26pt/32pt sans-serif;font:var(--title-1);padding:.5em 0}body>header a{color:#000;color:var(--label)}body>header span{font-weight:400}body>header sup{text-transform:uppercase;font-size:small;font-weight:300;letter-spacing:.1ch}body>footer,body>header sup{color:#3c3c43;color:var(--secondary-label)}body>footer{clear:both;padding:1em 0;font:300 11pt/13pt sans-serif;font:var(--caption-1)}@media screen and (max-width:768px){body{width:96vw;max-width:100%}body>header{font:500 18pt/23pt sans-serif;font:var(--title-3);text-align:left;padding:1em 0}body>nav{display:none}body>main{padding:0 1em}}@media screen and (max-width:768px){#relationships figure{display:none}section>[role=article][class] pre{margin-left:-1em;margin-right:-1em}section>[role=article][class] div{margin-left:-2em}}main,nav{overflow-x:auto}main{background:#fff;background:var(--system-background);border-radius:8px;padding:0 2em}main section{border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator);margin-bottom:2em;padding-bottom:1em}main section:last-of-type{border-bottom:none;margin-bottom:0}nav{float:right;margin-left:1em;max-height:100vh;overflow:auto;padding:0 1em 3em;position:sticky;top:1em;width:20vw}nav a{color:#3c3c43;color:var(--secondary-label)}nav ul a{color:#48484a;color:var(--tertiary-label)}nav ol,nav ul{padding:0}nav ul{font:300 14pt/19pt sans-serif;font:var(--callout);margin-bottom:1em}nav ol>li>a{display:block;font-size:smaller;font:500 15pt/20pt sans-serif;font:var(--headline);margin:.5em 0}nav li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}blockquote{--link:var(--secondary-label);border-left:4px solid #e5e5ea;border-left:4px solid var(--separator);color:#3c3c43;color:var(--secondary-label);font-size:smaller;margin-left:0;padding-left:2em}blockquote a{text-decoration:underline}article{padding:2em 0 1em}article>.summary{border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator);margin-bottom:2em;padding-bottom:1em}article>.summary:last-child{border-bottom:none}.parameters th{text-align:right}.parameters td{color:#3c3c43;color:var(--secondary-label)}.parameters th+td{text-align:center}dl{padding-top:1em}dt{font:500 15pt/20pt sans-serif;font:var(--headline)}dd{margin-left:2em;margin-bottom:1em}dd p{margin-top:0}.highlight{background:#f2f2f7;background:var(--secondary-system-background);border-radius:8px;font-size:.75em;margin-bottom:2em;overflow-x:auto;text-indent:-2em;padding:1em 1em 1em 3em;white-space:pre-wrap}.highlight .p{white-space:nowrap}.highlight .placeholder{color:#000;color:var(--label)}.highlight a{text-decoration:underline;color:#8e8e93;color:var(--placeholder-text)}.highlight .attribute,.highlight .keyword,.highlight .literal{color:#af52de;color:var(--system-purple)}.highlight .number{color:#007aff;color:var(--system-blue)}.highlight .declaration{color:#5ac8fa;color:var(--system-teal)}.highlight .type{color:#5856d6;color:var(--system-indigo)}.highlight .directive{color:#ff9500;color:var(--system-orange)}.highlight .comment{color:#8e8e93;color:var(--system-gray)}main summary:hover{text-decoration:underline}figure{margin:2em 0;padding:1em 0}figure svg{max-width:100%;height:auto!important;margin:0 auto;display:block}h1 small{font-size:.5em;line-height:1.5;display:block;font-weight:400;color:#636366;color:var(--quaternary-label)}dd code,li code,p code{font-size:smaller;color:#3c3c43;color:var(--secondary-label)}a code{text-decoration:underline}dl dt[class],nav li[class],section>[role=article][class]{background-image:var(--background-image);background-size:1em;background-repeat:no-repeat;background-position:left .25em;padding-left:3em}dl dt[class]{background-position-y:.125em}section>[role=article]{margin-bottom:1em;padding-bottom:1em;border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator);padding-left:2em!important}section>[role=article]:last-of-type{margin-bottom:0;padding-bottom:0;border-bottom:none}dl dt[class],nav li[class]{list-style:none;text-indent:-1em;margin-bottom:.5em}nav li[class]{padding-left:2.5em}.associatedtype{--background-image:var(--icon-associatedtype);--link:var(--system-pink)}.case,.enumeration_case{--background-image:var(--icon-case);--link:var(--system-teal)}.class{--background-image:var(--icon-class);--link:var(--system-indigo)}.enumeration{--background-image:var(--icon-enumeration)}.enumeration,.extension{--link:var(--system-orange)}.extension{--background-image:var(--icon-extension)}.function{--background-image:var(--icon-function);--link:var(--system-green)}.initializer,.method{--background-image:var(--icon-method);--link:var(--system-blue)}.property{--background-image:var(--icon-property);--link:var(--system-teal)}.protocol{--background-image:var(--icon-protocol);--link:var(--system-pink)}.structure{--background-image:var(--icon-structure);--link:var(--system-purple)}.typealias{--background-image:var(--icon-typealias)}.typealias,.variable{--link:var(--system-green)}.variable{--background-image:var(--icon-variable)}.unknown{--link:var(--quaternary-label);color:#007aff;color:var(--link)} \ No newline at end of file +:root{--system-red:#ff3b30;--system-orange:#ff9500;--system-yellow:#fc0;--system-green:#34c759;--system-teal:#5ac8fa;--system-blue:#007aff;--system-indigo:#5856d6;--system-purple:#af52de;--system-pink:#ff2d55;--system-gray:#8e8e93;--system-gray2:#aeaeb2;--system-gray3:#c7c7cc;--system-gray4:#d1d1d6;--system-gray5:#e5e5ea;--system-gray6:#f2f2f7;--label:#000;--secondary-label:#3c3c43;--tertiary-label:#48484a;--quaternary-label:#636366;--placeholder-text:#8e8e93;--link:#007aff;--separator:#e5e5ea;--opaque-separator:#c6c6c8;--system-fill:#787880;--secondary-system-fill:#787880;--tertiary-system-fill:#767680;--quaternary-system-fill:#747480;--system-background:#fff;--secondary-system-background:#f2f2f7;--tertiary-system-background:#fff;--system-grouped-background:#f2f2f7;--secondary-system-grouped-background:#fff;--tertiary-system-grouped-background:#f2f2f7}@supports (color:color(display-p3 1 1 1)){:root{--system-red:color(display-p3 1 0.2314 0.1882);--system-orange:color(display-p3 1 0.5843 0);--system-yellow:color(display-p3 1 0.8 0);--system-green:color(display-p3 0.2039 0.7804 0.349);--system-teal:color(display-p3 0.3529 0.7843 0.9804);--system-blue:color(display-p3 0 0.4784 1);--system-indigo:color(display-p3 0.3451 0.3373 0.8392);--system-purple:color(display-p3 0.6863 0.3216 0.8706);--system-pink:color(display-p3 1 0.1765 0.3333);--system-gray:color(display-p3 0.5569 0.5569 0.5765);--system-gray2:color(display-p3 0.6824 0.6824 0.698);--system-gray3:color(display-p3 0.7804 0.7804 0.8);--system-gray4:color(display-p3 0.8196 0.8196 0.8392);--system-gray5:color(display-p3 0.898 0.898 0.9176);--system-gray6:color(display-p3 0.949 0.949 0.9686);--label:color(display-p3 0 0 0);--secondary-label:color(display-p3 0.2353 0.2353 0.2627);--tertiary-label:color(display-p3 0.2823 0.2823 0.2901);--quaternary-label:color(display-p3 0.4627 0.4627 0.5019);--placeholder-text:color(display-p3 0.5568 0.5568 0.5764);--link:color(display-p3 0 0.4784 1);--separator:color(display-p3 0.898 0.898 0.9176);--opaque-separator:color(display-p3 0.7765 0.7765 0.7843);--system-fill:color(display-p3 0.4706 0.4706 0.502);--secondary-system-fill:color(display-p3 0.4706 0.4706 0.502);--tertiary-system-fill:color(display-p3 0.4627 0.4627 0.502);--quaternary-system-fill:color(display-p3 0.4549 0.4549 0.502);--system-background:color(display-p3 1 1 1);--secondary-system-background:color(display-p3 0.949 0.949 0.9686);--tertiary-system-background:color(display-p3 1 1 1);--system-grouped-background:color(display-p3 0.949 0.949 0.9686);--secondary-system-grouped-background:color(display-p3 1 1 1);--tertiary-system-grouped-background:color(display-p3 0.949 0.949 0.9686)}}:root{--large-title:600 32pt/39pt sans-serif;--title-1:600 26pt/32pt sans-serif;--title-2:600 20pt/25pt sans-serif;--title-3:500 18pt/23pt sans-serif;--headline:500 15pt/20pt sans-serif;--body:300 15pt/20pt sans-serif;--callout:300 14pt/19pt sans-serif;--subhead:300 13pt/18pt sans-serif;--footnote:300 12pt/16pt sans-serif;--caption-1:300 11pt/13pt sans-serif;--caption-2:300 11pt/13pt sans-serif;--icon-associatedtype:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23ff6682' height='90' rx='8' stroke='%23ff2d55' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M42 81.71V31.3H24.47v-13h51.06v13H58v50.41z' fill='%23fff'/%3E%3C/svg%3E");--icon-case:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%2389c5e6' height='90' rx='8' stroke='%236bb7e1' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M20.21 50c0-20.7 11.9-32.79 30.8-32.79 16 0 28.21 10.33 28.7 25.32H64.19C63.4 35 58.09 30.11 51 30.11c-8.79 0-14.37 7.52-14.37 19.82s5.54 20 14.41 20c7.08 0 12.22-4.66 13.23-12.09h15.52c-.74 15.07-12.43 25-28.78 25C32 82.81 20.21 70.72 20.21 50z' fill='%23fff'/%3E%3C/svg%3E");--icon-class:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%239b98e6' height='90' rx='8' stroke='%235856d6' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='m20.21 50c0-20.7 11.9-32.79 30.8-32.79 16 0 28.21 10.33 28.7 25.32h-15.52c-.79-7.53-6.1-12.42-13.19-12.42-8.79 0-14.37 7.52-14.37 19.82s5.54 20 14.41 20c7.08 0 12.22-4.66 13.23-12.09h15.52c-.74 15.07-12.43 25-28.78 25-19.01-.03-30.8-12.12-30.8-32.84z' fill='%23fff'/%3E%3C/svg%3E");--icon-enumeration:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23eca95b' height='90' rx='8' stroke='%23e89234' stroke-miterlimit='10' stroke-width='4' width='90' x='5.17' y='5'/%3E%3Cpath d='M71.9 81.71H28.43V18.29H71.9v13H44.56v12.62h25.71v11.87H44.56V68.7H71.9z' fill='%23fff'/%3E%3C/svg%3E");--icon-extension:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23eca95b' height='90' rx='8' stroke='%23e89234' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cg fill='%23fff'%3E%3Cpath d='M54.43 81.93H20.51V18.07h33.92v12.26H32.61v13.8h20.45v11.32H32.61v14.22h21.82zM68.74 74.58h-.27l-2.78 7.35h-7.28L64 69.32l-6-12.54h8l2.74 7.3h.27l2.76-7.3h7.64l-6.14 12.54 5.89 12.61h-7.64z'/%3E%3C/g%3E%3C/svg%3E");--icon-function:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%237ac673' height='90' rx='8' stroke='%235bb74f' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M24.25 75.66A5.47 5.47 0 0130 69.93c1.55 0 3.55.41 6.46.41 3.19 0 4.78-1.55 5.46-6.65l1.5-10.14h-9.34a6 6 0 110-12h11.1l1.09-7.27C47.82 23.39 54.28 17.7 64 17.7c6.69 0 11.74 1.77 11.74 6.64A5.47 5.47 0 0170 30.07c-1.55 0-3.55-.41-6.46-.41-3.14 0-4.73 1.51-5.46 6.65l-.78 5.27h11.44a6 6 0 11.05 12H55.6l-1.78 12.11C52.23 76.61 45.72 82.3 36 82.3c-6.7 0-11.75-1.77-11.75-6.64z' fill='%23fff'/%3E%3C/svg%3E");--icon-method:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%235a98f8' height='90' rx='8' stroke='%232974ed' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M70.61 81.71v-39.6h-.31l-15.69 39.6h-9.22l-15.65-39.6h-.35v39.6H15.2V18.29h18.63l16 41.44h.36l16-41.44H84.8v63.42z' fill='%23fff'/%3E%3C/svg%3E");--icon-operator:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%237ac673' height='90' rx='8' stroke='%235bb74f' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Ccircle fill='%23fff' cx='50' cy='50' r='16'/%3E%3C/svg%3E");--icon-property:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%2389c5e6' height='90' rx='8' stroke='%236bb7e1' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M52.31 18.29c13.62 0 22.85 8.84 22.85 22.46s-9.71 22.37-23.82 22.37H41v18.59H24.84V18.29zM41 51h7c6.85 0 10.89-3.56 10.89-10.2S54.81 30.64 48 30.64h-7z' fill='%23fff'/%3E%3C/svg%3E");--icon-protocol:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23ff6682' height='90' rx='8' stroke='%23ff2d55' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cg fill='%23fff'%3E%3Cpath d='M46.28 18.29c11.84 0 20 8.66 20 21.71s-8.44 21.71-20.6 21.71H34.87v20H22.78V18.29zM34.87 51.34H43c6.93 0 11-4 11-11.29S50 28.8 43.07 28.8h-8.2zM62 57.45h8v4.77h.16c.84-3.45 2.54-5.12 5.17-5.12a5.06 5.06 0 011.92.35V65a5.69 5.69 0 00-2.39-.51c-3.08 0-4.66 1.74-4.66 5.12v12.1H62z'/%3E%3C/g%3E%3C/svg%3E");--icon-structure:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23b57edf' height='90' rx='8' stroke='%239454c2' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M38.38 63c.74 4.53 5.62 7.16 11.82 7.16s10.37-2.81 10.37-6.68c0-3.51-2.73-5.31-10.24-6.76l-6.5-1.23C31.17 53.14 24.62 47 24.62 37.28c0-12.22 10.59-20.09 25.18-20.09 16 0 25.36 7.83 25.53 19.91h-15c-.26-4.57-4.57-7.29-10.42-7.29s-9.31 2.63-9.31 6.37c0 3.34 2.9 5.18 9.8 6.5l6.5 1.23C70.46 46.51 76.61 52 76.61 62c0 12.74-10 20.83-26.72 20.83-15.82 0-26.28-7.3-26.5-19.78z' fill='%23fff'/%3E%3C/svg%3E");--icon-typealias:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%237ac673' height='90' rx='8' stroke='%235bb74f' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M42 81.71V31.3H24.47v-13h51.06v13H58v50.41z' fill='%23fff'/%3E%3C/svg%3E");--icon-variable:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%237ac673' height='90' rx='8' stroke='%235bb74f' stroke-miterlimit='10' stroke-width='4' width='90' x='5' y='5'/%3E%3Cpath d='M39.85 81.71L19.63 18.29H38l12.18 47.64h.35L62.7 18.29h17.67L60.15 81.71z' fill='%23fff'/%3E%3C/svg%3E")}body,button,input,select,textarea{-moz-font-feature-settings:"kern";-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;direction:ltr;font-synthesis:none;text-align:left}h1:first-of-type,h2:first-of-type,h3:first-of-type,h4:first-of-type,h5:first-of-type,h6:first-of-type{margin-top:0}h1 code,h2 code,h3 code,h4 code,h5 code,h6 code{font-family:inherit;font-weight:inherit}h1 img,h2 img,h3 img,h4 img,h5 img,h6 img{margin:0 .5em .2em 0;vertical-align:middle;display:inline-block}h1+*,h2+*,h3+*,h4+*,h5+*,h6+*{margin-top:.8em}img+h1{margin-top:.5em}img+h1,img+h2,img+h3,img+h4,img+h5,img+h6{margin-top:.3em}:is(h1,h2,h3,h4,h5,h6)+:is(h1,h2,h3,h4,h5,h6){margin-top:.4em}:matches(h1,h2,h3,h4,h5,h6)+:matches(h1,h2,h3,h4,h5,h6){margin-top:.4em}:is(p,ul,ol)+:is(h1,h2,h3,h4,h5,h6){margin-top:1.6em}:matches(p,ul,ol)+:matches(h1,h2,h3,h4,h5,h6){margin-top:1.6em}:is(p,ul,ol)+*{margin-top:.8em}:matches(p,ul,ol)+*{margin-top:.8em}ol,ul{margin-left:1.17647em}:matches(ul,ol) :matches(ul,ol){margin-bottom:0;margin-top:0}nav h2{color:#3c3c43;color:var(--secondary-label);font-size:1rem;font-feature-settings:"smcp";font-variant:small-caps;font-weight:600;text-transform:uppercase}nav ol,nav ul{margin:0;list-style:none}nav li li{font-size:smaller}a:link,a:visited{text-decoration:none}a:hover{text-decoration:underline}a:active{text-decoration:none}b,strong{font-weight:600}.discussion,.summary{font:300 14pt/19pt sans-serif;font:var(--callout)}article>.discussion{margin-bottom:2em}.discussion .highlight{background:transparent;border:1px solid #e5e5ea;border:1px solid var(--separator);font:300 11pt/13pt sans-serif;font:var(--caption-1);padding:1em;text-indent:0}cite,dfn,em,i{font-style:italic}:matches(h1,h2,h3) sup{font-size:.4em}sup a{color:inherit;vertical-align:inherit}sup a:hover{color:#007aff;color:var(--link);text-decoration:none}sub{line-height:1}abbr{border:0}:lang(ja),:lang(ko),:lang(th),:lang(zh){font-style:normal}:lang(ko){word-break:keep-all}form fieldset{margin:1em auto;max-width:450px;width:95%}form label{display:block;font-size:1em;font-weight:400;line-height:1.5em;margin-bottom:14px;position:relative;width:100%}input[type=email],input[type=number],input[type=password],input[type=tel],input[type=text],input[type=url],textarea{border-radius:4px;border:1px solid #e5e5ea;border:1px solid var(--separator);color:#333;font-family:inherit;font-size:100%;font-weight:400;height:34px;margin:0;padding:0 1em;position:relative;vertical-align:top;width:100%;z-index:1}input[type=email],input [type=email]:focus,input[type=number],input [type=number]:focus,input[type=password],input [type=password]:focus,input[type=tel],input [type=tel]:focus,input[type=text],input [type=text]:focus,input[type=url],input [type=url]:focus,textarea,textarea:focus{-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=email]:focus,input[type=number]:focus,input[type=password]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=url]:focus,textarea:focus{border-color:#08c;box-shadow:0 0 0 3px rgba(0,136,204,.3);outline:0;z-index:9}input[type=email]:-moz-read-only,input[type=number]:-moz-read-only,input[type=password]:-moz-read-only,input[type=tel]:-moz-read-only,input[type=text]:-moz-read-only,input[type=url]:-moz-read-only,textarea:-moz-read-only{background:none;border:none;box-shadow:none;padding-left:0}input[type=email]:read-only,input[type=number]:read-only,input[type=password]:read-only,input[type=tel]:read-only,input[type=text]:read-only,input[type=url]:read-only,textarea:read-only{background:none;border:none;box-shadow:none;padding-left:0}::-moz-placeholder{color:#8e8e93;color:var(--placeholder-text)}:-ms-input-placeholder{color:#8e8e93;color:var(--placeholder-text)}::placeholder{color:#8e8e93;color:var(--placeholder-text)}textarea{-webkit-overflow-scrolling:touch;line-height:1.4737;min-height:134px;overflow-y:auto;resize:vertical;transform:translateZ(0)}textarea,textarea:focus{-webkit-appearance:none;-moz-appearance:none;appearance:none}select{background:transparent;border-radius:4px;border:none;cursor:pointer;font-family:inherit;font-size:1em;height:34px;margin:0;padding:0 1em;width:100%}select,select:focus{-webkit-appearance:none;-moz-appearance:none;appearance:none}select:focus{border-color:#08c;box-shadow:0 0 0 3px rgba(0,136,204,.3);outline:0;z-index:9}input[type=file]{background:#fafafa;border-radius:4px;color:#333;cursor:pointer;font-family:inherit;font-size:100%;height:34px;margin:0;padding:6px 1em;position:relative;vertical-align:top;width:100%;z-index:1}input[type=file]:focus{border-color:#08c;outline:0;box-shadow:0 0 0 3px rgba(0,136,204,.3);z-index:9}button,button:focus,input[type=file]:focus,input[type=file]:focus:focus,input[type=reset],input[type=reset]:focus,input[type=submit],input[type=submit]:focus{-webkit-appearance:none;-moz-appearance:none;appearance:none}:matches(button,input[type=reset],input[type=submit]){background-color:#e3e3e3;background:linear-gradient(#fff,#e3e3e3);border-color:#d6d6d6;color:#0070c9}:matches(button,input[type=reset],input[type=submit]):hover{background-color:#eee;background:linear-gradient(#fff,#eee);border-color:#d9d9d9}:matches(button,input[type=reset],input[type=submit]):active{background-color:#dcdcdc;background:linear-gradient(#f7f7f7,#dcdcdc);border-color:#d0d0d0}:matches(button,input[type=reset],input[type=submit]):disabled{background-color:#e3e3e3;background:linear-gradient(#fff,#e3e3e3);border-color:#d6d6d6;color:#0070c9}body{background:#f2f2f7;background:var(--system-grouped-background);color:#000;color:var(--label);font-family:ui-system,-apple-system,BlinkMacSystemFont,sans-serif;font:300 15pt/20pt sans-serif;font:var(--body)}h1{font:600 32pt/39pt sans-serif;font:var(--large-title)}h2{font:600 20pt/25pt sans-serif;font:var(--title-2)}h3{font:500 18pt/23pt sans-serif;font:var(--title-3)}h4,h5,h6{font:500 15pt/20pt sans-serif;font:var(--headline)}a{color:#007aff;color:var(--link)}label{font:300 14pt/19pt sans-serif;font:var(--callout)}input,label{display:block}input{margin-bottom:1em}hr{border:none;border-top:1px solid #e5e5ea;border-top:1px solid var(--separator);margin:1em 0}table{width:100%;font:300 11pt/13pt sans-serif;font:var(--caption-1);caption-side:bottom;margin-bottom:2em}td,th{padding:0 1em}th{font-weight:600;text-align:left}thead th{border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator)}tr:last-of-type td,tr:last-of-type th{border-bottom:none}td,th{border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator);color:#3c3c43;color:var(--secondary-label)}caption{color:#48484a;color:var(--tertiary-label);font:300 11pt/13pt sans-serif;font:var(--caption-2);margin-top:2em;text-align:left}.graph text,code{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-weight:300}.graph>polygon{display:none}.graph text{fill:currentColor!important}.graph ellipse,.graph path,.graph polygon,.graph rect{stroke:currentColor!important}body{width:90vw;max-width:1280px;margin:1em auto}body>header{font:600 26pt/32pt sans-serif;font:var(--title-1);padding:.5em 0}body>header a{color:#000;color:var(--label)}body>header span{font-weight:400}body>header sup{text-transform:uppercase;font-size:small;font-weight:300;letter-spacing:.1ch}body>footer,body>header sup{color:#3c3c43;color:var(--secondary-label)}body>footer{clear:both;padding:1em 0;font:300 11pt/13pt sans-serif;font:var(--caption-1)}@media screen and (max-width:768px){body{width:96vw;max-width:100%}body>header{font:500 18pt/23pt sans-serif;font:var(--title-3);text-align:left;padding:1em 0}body>nav{display:none}body>main{padding:0 1em}}@media screen and (max-width:768px){#relationships figure{display:none}section>[role=article][class] pre{margin-left:-1em;margin-right:-1em}section>[role=article][class] div{margin-left:-2em}}main,nav{overflow-x:auto}main{background:#fff;background:var(--system-background);border-radius:8px;padding:0 2em}main section{border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator);margin-bottom:2em;padding-bottom:1em}main section:last-of-type{border-bottom:none;margin-bottom:0}nav{float:right;margin-left:1em;max-height:100vh;overflow:auto;padding:0 1em 3em;position:sticky;top:1em;width:20vw}nav a{color:#3c3c43;color:var(--secondary-label)}nav ul a{color:#48484a;color:var(--tertiary-label)}nav ol,nav ul{padding:0}nav ul{font:300 14pt/19pt sans-serif;font:var(--callout);margin-bottom:1em}nav ol>li>a{display:block;font-size:smaller;font:500 15pt/20pt sans-serif;font:var(--headline);margin:.5em 0}nav li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}blockquote{--link:var(--secondary-label);border-left:4px solid #e5e5ea;border-left:4px solid var(--separator);color:#3c3c43;color:var(--secondary-label);font-size:smaller;margin-left:0;padding-left:2em}blockquote a{text-decoration:underline}article{padding:2em 0 1em}article>.summary{border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator);margin-bottom:2em;padding-bottom:1em}article>.summary:last-child{border-bottom:none}.parameters th{text-align:right}.parameters td{color:#3c3c43;color:var(--secondary-label)}.parameters th+td{text-align:center}dl{padding-top:1em}dt{font:500 15pt/20pt sans-serif;font:var(--headline)}dd{margin-left:2em;margin-bottom:1em}dd p{margin-top:0}.highlight{background:#f2f2f7;background:var(--secondary-system-background);border-radius:8px;font-size:.75em;margin-bottom:2em;overflow-x:auto;text-indent:-2em;padding:1em 1em 1em 3em;white-space:pre-wrap}.highlight .p{white-space:nowrap}.highlight .placeholder{color:#000;color:var(--label)}.highlight a{text-decoration:underline;color:#8e8e93;color:var(--placeholder-text)}.highlight .attribute,.highlight .keyword,.highlight .literal{color:#af52de;color:var(--system-purple)}.highlight .number{color:#007aff;color:var(--system-blue)}.highlight .declaration{color:#5ac8fa;color:var(--system-teal)}.highlight .type{color:#5856d6;color:var(--system-indigo)}.highlight .directive{color:#ff9500;color:var(--system-orange)}.highlight .comment{color:#8e8e93;color:var(--system-gray)}main summary:hover{text-decoration:underline}figure{margin:2em 0;padding:1em 0}figure svg{max-width:100%;height:auto!important;margin:0 auto;display:block}h1 small{font-size:.5em;line-height:1.5;display:block;font-weight:400;color:#636366;color:var(--quaternary-label)}h3 small{color:#48484a;color:var(--tertiary-label)}dd code,li code,p code{font-size:smaller;color:#3c3c43;color:var(--secondary-label)}a code{text-decoration:underline}dl dt[class],nav li[class],section>[role=article][class]{background-image:var(--background-image);background-size:1em;background-repeat:no-repeat;background-position:left .25em;padding-left:3em}dl dt[class]{background-position-y:.125em}section>[role=article]{margin-bottom:1em;padding-bottom:1em;border-bottom:1px solid #e5e5ea;border-bottom:1px solid var(--separator);padding-left:2em!important}section>[role=article]:last-of-type{margin-bottom:0;padding-bottom:0;border-bottom:none}dl dt[class],nav li[class]{list-style:none;text-indent:-1em;margin-bottom:.5em}nav li[class]{padding-left:2.5em}.associatedtype{--background-image:var(--icon-associatedtype);--link:var(--system-pink)}.case,.enumeration_case{--background-image:var(--icon-case);--link:var(--system-teal)}.class{--background-image:var(--icon-class);--link:var(--system-indigo)}.enumeration{--background-image:var(--icon-enumeration)}.enumeration,.extension{--link:var(--system-orange)}.extension{--background-image:var(--icon-extension)}.function{--background-image:var(--icon-function);--link:var(--system-green)}.initializer,.method{--background-image:var(--icon-method);--link:var(--system-blue)}.operator{--background-image:var(--icon-operator);--link:var(--system-green)}.property{--background-image:var(--icon-property);--link:var(--system-teal)}.protocol{--background-image:var(--icon-protocol);--link:var(--system-pink)}.structure{--background-image:var(--icon-structure);--link:var(--system-purple)}.typealias{--background-image:var(--icon-typealias)}.typealias,.variable{--link:var(--system-green)}.variable{--background-image:var(--icon-variable)}.unknown{--link:var(--quaternary-label);color:#007aff;color:var(--link)} \ No newline at end of file diff --git a/Sources/SwiftDoc/API.swift b/Sources/SwiftDoc/API.swift index dbdb7af2..46890a95 100644 --- a/Sources/SwiftDoc/API.swift +++ b/Sources/SwiftDoc/API.swift @@ -31,7 +31,11 @@ extension Enumeration.Case: API {} extension Function: API { public var name: String { - return "\(identifier)(\(signature.input.map { ($0.firstName ?? "_") + ":" }.joined()))" + if self.isOperator { + return identifier + } else { + return "\(identifier)(\(signature.input.map { ($0.firstName ?? "_") + ":" }.joined()))" + } } } diff --git a/Sources/SwiftDoc/Extensions/SwiftSemantics+Extensions.swift b/Sources/SwiftDoc/Extensions/SwiftSemantics+Extensions.swift index 54386111..98f4ad47 100644 --- a/Sources/SwiftDoc/Extensions/SwiftSemantics+Extensions.swift +++ b/Sources/SwiftDoc/Extensions/SwiftSemantics+Extensions.swift @@ -27,3 +27,18 @@ extension Structure: Type {} extension Unknown: Type { public var inheritance: [String] { return [] } } + +// MARK: - + +extension Operator.Kind: Comparable { + public static func < (lhs: Operator.Kind, rhs: Operator.Kind) -> Bool { + switch (lhs, rhs) { + case (_, .infix): + return true + case (.postfix, _): + return true + default: + return false + } + } +} diff --git a/Sources/SwiftDoc/Helpers.swift b/Sources/SwiftDoc/Helpers.swift index 7a19bb28..d23e8384 100644 --- a/Sources/SwiftDoc/Helpers.swift +++ b/Sources/SwiftDoc/Helpers.swift @@ -6,6 +6,7 @@ public func route(for symbol: Symbol) -> String { public func route(for name: CustomStringConvertible) -> String { return name.description.replacingOccurrences(of: ".", with: "_") + .replacingOccurrences(of: " ", with: "-") } public func path(for symbol: Symbol, with baseURL: String) -> String { diff --git a/Sources/SwiftDoc/Interface.swift b/Sources/SwiftDoc/Interface.swift index f68972f1..b5a0ad3a 100644 --- a/Sources/SwiftDoc/Interface.swift +++ b/Sources/SwiftDoc/Interface.swift @@ -15,7 +15,17 @@ public final class Interface { self.symbolsGroupedByIdentifier = symbolsGroupedByIdentifier self.symbolsGroupedByQualifiedName = symbolsGroupedByQualifiedName - self.topLevelSymbols = symbols.filter { $0.api is Type || $0.id.context.isEmpty } + self.topLevelSymbols = symbols.filter { symbol in + if symbol.api is Type || symbol.api is Operator { + return true + } + + if let function = symbol.api as? Function, function.isOperator { + return false + } + + return symbol.id.pathComponents.isEmpty + } self.relationships = { let extensionsByExtendedType: [String: [Extension]] = Dictionary(grouping: symbols.flatMap { $0.context.compactMap { $0 as? Extension } }, by: { $0.extendedType }) @@ -90,6 +100,20 @@ public final class Interface { return Array(relationships) }() + self.functionsByOperator = { + var functionsByOperator: [Symbol: Set] = [:] + + let functionsGroupedByName = Dictionary(grouping: symbols.filter { $0.api is Function}, + by: { $0.api.name }) + + for `operator` in symbols.filter({ $0.api is Operator }) { + let functions = functionsGroupedByName[`operator`.name] ?? [] + functionsByOperator[`operator`] = Set(functions) + } + + return functionsByOperator + }() + self.relationshipsBySubject = Dictionary(grouping: relationships, by: { $0.subject.id }) self.relationshipsByObject = Dictionary(grouping: relationships, by: { $0.object.id }) } @@ -99,6 +123,7 @@ public final class Interface { public let symbolsGroupedByIdentifier: [Symbol.ID: [Symbol]] public let symbolsGroupedByQualifiedName: [String: [Symbol]] public let topLevelSymbols: [Symbol] + public var functionsByOperator: [Symbol: Set] public var baseClasses: [Symbol] { symbols.filter { $0.api is Class && typesInherited(by: $0).isEmpty } } diff --git a/Sources/SwiftDoc/SourceFile.swift b/Sources/SwiftDoc/SourceFile.swift index f1a3da13..1a179135 100644 --- a/Sources/SwiftDoc/SourceFile.swift +++ b/Sources/SwiftDoc/SourceFile.swift @@ -168,6 +168,11 @@ public struct SourceFile: Hashable, Codable { return .skipChildren } + override func visit(_ node: OperatorDeclSyntax) -> SyntaxVisitorContinueKind { + push(symbol(Operator.self, node)) + return .skipChildren + } + override func visit(_ node: PrecedenceGroupDeclSyntax) -> SyntaxVisitorContinueKind { push(symbol(PrecedenceGroup.self, node)) return .skipChildren diff --git a/Sources/SwiftDoc/Symbol.swift b/Sources/SwiftDoc/Symbol.swift index 66e1c659..43569889 100644 --- a/Sources/SwiftDoc/Symbol.swift +++ b/Sources/SwiftDoc/Symbol.swift @@ -34,11 +34,24 @@ public final class Symbol { return api.name } + public var kind: String { + switch api { + case let function as Function where function.isOperator: + return "Operator" + default: + return String(describing: type(of: api)) + } + } + public var isPublic: Bool { if api is Unknown { return true } + if api is Operator { + return true + } + if api.modifiers.contains(where: { $0.name == "public" || $0.name == "open" }) { return true } diff --git a/Sources/swift-doc/Extensions/StringProtocol+Extensions.swift b/Sources/swift-doc/Extensions/StringProtocol+Extensions.swift index b3d8a373..bb36c526 100644 --- a/Sources/swift-doc/Extensions/StringProtocol+Extensions.swift +++ b/Sources/swift-doc/Extensions/StringProtocol+Extensions.swift @@ -1,3 +1,5 @@ +import Foundation + extension StringProtocol { func indented(by spaces: Int = 2) -> String { return String(repeating: " ", count: spaces) + self @@ -20,4 +22,30 @@ extension StringProtocol { // See: https://docs.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax#using-emoji return self.replacingOccurrences(of: ":", with: ":\u{200B}") } + + var escaped: String { + #if os(macOS) + return (CFXMLCreateStringByEscapingEntities(nil, String(self) as NSString, nil)! as NSString) as String + #else + return [ + ("&", "&"), + ("<", "<"), + (">", ">"), + ("'", "'"), + ("\"", """), + ].reduce(String(self)) { (string, element) in + string.replacingOccurrences(of: element.0, with: element.1) + } + #endif + } + + func escapingOccurrences(of target: Target, options: String.CompareOptions = [], range searchRange: Range? = nil) -> String where Target : StringProtocol { + return replacingOccurrences(of: target, with: target.escaped, options: options, range: searchRange) + } + + func escapingOccurrences(of targets: [Target], options: String.CompareOptions = []) -> String where Target : StringProtocol { + return targets.reduce(into: String(self)) { (result, target) in + result = result.escapingOccurrences(of: target, options: options) + } + } } diff --git a/Sources/swift-doc/Subcommands/Generate.swift b/Sources/swift-doc/Subcommands/Generate.swift index 04426e53..82c9ef32 100644 --- a/Sources/swift-doc/Subcommands/Generate.swift +++ b/Sources/swift-doc/Subcommands/Generate.swift @@ -75,6 +75,8 @@ extension SwiftDoc { pages[route(for: symbol)] = TypePage(module: module, symbol: symbol, baseURL: baseURL, includingChildren: symbolFilter) case let `typealias` as Typealias: pages[route(for: `typealias`.name)] = TypealiasPage(module: module, symbol: symbol, baseURL: baseURL) + case is Operator: + pages[route(for: symbol)] = OperatorPage(module: module, symbol: symbol, baseURL: baseURL) case let function as Function where !function.isOperator: globals[function.name, default: []] += [symbol] case let variable as Variable: diff --git a/Sources/swift-doc/Supporting Types/Components/Members.swift b/Sources/swift-doc/Supporting Types/Components/Members.swift index 994eca5c..95835687 100644 --- a/Sources/swift-doc/Supporting Types/Components/Members.swift +++ b/Sources/swift-doc/Supporting Types/Components/Members.swift @@ -16,6 +16,7 @@ struct Members: Component { var cases: [Symbol] var properties: [Symbol] var methods: [Symbol] + let operatorImplementations: [Symbol] var genericallyConstrainedMembers: [[GenericRequirement] : [Symbol]] let defaultImplementations: [Symbol] @@ -32,7 +33,8 @@ struct Members: Component { self.initializers = members.filter { $0.api is Initializer } self.cases = members.filter { $0.api is Enumeration.Case } self.properties = members.filter { $0.api is Variable } - self.methods = members.filter { $0.api is Function } + self.methods = members.filter { ($0.api as? Function)?.isOperator == false } + self.operatorImplementations = members.filter { ($0.api as? Function)?.isOperator == true } self.genericallyConstrainedMembers = Dictionary(grouping: members) { $0.`extension`?.genericRequirements ?? [] }.filter { !$0.key.isEmpty } self.defaultImplementations = module.interface.defaultImplementations(of: symbol).filter(symbolFilter) } @@ -44,6 +46,7 @@ struct Members: Component { ("Enumeration Cases", cases), ("Properties", properties), ("Methods", methods), + ("Operators", operatorImplementations), ("Default Implementations", defaultImplementations), ].filter { !$0.members.isEmpty } } diff --git a/Sources/swift-doc/Supporting Types/Components/OperatorImplementations.swift b/Sources/swift-doc/Supporting Types/Components/OperatorImplementations.swift new file mode 100644 index 00000000..c0040a2a --- /dev/null +++ b/Sources/swift-doc/Supporting Types/Components/OperatorImplementations.swift @@ -0,0 +1,99 @@ +import CommonMarkBuilder +import SwiftDoc +import SwiftMarkup +import SwiftSemantics +import HypertextLiteral + +struct OperatorImplementations: Component { + var symbol: Symbol + var module: Module + let baseURL: String + + var implementations: [Symbol] + + init(of symbol: Symbol, in module: Module, baseURL: String, implementations: [Symbol]) { + self.symbol = symbol + self.module = module + self.baseURL = baseURL + self.implementations = implementations + } + + + // MARK: - Component + + var fragment: Fragment { + guard !implementations.isEmpty else { return Fragment { "" } } + + return Fragment { + ForEach(in: implementations) { implementation -> BlockConvertible in + Section { + Heading { implementation.name } + + Documentation(for: implementation, in: module, baseURL: baseURL) + } + } + } + } + + var html: HypertextLiteral.HTML { + let sections = implementations.compactMap { implementation -> HypertextLiteral.HTML? in + guard let `operator` = symbol.api as? Operator, + let function = implementation.api as? Function + else { return nil } + + let heading: String + switch `operator`.kind { + case .infix: + guard function.signature.input.count == 2, + let lhs = function.signature.input.first, + let rhs = function.signature.input.last + else { + return nil + } + + heading = [lhs.type, function.name, rhs.type].compactMap { $0 }.joined(separator: " ") + case .prefix: + guard function.signature.input.count == 2, + let operand = function.signature.input.first + else { + return nil + } + heading = [function.name, operand.type].compactMap { $0 }.joined(separator: " ") + + case .postfix: + guard function.signature.input.count == 2, + let operand = function.signature.input.first + else { + return nil + } + heading = [operand.type, function.name].compactMap { $0 }.joined(separator: " ") + } + + return #""" +
+

+ \#(heading) + \#(unsafeUnescaped: function.genericWhereClause.map({ #"\#($0.escaped)"# }) ?? "") +

+ \#(Documentation(for: implementation, in: module, baseURL: baseURL).html) +
+ """# + } + + guard !sections.isEmpty else { return "" } + + return #""" +
+

Implementations

+ \#(sections) +
+ """# + } +} + +fileprivate extension Function { + var genericWhereClause: String? { + guard !genericRequirements.isEmpty else { return nil } + return "where \(genericRequirements.map { $0.description }.joined(separator: ", "))" + } +} diff --git a/Sources/swift-doc/Supporting Types/Pages/HomePage.swift b/Sources/swift-doc/Supporting Types/Pages/HomePage.swift index dc781d53..798544d3 100644 --- a/Sources/swift-doc/Supporting Types/Pages/HomePage.swift +++ b/Sources/swift-doc/Supporting Types/Pages/HomePage.swift @@ -38,8 +38,6 @@ struct HomePage: Page { globalTypealiases.append(symbol) case is Operator: operators.append(symbol) - case let function as Function where function.isOperator: - operators.append(symbol) case is Function: globalFunctions.append(symbol) case is Variable: @@ -48,6 +46,18 @@ struct HomePage: Page { continue } } + + classes.sort() + enumerations.sort() + structures.sort() + protocols.sort() + globalTypealiases.sort() + operators.sort(by: { (lhs, rhs) in + guard let lo = lhs.api as? Operator, let ro = rhs.api as? Operator else { return false } + return (lo.kind, lo.name) > (ro.kind, ro.name) + }) + globalFunctions.sort() + globalVariables.sort() } // MARK: - Page @@ -61,15 +71,15 @@ struct HomePage: Page { ForEach(in: [ ("Types", classes + enumerations + structures), ("Protocols", protocols), - ("Operators", operators), ("Global Typealiases", globalTypealiases), ("Global Functions", globalFunctions), ("Global Variables", globalVariables), + ("Operators", operators), ]) { (heading, symbols) in if (!symbols.isEmpty) { Heading { heading } - List(of: symbols.sorted()) { symbol in + List(of: symbols) { symbol in Abstract(for: symbol, baseURL: baseURL).fragment } } @@ -98,7 +108,8 @@ struct HomePage: Page { ("Protocols", protocols), ("Typealiases", globalTypealiases), ("Functions", globalFunctions), - ("Variables", globalVariables) + ("Variables", globalVariables), + ("Operators", operators), ].compactMap { (heading, symbols) -> HypertextLiteral.HTML? in guard !symbols.isEmpty else { return nil } @@ -106,7 +117,7 @@ struct HomePage: Page {

\#(heading)

- \#(symbols.sorted().map { Abstract(for: $0, baseURL: baseURL).html }) + \#(symbols.map { Abstract(for: $0, baseURL: baseURL).html })
"""# diff --git a/Sources/swift-doc/Supporting Types/Pages/OperatorPage.swift b/Sources/swift-doc/Supporting Types/Pages/OperatorPage.swift new file mode 100644 index 00000000..d8a428a2 --- /dev/null +++ b/Sources/swift-doc/Supporting Types/Pages/OperatorPage.swift @@ -0,0 +1,46 @@ +import SwiftSemantics +import SwiftDoc +import CommonMarkBuilder +import HypertextLiteral + +struct OperatorPage: Page { + let module: Module + let symbol: Symbol + let implementations: [Symbol] + let baseURL: String + + init(module: Module, symbol: Symbol, baseURL: String) { + precondition(symbol.api is Operator) + self.module = module + self.symbol = symbol + self.implementations = module.interface.functionsByOperator[symbol]?.sorted() ?? [] + self.baseURL = baseURL + } + + // MARK: - Page + + var title: String { + return symbol.id.description + } + + var document: CommonMark.Document { + return CommonMark.Document { + Heading { symbol.id.description } + + Documentation(for: symbol, in: module, baseURL: baseURL) + } + } + + var html: HypertextLiteral.HTML { + return #""" +

+ \#(symbol.kind) + \#(softbreak(symbol.id.description)) +

+ + \#(Documentation(for: symbol, in: module, baseURL: baseURL).html) + \#(OperatorImplementations(of: symbol, in: module, baseURL: baseURL, implementations: implementations).html) + """# + } +} +