From a28f9cb0bf78b2e9930d08f2816a1f1ce9abdde0 Mon Sep 17 00:00:00 2001 From: Maxime Mangel Date: Sun, 14 Jul 2024 16:01:17 +0200 Subject: [PATCH 1/7] feat: port an example of using signature for documenting the API #929 --- docs/_template.html | 10 + docs/content/fsdocs-default.css | 141 ++++- docs/content/prism/prism.css | 507 ++++++++++++++++ docs/content/prism/prism.js | 16 + .../CommentFormatter.fs | 574 ++++++++++++++++++ .../FSharp.Formatting.ApiDocs.fsproj | 3 + src/FSharp.Formatting.ApiDocs/GenerateHtml.fs | 184 +++++- .../GenerateSignature.fs | 320 ++++++++++ src/FSharp.Formatting.ApiDocs/Prelude.fs | 44 ++ src/FSharp.Formatting.Common/HtmlModel.fs | 171 ++++++ src/fsdocs-tool/Options.fs | 2 +- 11 files changed, 1952 insertions(+), 20 deletions(-) create mode 100644 docs/content/prism/prism.css create mode 100644 docs/content/prism/prism.js create mode 100644 src/FSharp.Formatting.ApiDocs/CommentFormatter.fs create mode 100644 src/FSharp.Formatting.ApiDocs/GenerateSignature.fs create mode 100644 src/FSharp.Formatting.ApiDocs/Prelude.fs diff --git a/docs/_template.html b/docs/_template.html index a49523762..b3fc71ae4 100644 --- a/docs/_template.html +++ b/docs/_template.html @@ -25,6 +25,16 @@ + + + + {{fsdocs-head-extra}} {{fsdocs-watch-script}} diff --git a/docs/content/fsdocs-default.css b/docs/content/fsdocs-default.css index 7dea22869..f811770ec 100644 --- a/docs/content/fsdocs-default.css +++ b/docs/content/fsdocs-default.css @@ -122,6 +122,7 @@ --code-preprocessor-color: #af75c1; --code-fsioutput-color: #808080; --code-tooltip-color: #d1d1d1; + } /* dark theme */ @@ -671,7 +672,10 @@ a { p { line-height: 1.8; - margin-top: var(--spacing-300); + + &:not(:last-child) { + margin-bottom: var(--spacing-300); + } } ol, ul { @@ -713,15 +717,12 @@ blockquote { /* Code snippets */ /* reset browser style */ -pre { - margin: 0; - padding: 0; -} + code, table.pre, pre { background-color: var(--code-background); color: var(--code-color); - font-family: var(--monospace-font); + font-family: var(--monospace-font); font-variant-ligatures: none; font-size: var(--font-200); -webkit-text-size-adjust: 100%; @@ -729,7 +730,7 @@ code, table.pre, pre { h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { font-size: inherit; -} +} table.pre, #content > pre.fssnip { border: 1px solid var(--code-fence-border-color); @@ -1062,20 +1063,11 @@ span[onmouseout] { flex-grow: 1; } - & pre { - margin-bottom: var(--spacing-200); - padding: var(--spacing-50); - flex-grow: 1; - overflow-x: auto; - } } } .fsdocs-summary-contents { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: flex-start; + width: 100%; } .fsdocs-member-xmldoc-column { @@ -1286,3 +1278,118 @@ dialog { opacity: 0.75; } } + + + + + +/* Code */ + +.fsdocs-api-code { + font-family: var(--monospace-font); + margin-bottom: 1rem; + + a.record-field-name, + a.union-case-property, + a.property { + /* color: darken($primary, 4%); */ + + &:hover { + text-decoration: underline; + } + } + + .property[id]:target, + a[id]:target { + animation-name: blink; + animation-direction: normal; + animation-duration: 0.75s; + animation-iteration-count: 2; + animation-timing-function: ease; + } + + span { + &.property { + color: var(--code-property-color); + } + + &.keyword { + color: var(--code-keywords-color); + } + + &.type { + color: var(--code-reference-color); + } + } + +} + +/* + Animations for blinking the target of a link + + It makes it easier to see where the link is pointing to +*/ +@keyframes blink { + 0% { + background-color: var(--primary); + color: var(--background); + } + 100% { + background-color: transparent; + color: var(--link-color); + } +} + +.docs-example:not(:last-child) { + margin-bottom: var(--spacing-300); +} + +/* + If there is parameter right after this one, add some margin. + + We don't want to do it for all of them, because the last one is followed by a `hr` which already adds spacing around it. +*/ +.fsdocs-doc-parameter { + margin-bottom: var(--spacing-300); +} + +/* +.button { + padding: .5rem .75rem; + color: var(--text-color); + cursor: pointer; + border-radius: var(--radius); + + &:has(iconify-icon) { + display: flex; + justify-content: center; + align-items: center; + } + + &:hover { + background-color: var(--shadow-color); + } +} */ + +.fsdocs-block { + position: relative; + padding: 1rem; + + &:not(:first-child) { + border-top: 1px solid var(--shadow-color); + } + + .actions-buttons { + /* Buttons are in the top right of the current block */ + position: absolute; + top: 1rem; + right: 1rem; + + /* Should be extract as an independant .buttons class when reworking the CSS */ + display: flex; + gap: .25rem; + flex-wrap: wrap; + justify-content: flex-start; + align-items: center; + } +} \ No newline at end of file diff --git a/docs/content/prism/prism.css b/docs/content/prism/prism.css new file mode 100644 index 000000000..de2dddfad --- /dev/null +++ b/docs/content/prism/prism.css @@ -0,0 +1,507 @@ +/** + * One Light theme for prism.js + * Based on Atom's One Light theme: https://github.com/atom/atom/tree/master/packages/one-light-syntax + */ + +/** + * One Light colours (accurate as of commit eb064bf on 19 Feb 2021) + * From colors.less + * --mono-1: hsl(230, 8%, 24%); + * --mono-2: hsl(230, 6%, 44%); + * --mono-3: hsl(230, 4%, 64%) + * --hue-1: hsl(198, 99%, 37%); + * --hue-2: hsl(221, 87%, 60%); + * --hue-3: hsl(301, 63%, 40%); + * --hue-4: hsl(119, 34%, 47%); + * --hue-5: hsl(5, 74%, 59%); + * --hue-5-2: hsl(344, 84%, 43%); + * --hue-6: hsl(35, 99%, 36%); + * --hue-6-2: hsl(35, 99%, 40%); + * --syntax-fg: hsl(230, 8%, 24%); + * --syntax-bg: hsl(230, 1%, 98%); + * --syntax-gutter: hsl(230, 1%, 62%); + * --syntax-guide: hsla(230, 8%, 24%, 0.2); + * --syntax-accent: hsl(230, 100%, 66%); + * From syntax-variables.less + * --syntax-selection-color: hsl(230, 1%, 90%); + * --syntax-gutter-background-color-selected: hsl(230, 1%, 90%); + * --syntax-cursor-line: hsla(230, 8%, 24%, 0.05); + */ + +code[class*="language-"], +pre[class*="language-"] { + background: hsl(230, 1%, 98%); + color: hsl(230, 8%, 24%); + font-family: "Fira Code", "Fira Mono", Menlo, Consolas, "DejaVu Sans Mono", + monospace; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + line-height: 1.5; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +/* Selection */ +code[class*="language-"]::-moz-selection, +code[class*="language-"] *::-moz-selection, +pre[class*="language-"] *::-moz-selection { + background: hsl(230, 1%, 90%); + color: inherit; +} + +code[class*="language-"]::selection, +code[class*="language-"] *::selection, +pre[class*="language-"] *::selection { + background: hsl(230, 1%, 90%); + color: inherit; +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: 0.5em 0; + overflow: auto; + border-radius: 0.3em; + border: 1px solid hsl(230, 1%, 90%); + box-shadow: 5px 5px 0px 1px hsl(230, 1%, 90%);; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + padding: 0.2em 0.3em; + border-radius: 0.3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.cdata { + color: hsl(230, 4%, 64%); +} + +.token.doctype, +.token.punctuation, +.token.entity { + color: hsl(230, 8%, 24%); +} + +.token.attr-name, +.token.class-name, +.token.boolean, +.token.constant, +.token.number, +.token.atrule { + color: hsl(35, 99%, 36%); +} + +.token.keyword { + color: hsl(301, 63%, 40%); +} + +.token.property, +.token.tag, +.token.symbol, +.token.deleted, +.token.important { + color: hsl(5, 74%, 59%); +} + +.token.selector, +.token.string, +.token.char, +.token.builtin, +.token.inserted, +.token.regex, +.token.attr-value, +.token.attr-value > .token.punctuation { + color: hsl(119, 34%, 47%); +} + +.token.variable, +.token.operator, +.token.function { + color: hsl(221, 87%, 60%); +} + +.token.url { + color: hsl(198, 99%, 37%); +} + +/* HTML overrides */ +.token.attr-value > .token.punctuation.attr-equals, +.token.special-attr > .token.attr-value > .token.value.css { + color: hsl(230, 8%, 24%); +} + +/* CSS overrides */ +.language-css .token.selector { + color: hsl(5, 74%, 59%); +} + +.language-css .token.property { + color: hsl(230, 8%, 24%); +} + +.language-css .token.function, +.language-css .token.url > .token.function { + color: hsl(198, 99%, 37%); +} + +.language-css .token.url > .token.string.url { + color: hsl(119, 34%, 47%); +} + +.language-css .token.important, +.language-css .token.atrule .token.rule { + color: hsl(301, 63%, 40%); +} + +/* JS overrides */ +.language-javascript .token.operator { + color: hsl(301, 63%, 40%); +} + +.language-javascript + .token.template-string + > .token.interpolation + > .token.interpolation-punctuation.punctuation { + color: hsl(344, 84%, 43%); +} + +/* JSON overrides */ +.language-json .token.operator { + color: hsl(230, 8%, 24%); +} + +.language-json .token.null.keyword { + color: hsl(35, 99%, 36%); +} + +/* MD overrides */ +.language-markdown .token.url, +.language-markdown .token.url > .token.operator, +.language-markdown .token.url-reference.url > .token.string { + color: hsl(230, 8%, 24%); +} + +.language-markdown .token.url > .token.content { + color: hsl(221, 87%, 60%); +} + +.language-markdown .token.url > .token.url, +.language-markdown .token.url-reference.url { + color: hsl(198, 99%, 37%); +} + +.language-markdown .token.blockquote.punctuation, +.language-markdown .token.hr.punctuation { + color: hsl(230, 4%, 64%); + font-style: italic; +} + +.language-markdown .token.code-snippet { + color: hsl(119, 34%, 47%); +} + +.language-markdown .token.bold .token.content { + color: hsl(35, 99%, 36%); +} + +.language-markdown .token.italic .token.content { + color: hsl(301, 63%, 40%); +} + +.language-markdown .token.strike .token.content, +.language-markdown .token.strike .token.punctuation, +.language-markdown .token.list.punctuation, +.language-markdown .token.title.important > .token.punctuation { + color: hsl(5, 74%, 59%); +} + +/* General */ +.token.bold { + font-weight: bold; +} + +.token.comment, +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +.token.namespace { + opacity: 0.8; +} + +/* Plugin overrides */ +/* Selectors should have higher specificity than those in the plugins' default stylesheets */ + +/* Show Invisibles plugin overrides */ +.token.token.tab:not(:empty):before, +.token.token.cr:before, +.token.token.lf:before, +.token.token.space:before { + color: hsla(230, 8%, 24%, 0.2); +} + +/* Toolbar plugin overrides */ +/* Space out all buttons and move them away from the right edge of the code block */ +div.code-toolbar > .toolbar.toolbar > .toolbar-item { + &:not(:last-child) { + margin-right: 0.5rem; + } +} + +/* Styling the buttons */ +div.code-toolbar > .toolbar.toolbar > .toolbar-item > button, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > a, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > span { + background: hsl(230, 1%, 90%); + color: hsl(230, 6%, 44%); + padding: 0.5rem; + border-radius: 0.3rem; +} + +div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus { + background: hsl(230, 1%, 78%); /* custom: darken(--syntax-bg, 20%) */ + color: hsl(230, 8%, 24%); + cursor: pointer; +} + +/* Line Highlight plugin overrides */ +/* The highlighted line itself */ +.line-highlight.line-highlight { + background: hsla(230, 8%, 24%, 0.05); +} + +/* Default line numbers in Line Highlight plugin */ +.line-highlight.line-highlight:before, +.line-highlight.line-highlight[data-end]:after { + background: hsl(230, 1%, 90%); + color: hsl(230, 8%, 24%); + padding: 0.1em 0.6em; + border-radius: 0.3em; + box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); /* same as Toolbar plugin default */ +} + +/* Hovering over a linkable line number (in the gutter area) */ +/* Requires Line Numbers plugin as well */ +pre[id].linkable-line-numbers.linkable-line-numbers + span.line-numbers-rows + > span:hover:before { + background-color: hsla(230, 8%, 24%, 0.05); +} + +/* Line Numbers and Command Line plugins overrides */ +/* Line separating gutter from coding area */ +.line-numbers.line-numbers .line-numbers-rows, +.command-line .command-line-prompt { + border-right-color: hsla(230, 8%, 24%, 0.2); +} + +/* Stuff in the gutter */ +.line-numbers .line-numbers-rows > span:before, +.command-line .command-line-prompt > span:before { + color: hsl(230, 1%, 62%); +} + +/* Match Braces plugin overrides */ +/* Note: Outline colour is inherited from the braces */ +.rainbow-braces .token.token.punctuation.brace-level-1, +.rainbow-braces .token.token.punctuation.brace-level-5, +.rainbow-braces .token.token.punctuation.brace-level-9 { + color: hsl(5, 74%, 59%); +} + +.rainbow-braces .token.token.punctuation.brace-level-2, +.rainbow-braces .token.token.punctuation.brace-level-6, +.rainbow-braces .token.token.punctuation.brace-level-10 { + color: hsl(119, 34%, 47%); +} + +.rainbow-braces .token.token.punctuation.brace-level-3, +.rainbow-braces .token.token.punctuation.brace-level-7, +.rainbow-braces .token.token.punctuation.brace-level-11 { + color: hsl(221, 87%, 60%); +} + +.rainbow-braces .token.token.punctuation.brace-level-4, +.rainbow-braces .token.token.punctuation.brace-level-8, +.rainbow-braces .token.token.punctuation.brace-level-12 { + color: hsl(301, 63%, 40%); +} + +/* Diff Highlight plugin overrides */ +/* Taken from https://github.com/atom/github/blob/master/styles/variables.less */ +pre.diff-highlight > code .token.token.deleted:not(.prefix), +pre > code.diff-highlight .token.token.deleted:not(.prefix) { + background-color: hsla(353, 100%, 66%, 0.15); +} + +pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection, +pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection, +pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection, +pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection { + background-color: hsla(353, 95%, 66%, 0.25); +} + +pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection, +pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection, +pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection, +pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection { + background-color: hsla(353, 95%, 66%, 0.25); +} + +pre.diff-highlight > code .token.token.inserted:not(.prefix), +pre > code.diff-highlight .token.token.inserted:not(.prefix) { + background-color: hsla(137, 100%, 55%, 0.15); +} + +pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection, +pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection, +pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection, +pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection { + background-color: hsla(135, 73%, 55%, 0.25); +} + +pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection, +pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection, +pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection, +pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection { + background-color: hsla(135, 73%, 55%, 0.25); +} + +/* Previewers plugin overrides */ +/* Based on https://github.com/atom-community/atom-ide-datatip/blob/master/styles/atom-ide-datatips.less and https://github.com/atom/atom/blob/master/packages/one-light-ui */ +/* Border around popup */ +.prism-previewer.prism-previewer:before, +.prism-previewer-gradient.prism-previewer-gradient div { + border-color: hsl(0, 0, 95%); +} + +/* Angle and time should remain as circles and are hence not included */ +.prism-previewer-color.prism-previewer-color:before, +.prism-previewer-gradient.prism-previewer-gradient div, +.prism-previewer-easing.prism-previewer-easing:before { + border-radius: 0.3em; +} + +/* Triangles pointing to the code */ +.prism-previewer.prism-previewer:after { + border-top-color: hsl(0, 0, 95%); +} + +.prism-previewer-flipped.prism-previewer-flipped.after { + border-bottom-color: hsl(0, 0, 95%); +} + +/* Background colour within the popup */ +.prism-previewer-angle.prism-previewer-angle:before, +.prism-previewer-time.prism-previewer-time:before, +.prism-previewer-easing.prism-previewer-easing { + background: hsl(0, 0%, 100%); +} + +/* For angle, this is the positive area (eg. 90deg will display one quadrant in this colour) */ +/* For time, this is the alternate colour */ +.prism-previewer-angle.prism-previewer-angle circle, +.prism-previewer-time.prism-previewer-time circle { + stroke: hsl(230, 8%, 24%); + stroke-opacity: 1; +} + +/* Stroke colours of the handle, direction point, and vector itself */ +.prism-previewer-easing.prism-previewer-easing circle, +.prism-previewer-easing.prism-previewer-easing path, +.prism-previewer-easing.prism-previewer-easing line { + stroke: hsl(230, 8%, 24%); +} + +/* Fill colour of the handle */ +.prism-previewer-easing.prism-previewer-easing circle { + fill: transparent; +} + +/* Prism toolbar */ + +div.code-toolbar { + position: relative; +} + +div.code-toolbar > .toolbar { + position: absolute; + z-index: 10; + top: 1em; + right: 1em; + transition: opacity 0.3s ease-in-out; + opacity: 0; +} + +div.code-toolbar:hover > .toolbar { + opacity: 1; +} + +/* Separate line b/c rules are thrown out if selector is invalid. + IE11 and old Edge versions don't support :focus-within. */ +div.code-toolbar:focus-within > .toolbar { + opacity: 1; +} + +div.code-toolbar > .toolbar > .toolbar-item { + display: inline-block; +} + +div.code-toolbar > .toolbar > .toolbar-item > a { + cursor: pointer; +} + +div.code-toolbar > .toolbar > .toolbar-item > button { + background: none; + border: 0; + color: inherit; + font: inherit; + line-height: normal; + overflow: visible; + padding: 0; + -webkit-user-select: none; /* for button */ + -moz-user-select: none; + -ms-user-select: none; +} + +div.code-toolbar > .toolbar > .toolbar-item > a, +div.code-toolbar > .toolbar > .toolbar-item > button, +div.code-toolbar > .toolbar > .toolbar-item > span { + color: #bbb; + font-size: .8em; + padding: 0 .5em; + background: #f5f2f0; + background: rgba(224, 224, 224, 0.2); + box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); + border-radius: .5em; +} + +div.code-toolbar > .toolbar > .toolbar-item > a:hover, +div.code-toolbar > .toolbar > .toolbar-item > a:focus, +div.code-toolbar > .toolbar > .toolbar-item > button:hover, +div.code-toolbar > .toolbar > .toolbar-item > button:focus, +div.code-toolbar > .toolbar > .toolbar-item > span:hover, +div.code-toolbar > .toolbar > .toolbar-item > span:focus { + color: inherit; + text-decoration: none; +} diff --git a/docs/content/prism/prism.js b/docs/content/prism/prism.js new file mode 100644 index 000000000..3809d6ee8 --- /dev/null +++ b/docs/content/prism/prism.js @@ -0,0 +1,16 @@ +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+dart+fsharp+python+rust&plugins=line-highlight+line-numbers+custom-class+toolbar+copy-to-clipboard */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; +!function(e){var a=[/\b(?:async|sync|yield)\*/,/\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extends|extension|external|factory|final|finally|for|get|hide|if|implements|import|in|interface|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/],n="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp(n+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}}}};e.languages.dart=e.languages.extend("clike",{"class-name":[s,{pattern:RegExp(n+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()])"),lookbehind:!0,inside:s.inside}],keyword:a,operator:/\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/}),e.languages.insertBefore("dart","string",{"string-literal":{pattern:/r?(?:("""|''')[\s\S]*?\1|(["'])(?:\\.|(?!\2)[^\\\r\n])*\2(?!\2))/,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:\w+|\{(?:[^{}]|\{[^{}]*\})*\})/,lookbehind:!0,inside:{punctuation:/^\$\{?|\}$/,expression:{pattern:/[\s\S]+/,inside:e.languages.dart}}},string:/[\s\S]+/}},string:void 0}),e.languages.insertBefore("dart","class-name",{metadata:{pattern:/@\w+/,alias:"function"}}),e.languages.insertBefore("dart","class-name",{generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":s,keyword:a,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(Prism); +Prism.languages.fsharp=Prism.languages.extend("clike",{comment:[{pattern:/(^|[^\\])\(\*(?!\))[\s\S]*?\*\)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(?:"""[\s\S]*?"""|@"(?:""|[^"])*"|"(?:\\[\s\S]|[^\\"])*")B?/,greedy:!0},"class-name":{pattern:/(\b(?:exception|inherit|interface|new|of|type)\s+|\w\s*:\s*|\s:\??>\s*)[.\w]+\b(?:\s*(?:->|\*)\s*[.\w]+\b)*(?!\s*[:.])/,lookbehind:!0,inside:{operator:/->|\*/,punctuation:/\./}},keyword:/\b(?:let|return|use|yield)(?:!\B|\b)|\b(?:abstract|and|as|asr|assert|atomic|base|begin|break|checked|class|component|const|constraint|constructor|continue|default|delegate|do|done|downcast|downto|eager|elif|else|end|event|exception|extern|external|false|finally|fixed|for|fun|function|functor|global|if|in|include|inherit|inline|interface|internal|land|lazy|lor|lsl|lsr|lxor|match|member|method|mixin|mod|module|mutable|namespace|new|not|null|object|of|open|or|override|parallel|private|process|protected|public|pure|rec|sealed|select|sig|static|struct|tailcall|then|to|trait|true|try|type|upcast|val|virtual|void|volatile|when|while|with)\b/,number:[/\b0x[\da-fA-F]+(?:LF|lf|un)?\b/,/\b0b[01]+(?:uy|y)?\b/,/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[fm]|e[+-]?\d+)?\b/i,/\b\d+(?:[IlLsy]|UL|u[lsy]?)?\b/],operator:/([<>~&^])\1\1|([*.:<>&])\2|<-|->|[!=:]=|?|\??(?:<=|>=|<>|[-+*/%=<>])\??|[!?^&]|~[+~-]|:>|:\?>?/}),Prism.languages.insertBefore("fsharp","keyword",{preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(^#)\b(?:else|endif|if|light|line|nowarn)\b/,lookbehind:!0,alias:"keyword"}}}}),Prism.languages.insertBefore("fsharp","punctuation",{"computation-expression":{pattern:/\b[_a-z]\w*(?=\s*\{)/i,alias:"keyword"}}),Prism.languages.insertBefore("fsharp","string",{annotation:{pattern:/\[<.+?>\]/,greedy:!0,inside:{punctuation:/^\[<|>\]$/,"class-name":{pattern:/^\w+$|(^|;\s*)[A-Z]\w*(?=\()/,lookbehind:!0},"annotation-content":{pattern:/[\s\S]+/,inside:Prism.languages.fsharp}}},char:{pattern:/'(?:[^\\']|\\(?:.|\d{3}|x[a-fA-F\d]{2}|u[a-fA-F\d]{4}|U[a-fA-F\d]{8}))'B?/,greedy:!0}}); +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; +!function(e){for(var a="/\\*(?:[^*/]|\\*(?!/)|/(?!\\*)|)*\\*/",t=0;t<2;t++)a=a.replace(//g,(function(){return a}));a=a.replace(//g,(function(){return"[^\\s\\S]"})),e.languages.rust={comment:[{pattern:RegExp("(^|[^\\\\])"+a),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism); +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document&&document.querySelector){var e,t="line-numbers",i="linkable-line-numbers",n=/\n(?!$)/g,r=!0;Prism.plugins.lineHighlight={highlightLines:function(o,u,c){var h=(u="string"==typeof u?u:o.getAttribute("data-line")||"").replace(/\s+/g,"").split(",").filter(Boolean),d=+o.getAttribute("data-line-offset")||0,f=(function(){if(void 0===e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding="0",t.style.border="0",t.innerHTML=" 
 ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}()?parseInt:parseFloat)(getComputedStyle(o).lineHeight),p=Prism.util.isActive(o,t),g=o.querySelector("code"),m=p?o:g||o,v=[],y=g.textContent.match(n),b=y?y.length+1:1,A=g&&m!=g?function(e,t){var i=getComputedStyle(e),n=getComputedStyle(t);function r(e){return+e.substr(0,e.length-2)}return t.offsetTop+r(n.borderTopWidth)+r(n.paddingTop)-r(i.paddingTop)}(o,g):0;h.forEach((function(e){var t=e.split("-"),i=+t[0],n=+t[1]||i;if(!((n=Math.min(b+d,n))i&&r.setAttribute("data-end",String(n)),r.style.top=(i-d-1)*f+A+"px",r.textContent=new Array(n-i+2).join(" \n")}));v.push((function(){r.style.width=o.scrollWidth+"px"})),v.push((function(){m.appendChild(r)}))}}));var P=o.id;if(p&&Prism.util.isActive(o,i)&&P){l(o,i)||v.push((function(){o.classList.add(i)}));var E=parseInt(o.getAttribute("data-start")||"1");s(".line-numbers-rows > span",o).forEach((function(e,t){var i=t+E;e.onclick=function(){var e=P+"."+i;r=!1,location.hash=e,setTimeout((function(){r=!0}),1)}}))}return function(){v.forEach(a)}}};var o=0;Prism.hooks.add("before-sanity-check",(function(e){var t=e.element.parentElement;if(u(t)){var i=0;s(".line-highlight",t).forEach((function(e){i+=e.textContent.length,e.parentNode.removeChild(e)})),i&&/^(?: \n)+$/.test(e.code.slice(-i))&&(e.code=e.code.slice(0,-i))}})),Prism.hooks.add("complete",(function e(i){var n=i.element.parentElement;if(u(n)){clearTimeout(o);var r=Prism.plugins.lineNumbers,s=i.plugins&&i.plugins.lineNumbers;l(n,t)&&r&&!s?Prism.hooks.add("line-numbers",e):(Prism.plugins.lineHighlight.highlightLines(n)(),o=setTimeout(c,1))}})),window.addEventListener("hashchange",c),window.addEventListener("resize",(function(){s("pre").filter(u).map((function(e){return Prism.plugins.lineHighlight.highlightLines(e)})).forEach(a)}))}function s(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function l(e,t){return e.classList.contains(t)}function a(e){e()}function u(e){return!!(e&&/pre/i.test(e.nodeName)&&(e.hasAttribute("data-line")||e.id&&Prism.util.isActive(e,i)))}function c(){var e=location.hash.slice(1);s(".temporary.line-highlight").forEach((function(e){e.parentNode.removeChild(e)}));var t=(e.match(/\.([\d,-]+)$/)||[,""])[1];if(t&&!document.getElementById(e)){var i=e.slice(0,e.lastIndexOf(".")),n=document.getElementById(i);n&&(n.hasAttribute("data-line")||n.setAttribute("data-line",""),Prism.plugins.lineHighlight.highlightLines(n,t,"temporary ")(),r&&document.querySelector(".temporary.line-highlight").scrollIntoView())}}}(); +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var e="line-numbers",n=/\n(?!$)/g,t=Prism.plugins.lineNumbers={getLine:function(n,t){if("PRE"===n.tagName&&n.classList.contains(e)){var i=n.querySelector(".line-numbers-rows");if(i){var r=parseInt(n.getAttribute("data-start"),10)||1,s=r+(i.children.length-1);ts&&(t=s);var l=t-r;return i.children[l]}}},resize:function(e){r([e])},assumeViewportIndependence:!0},i=void 0;window.addEventListener("resize",(function(){t.assumeViewportIndependence&&i===window.innerWidth||(i=window.innerWidth,r(Array.prototype.slice.call(document.querySelectorAll("pre.line-numbers"))))})),Prism.hooks.add("complete",(function(t){if(t.code){var i=t.element,s=i.parentNode;if(s&&/pre/i.test(s.nodeName)&&!i.querySelector(".line-numbers-rows")&&Prism.util.isActive(i,e)){i.classList.remove(e),s.classList.add(e);var l,o=t.code.match(n),a=o?o.length+1:1,u=new Array(a+1).join("");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=u,s.hasAttribute("data-start")&&(s.style.counterReset="linenumber "+(parseInt(s.getAttribute("data-start"),10)-1)),t.element.appendChild(l),r([s]),Prism.hooks.run("line-numbers",t)}}})),Prism.hooks.add("line-numbers",(function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}))}function r(e){if(0!=(e=e.filter((function(e){var n,t=(n=e,n?window.getComputedStyle?getComputedStyle(n):n.currentStyle||null:null)["white-space"];return"pre-wrap"===t||"pre-line"===t}))).length){var t=e.map((function(e){var t=e.querySelector("code"),i=e.querySelector(".line-numbers-rows");if(t&&i){var r=e.querySelector(".line-numbers-sizer"),s=t.textContent.split(n);r||((r=document.createElement("span")).className="line-numbers-sizer",t.appendChild(r)),r.innerHTML="0",r.style.display="block";var l=r.getBoundingClientRect().height;return r.innerHTML="",{element:e,lines:s,lineHeights:[],oneLinerHeight:l,sizer:r}}})).filter(Boolean);t.forEach((function(e){var n=e.sizer,t=e.lines,i=e.lineHeights,r=e.oneLinerHeight;i[t.length-1]=void 0,t.forEach((function(e,t){if(e&&e.length>1){var s=n.appendChild(document.createElement("span"));s.style.display="block",s.textContent=e}else i[t]=r}))})),t.forEach((function(e){for(var n=e.sizer,t=e.lineHeights,i=0,r=0;r = "\n" + +let private tagPattern (tagName: string) = + sprintf + """(?'void_element'<%s(?'void_attributes'\s+[^\/>]+)?\/>)|(?'non_void_element'<%s(?'non_void_attributes'\s+[^>]+)?>(?'non_void_innerText'(?:(?!<%s>)(?!<\/%s>)[\s\S])*)<\/%s\s*>)""" + tagName + tagName + tagName + tagName + tagName + +type private TagInfo = + | VoidElement of attributes: Map + | NonVoidElement of innerText: string * attributes: Map + +[] +type private FormatterInfo = + { TagName: string + Formatter: TagInfo -> string option } + +let private extractTextFromQuote (quotedText: string) = + quotedText.Substring(1, quotedText.Length - 2) + +let private extractMemberText (text: string) = + let pattern = "(?'member_type'[a-z]{1}:)?(?'member_text'.*)" + let m = Regex.Match(text, pattern, RegexOptions.IgnoreCase) + + if m.Groups.["member_text"].Success then + m.Groups.["member_text"].Value + else + text + +let private getAttributes (attributes: Group) = + if attributes.Success then + let pattern = """(?'key'\S+)=(?'value''[^']*'|"[^"]*")""" + + Regex.Matches(attributes.Value, pattern, RegexOptions.IgnoreCase) + |> Seq.cast + |> Seq.map (fun m -> m.Groups.["key"].Value, extractTextFromQuote m.Groups.["value"].Value) + |> Map.ofSeq + else + Map.empty + +let rec private applyFormatter (info: FormatterInfo) text = + let pattern = tagPattern info.TagName + + match Regex.Match(text, pattern, RegexOptions.IgnoreCase) with + | m when m.Success -> + if m.Groups.["void_element"].Success then + let attributes = getAttributes m.Groups.["void_attributes"] + + let replacement = VoidElement attributes |> info.Formatter + + match replacement with + | Some replacement -> + text.Replace(m.Groups.["void_element"].Value, replacement) + // Re-apply the formatter, because perhaps there is more + // of the current tag to convert + |> applyFormatter info + + | None -> + // The formatter wasn't able to convert the tag + // Return as it is and don't re-apply the formatter + // otherwise it will create an infinity loop + text + + else if m.Groups.["non_void_element"].Success then + let innerText = m.Groups.["non_void_innerText"].Value + let attributes = getAttributes m.Groups.["non_void_attributes"] + + let replacement = NonVoidElement(innerText, attributes) |> info.Formatter + + match replacement with + | Some replacement -> + // Re-apply the formatter, because perhaps there is more + // of the current tag to convert + text.Replace(m.Groups.["non_void_element"].Value, replacement) + |> applyFormatter info + + | None -> + // The formatter wasn't able to convert the tag + // Return as it is and don't re-apply the formatter + // otherwise it will create an infinity loop + text + else + // Should not happend but like that we are sure to handle all possible cases + text + | _ -> text + +let private codeBlock = + { TagName = "code" + Formatter = + function + | VoidElement _ -> None + + | NonVoidElement(innerText, attributes) -> + let lang = + match Map.tryFind "lang" attributes with + | Some lang -> lang + + | None -> "" + + let formattedText = + if innerText.StartsWith("\n") then + + sprintf "```%s%s```" lang innerText + else + sprintf "```%s\n%s```" lang innerText + + newLine + formattedText + newLine |> Some + + } + |> applyFormatter + +let private codeInline = + { TagName = "c" + Formatter = + function + | VoidElement _ -> None + | NonVoidElement(innerText, _) -> "" + innerText + "" |> Some } + |> applyFormatter + +let private paragraph = + { TagName = "para" + Formatter = + function + | VoidElement _ -> None + + | NonVoidElement(innerText, _) -> "

" + innerText + "

" |> Some } + |> applyFormatter + +let private block = + { TagName = "block" + Formatter = + function + | VoidElement _ -> None + + | NonVoidElement(innerText, _) -> newLine + innerText + newLine |> Some } + |> applyFormatter + +let private see = + let getCRef (attributes: Map) = Map.tryFind "cref" attributes + + let getHref (attributes: Map) = Map.tryFind "href" attributes + + { TagName = "see" + Formatter = + function + | VoidElement attributes -> + match getCRef attributes with + | Some cref -> + // TODO: Add config to generates command + "" + extractMemberText cref + "" |> Some + + | None -> None + + | NonVoidElement(innerText, attributes) -> + if String.IsNullOrWhiteSpace innerText then + match getCRef attributes with + | Some cref -> + // TODO: Add config to generates command + "" + extractMemberText cref + "" |> Some + + | None -> None + else + match getHref attributes with + | Some href -> sprintf "[%s](%s)" innerText href |> Some + + | None -> "" + innerText + "" |> Some } + |> applyFormatter + +let private paramRef = + let getName (attributes: Map) = Map.tryFind "name" attributes + + { TagName = "paramref" + Formatter = + function + | VoidElement attributes -> + match getName attributes with + | Some name -> "" + name + "" |> Some + + | None -> None + + | NonVoidElement(innerText, attributes) -> None + + } + |> applyFormatter + +let private typeParamRef = + let getName (attributes: Map) = Map.tryFind "name" attributes + + { TagName = "typeparamref" + Formatter = + function + | VoidElement attributes -> + match getName attributes with + | Some name -> "" + name + "" |> Some + + | None -> None + + | NonVoidElement(innerText, attributes) -> None } + |> applyFormatter + +type private Term = string +type private Definition = string + +type private ListStyle = + | Bulleted + | Numbered + | Tablered + +/// ItemList allow a permissive representation of an Item. +/// In theory, TermOnly should not exist but we added it so part of the documentation doesn't disappear +/// TODO: Allow direct text support without and tags +type private ItemList = + /// A list where the items are just contains in a element + | DescriptionOnly of string + /// A list where the items are just contains in a element + | TermOnly of string + /// A list where the items are a term followed by a definition (ie in markdown: * - ) + | Definitions of Term * Definition + +let private itemListToStringAsMarkdownList (item: ItemList) = + match item with + | DescriptionOnly description -> description + | TermOnly term -> "" + term + "" + | Definitions(term, description) -> "" + term + " - " + description + +let private list = + let getType (attributes: Map) = Map.tryFind "type" attributes + + let tryGetInnerTextOnNonVoidElement (text: string) (tagName: string) = + match Regex.Match(text, tagPattern tagName, RegexOptions.IgnoreCase) with + | m when m.Success -> + if m.Groups.["non_void_element"].Success then + Some m.Groups.["non_void_innerText"].Value + else + None + | _ -> None + + let tryGetNonVoidElement (text: string) (tagName: string) = + match Regex.Match(text, tagPattern tagName, RegexOptions.IgnoreCase) with + | m when m.Success -> + if m.Groups.["non_void_element"].Success then + Some(m.Groups.["non_void_element"].Value, m.Groups.["non_void_innerText"].Value) + else + None + | _ -> None + + let tryGetDescription (text: string) = + tryGetInnerTextOnNonVoidElement text "description" + + let tryGetTerm (text: string) = + tryGetInnerTextOnNonVoidElement text "term" + + let rec extractItemList (res: ItemList list) (text: string) = + match Regex.Match(text, tagPattern "item", RegexOptions.IgnoreCase) with + | m when m.Success -> + let newText = text.Substring(m.Value.Length) + + if m.Groups.["non_void_element"].Success then + let innerText = m.Groups.["non_void_innerText"].Value + let description = tryGetDescription innerText + let term = tryGetTerm innerText + + let currentItem: ItemList option = + match description, term with + | Some description, Some term -> Definitions(term, description) |> Some + | Some description, None -> DescriptionOnly description |> Some + | None, Some term -> TermOnly term |> Some + | None, None -> None + + match currentItem with + | Some currentItem -> extractItemList (res @ [ currentItem ]) newText + | None -> extractItemList res newText + else + extractItemList res newText + | _ -> res + + let rec extractColumnHeader (res: string list) (text: string) = + match Regex.Match(text, tagPattern "listheader", RegexOptions.IgnoreCase) with + | m when m.Success -> + let newText = text.Substring(m.Value.Length) + + if m.Groups.["non_void_element"].Success then + let innerText = m.Groups.["non_void_innerText"].Value + + let rec extractAllTerms (res: string list) (text: string) = + match tryGetNonVoidElement text "term" with + | Some(fullString, innerText) -> + let escapedRegex = Regex(Regex.Escape(fullString)) + let newText = escapedRegex.Replace(text, "", 1) + extractAllTerms (res @ [ innerText ]) newText + | None -> res + + extractColumnHeader (extractAllTerms [] innerText) newText + else + extractColumnHeader res newText + | _ -> res + + let rec extractRowsForTable (res: (string list) list) (text: string) = + match Regex.Match(text, tagPattern "item", RegexOptions.IgnoreCase) with + | m when m.Success -> + let newText = text.Substring(m.Value.Length) + + if m.Groups.["non_void_element"].Success then + let innerText = m.Groups.["non_void_innerText"].Value + + let rec extractAllTerms (res: string list) (text: string) = + match tryGetNonVoidElement text "term" with + | Some(fullString, innerText) -> + let escapedRegex = Regex(Regex.Escape(fullString)) + let newText = escapedRegex.Replace(text, "", 1) + extractAllTerms (res @ [ innerText ]) newText + | None -> res + + extractRowsForTable (res @ [ extractAllTerms [] innerText ]) newText + else + extractRowsForTable res newText + | _ -> res + + { TagName = "list" + Formatter = + function + | VoidElement _ -> None + + | NonVoidElement(innerText, attributes) -> + let listStyle = + match getType attributes with + | Some "bullet" -> Bulleted + | Some "number" -> Numbered + | Some "table" -> Tablered + | Some _ + | None -> Bulleted + + match listStyle with + | Bulleted -> + let items = + extractItemList [] innerText + |> List.map (fun item -> "
  • " + itemListToStringAsMarkdownList item + "
  • ") + |> String.concat newLine + + "
      " + newLine + items + newLine + "
    " + + | Numbered -> + let items = + extractItemList [] innerText + |> List.map (fun item -> "
  • " + itemListToStringAsMarkdownList item + "
  • ") + |> String.concat newLine + + "
      " + newLine + items + newLine + "
    " + + | Tablered -> + let columnHeaders = extractColumnHeader [] innerText + let rows = extractRowsForTable [] innerText + + let columnHeadersText = + columnHeaders + |> List.mapi (fun index header -> "" + header + "") + |> String.concat "" + + let itemsText = + rows + |> List.map (fun columns -> + let rowContent = + columns + |> List.mapi (fun index column -> "" + column + "") + |> String.concat newLine + + "" + newLine + rowContent + newLine + "") + |> String.concat newLine + + "" + + newLine + + "" + + newLine + + columnHeadersText + + newLine + + "" + + newLine + + "" + + newLine + + itemsText + + newLine + + "" + + newLine + + "
    " + |> Some } + |> applyFormatter + +/// +/// Unescape XML special characters +/// +/// For example, this allows to print '>' in the tooltip instead of '>' +/// +let private unescapeSpecialCharacters (text: string) = + text + .Replace("<", "<") + .Replace(">", ">") + .Replace(""", "\"") + .Replace("'", "'") + .Replace("&", "&") + +let private summary = + { TagName = "summary" + Formatter = + function + | VoidElement _ -> None + + | NonVoidElement(innerText, _) -> + """
    """ + newLine + innerText + newLine + "
    " + |> Some + + } + |> applyFormatter + +let private example = + { TagName = "example" + Formatter = + function + | VoidElement _ -> None + + | NonVoidElement(innerText, _) -> + newLine + + """
    """ + + newLine + + """

    Example

    """ + + newLine + + innerText + + newLine + + "
    " + + newLine + + newLine + |> Some + + } + |> applyFormatter + +let private removeSummaryTag = + { TagName = "summary" + Formatter = + function + | VoidElement _ -> None + + | NonVoidElement(innerText, _) -> innerText |> Some + + } + |> applyFormatter + +let private removeParamElement = + { TagName = "param" + Formatter = + function + | VoidElement _ -> None + + | NonVoidElement(_, _) -> + // Returning an empty string will completely remove the element + Some "" + + } + |> applyFormatter + +let private removeRemarkTag = + { TagName = "remark" + Formatter = + function + | VoidElement _ -> None + + | NonVoidElement(innerText, _) -> innerText |> Some + + } + |> applyFormatter + +/// +/// Format the given doc comments text to HTML +/// +/// +/// +let format (text: string) = + text + |> removeSummaryTag + |> removeParamElement + |> removeRemarkTag + |> example + |> paragraph + |> block + |> codeBlock + |> codeInline // Important: Apply code inline after the codeBlock as we are generating tags + |> see + |> paramRef + |> typeParamRef + |> list + |> unescapeSpecialCharacters + |> Markdown.ToHtml + +/// +/// Extract and format only the summary tag +/// +/// +/// +let formatSummaryOnly (text: string) = + let pattern = tagPattern "summary" + + // Match all the param tags + match Regex.Match(text, pattern, RegexOptions.IgnoreCase) with + | m when m.Success -> + if m.Groups.["void_element"].Success then + "" + else if m.Groups.["non_void_element"].Success then + m.Groups.["non_void_innerText"].Value |> format + + else + // Should not happen but we are forced to handle it by F# compiler + "" + + | _ -> "" + +/// +/// Try to extract a specific param tag and format +/// +/// +/// Return the formatted param tag doc if found. +/// +/// Otherwise, it returns None +/// +let tryFormatParam (parameterName: string) (text: string) = + let pattern = tagPattern "param" + + // Match all the param tags + Regex.Matches(text, pattern, RegexOptions.IgnoreCase) + // Try find the param tag that has name attribute equal to the parameterName + |> Seq.tryFind (fun m -> + if m.Groups.["void_element"].Success then + false + else if m.Groups.["non_void_element"].Success then + let attributes = getAttributes m.Groups.["non_void_attributes"] + + match Map.tryFind "name" attributes with + | Some name -> name = parameterName + + | None -> false + else + // Should not happen but we are forced to handle it by F# compiler + false) + // Extract the inner text of the param tag + |> Option.map (fun m -> m.Groups.["non_void_innerText"].Value |> format) + +let tryFormatReturnsOnly (text: string) = + let pattern = tagPattern "returns" + + match Regex.Match(text, pattern, RegexOptions.IgnoreCase) with + | m when m.Success -> + if m.Groups.["void_element"].Success then + None + else if m.Groups.["non_void_element"].Success then + m.Groups.["non_void_innerText"].Value |> format |> Some + + else + // Should not happen but we are forced to handle it by F# compiler + None + + | _ -> None diff --git a/src/FSharp.Formatting.ApiDocs/FSharp.Formatting.ApiDocs.fsproj b/src/FSharp.Formatting.ApiDocs/FSharp.Formatting.ApiDocs.fsproj index 1255480ce..b3ae7573d 100644 --- a/src/FSharp.Formatting.ApiDocs/FSharp.Formatting.ApiDocs.fsproj +++ b/src/FSharp.Formatting.ApiDocs/FSharp.Formatting.ApiDocs.fsproj @@ -10,8 +10,11 @@ Common\StringParsing.fs + + + diff --git a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs index a6067d233..ab002d806 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs @@ -9,6 +9,9 @@ open FSharp.Compiler.Symbols open FSharp.Formatting.Templating open FSharp.Formatting.HtmlModel open FSharp.Formatting.HtmlModel.Html +open System.Xml.Linq +open System.Text.RegularExpressions +open FSharp.Formatting.ApiDocs.GenerateSignature /// Embed some HTML generated in GenerateModel let embed (x: ApiDocHtml) = !!x.HtmlText @@ -20,6 +23,36 @@ let fsdocsSummary (x: ApiDocHtml) = else div [ Class "fsdocs-summary-contents" ] [ p [ Class "fsdocs-summary" ] [ embed x ] ] +let formatXmlComment (commentOpt: XElement option) : string = + + match commentOpt with + | Some comment -> + let docComment = comment.ToString() + + let pattern = $"""((?'xml_doc'(?:(?!)(?!<\/member>)[\s\S])*)<\/member\s*>)""" + + let m = Regex.Match(docComment, pattern) + + // Remove the and tags + if m.Success then + let xmlDoc = m.Groups.["xml_doc"].Value + + let lines = xmlDoc |> String.splitLines |> Array.toList + + // Remove the non meaning full indentation + let content = + lines + |> List.map (fun line -> + // Add a small protection in case the user didn't align all it's tags + if line.StartsWith(" ") then line.Substring(1) else line) + |> String.concat "\n" + + CommentFormatter.format content + else + CommentFormatter.format docComment + + | None -> "" + type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = let root = model.Root let collectionName = model.Collection.CollectionName @@ -101,6 +134,151 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = | :? FSharpEntity as v -> copyXmlSigIconMarkdown (removeParen v.XmlDocSig) | _ -> () ] + let renderValueOrFunctions (entities: ApiDocMember list) = + + if entities.IsEmpty then + [] + else + + [ h3 [] [ !! "Functions and values" ] + + for entity in entities do + let (ApiDocMemberDetails(usageHtml, + paramTypes, + returnType, + modifiers, + typars, + baseType, + location, + compiledName)) = + entity.Details + + let returnHtml = + // TODO: Parse the return type information from + // let x = entity.Symbol :?> FSharpMemberOrFunctionOrValue + // x.FullType <-- Here we have access to all the type including the argument for the function that we should ignore... (making the processing complex) + // For now, we are just using returnType.HtmlText to have something ready as parsing from + // FSharpMemberOrFunctionOrValue seems to be quite complex + match returnType with + | Some(_, returnType) -> + // Remove the starting and ending + returnType.HtmlText.[6 .. returnType.HtmlText.Length - 8] + // Adapt the text to have basic syntax highlighting + |> fun text -> text.Replace("<", Html.lessThan.ToMinifiedHtml()) + |> fun text -> text.Replace(">", Html.greaterThan.ToMinifiedHtml()) + |> fun text -> text.Replace(",", Html.comma.ToMinifiedHtml()) + + | None -> "unit" + + let initial = Signature.ParamTypesInformation.Init entity.Name + + let paramTypesInfo = Signature.extractParamTypesInformation initial paramTypes + + div [ Class "fsdocs-block" ] [ + + div [ Class "actions-buttons" ] [ + yield! sourceLink entity.SourceLocation + yield! copyXmlSigIconForSymbol entity.Symbol + yield! copyXmlSigIconForSymbolMarkdown entity.Symbol + ] + + // This is a value + if paramTypesInfo.Infos.IsEmpty then + div [ Class "fsdocs-api-code" ] [ + div [] [ Html.val'; Html.space; !!entity.Name; Html.space; Html.colon; !!returnHtml ] + ] + + // This is a function + else + + div [ Class "fsdocs-api-code" ] [ + [ TextNode.Div [ + TextNode.Keyword "val" + TextNode.Space + TextNode.AnchorWithId($"#{entity.Name}", entity.Name, entity.Name) + TextNode.Space + TextNode.Colon + ] ] + |> TextNode.Node + |> TextNode.ToHtmlElement + + for index in 0 .. paramTypesInfo.Infos.Length - 1 do + let (name, returnType) = paramTypesInfo.Infos.[index] + + div [] [ + Html.spaces 4 // Equivalent to 'val ' + !!name + Html.spaces (paramTypesInfo.MaxNameLength - name.Length + 1) // Complete with space to align ':' + Html.colon + Html.space + !! returnType.HtmlElement.ToMinifiedHtml() + + Html.spaces (paramTypesInfo.MaxReturnTypeLength - returnType.Length + 1) // Complete with space to align '->' + + // Don't add the arrow for the last parameter + if index <> paramTypesInfo.Infos.Length - 1 then + Html.arrow + ] + |> Html.minify + + div [] [ + Html.spaces (4 + paramTypesInfo.MaxNameLength + 1) // Equivalent to 'val ' + the max length of parameter name + ':' + Html.arrow + Html.space + !!returnHtml + ] + |> Html.minify + ] + + match entity.Comment.Xml with + | Some xmlComment -> + let comment = xmlComment.ToString() + !!(CommentFormatter.formatSummaryOnly comment) + + if not paramTypesInfo.Infos.IsEmpty then + p [] [ strong [] [ !! "Parameters" ] ] + + + for (name, returnType) in paramTypesInfo.Infos do + let paramDoc = + CommentFormatter.tryFormatParam name comment + |> Option.map (fun paramDoc -> !!paramDoc) + |> Option.defaultValue Html.nothing + + div [ Class "fsdocs-doc-parameter" ] [ + [ TextNode.DivWithClass( + "fsdocs-api-code", + [ TextNode.Property name + TextNode.Space + TextNode.Colon + TextNode.Space + returnType ] + ) ] + |> TextNode.Node + |> TextNode.ToHtmlElement + + paramDoc + ] + + match CommentFormatter.tryFormatReturnsOnly comment with + | Some returnDoc -> + p [] [ strong [] [ !! "Returns" ] ] + + !!returnDoc + + | None -> () + + // TODO: Should we r``ender a minimal documentation here with the information we have? + // For example, we can render the list of parameters and the return type + // This is to make the documentation more consistent + // However, these minimal information will be rondontant with the information displayed in the signature + | None -> () + ] + + // hr [] + + ] + let renderMembers header tableHeader (members: ApiDocMember list) = [ if members.Length > 0 then h3 [] [ !!header ] @@ -330,7 +508,9 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = ] td [ Class "fsdocs-entity-xmldoc" ] [ div [] [ - fsdocsSummary e.Comment.Summary + + div [ Class "fsdocs-summary-contents" ] [ !!(formatXmlComment e.Comment.Xml) ] + div [ Class "icon-button-row" ] [ yield! sourceLink e.SourceLocation yield! copyXmlSigIconForSymbol e.Symbol @@ -481,7 +661,7 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = let constructors = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.Constructor) let instanceMembers = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.InstanceMember) let staticMembers = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.StaticMember) - div [] (renderMembers "Functions and values" "Function or value" functionsOrValues) + div [] (renderValueOrFunctions functionsOrValues) div [] (renderMembers "Type extensions" "Type extension" extensions) div [] (renderMembers "Active patterns" "Active pattern" activePatterns) div [] (renderMembers "Union cases" "Union case" unionCases) diff --git a/src/FSharp.Formatting.ApiDocs/GenerateSignature.fs b/src/FSharp.Formatting.ApiDocs/GenerateSignature.fs new file mode 100644 index 000000000..3d53d818b --- /dev/null +++ b/src/FSharp.Formatting.ApiDocs/GenerateSignature.fs @@ -0,0 +1,320 @@ +module internal FSharp.Formatting.ApiDocs.GenerateSignature + +open System +open System.Collections.Generic +open System.IO +open System.Web +open FSharp.Formatting.Common +open FSharp.Compiler.Symbols +open FSharp.Formatting.Templating +open FSharp.Formatting.HtmlModel +open FSharp.Formatting.HtmlModel.Html +open System.Xml.Linq +open System.Text.RegularExpressions + +/// +/// Type used to represent a text node. +/// +/// This is mostly used to render API signature while also being able to compute the length of the text +/// in term of characters to align the signature. +/// +[] +type TextNode = + | Text of string + | Anchor of url: string * label: string + | AnchorWithId of url: string * id: string * label: string + | Space + | Dot + | Comma + | Arrow + | GreaterThan + | Colon + | LessThan + | LeftParent + | RightParent + | Equal + | Tick + | Node of TextNode list + | Keyword of string + | NewLine + | Spaces of int + | Div of TextNode list + | DivWithClass of string * TextNode list + | Property of string + | Paragraph of TextNode list + + static member ToHtmlElement(node: TextNode) : HtmlElement = node.HtmlElement + + member this.HtmlElement: HtmlElement = + match this with + | Text s -> !!s + | Colon -> Html.colon + | Anchor(url, text) -> a [ Href url ] [ !!text ] + | AnchorWithId(url, id, text) -> a [ Href url; Id id ] [ !!text ] + | Keyword text -> Html.keyword text + | Property text -> Html.property text + | Div nodes -> div [] (nodes |> List.map (fun node -> node.HtmlElement)) + | DivWithClass(cls, nodes) -> div [ Class cls ] (nodes |> List.map (fun node -> node.HtmlElement)) + | Paragraph nodes -> p [] (nodes |> List.map (fun node -> node.HtmlElement)) + | Spaces n -> + [ for _ in 0..n do + Space ] + |> Node + |> TextNode.ToHtmlElement + | NewLine -> !! "\n" // Should it be
    instead? + | Arrow -> Html.arrow + | Dot -> Html.dot + | Comma -> Html.comma + | Space -> Html.space + | GreaterThan -> Html.greaterThan + | LessThan -> Html.lessThan + | Equal -> Html.keyword "=" + | Tick -> !! "'" + | LeftParent -> Html.leftParent + | RightParent -> Html.rightParent + | Node node -> + // TODO: Can we have something similar to fragments in React? + let elements = span [] (node |> List.map (fun node -> node.HtmlElement)) + + !! elements.ToMinifiedHtml() + + member this.Length = + match this with + | NewLine -> 0 + // 1 character + | Comma + | Colon + | Dot + | Space + | GreaterThan + | LessThan + | LeftParent + | RightParent + | Equal + | Tick -> 1 + // 2 characters + | Anchor(_, text) + | AnchorWithId(_, _, text) + | Keyword text + | Property text -> text.Length + | Arrow -> 2 + // X characters + | Text s -> s.Length + | Spaces count -> count + // Sum of children + | Node nodes + | Div nodes + | DivWithClass(_, nodes) + | Paragraph nodes -> nodes |> List.map (fun node -> node.Length) |> List.sum + +[] +module Signature = + + /// + /// Generate a list of generic parameters + /// + /// 'T, 'T2, 'MyType + /// + /// + /// + /// + let renderGenericParameters (parameters: IList) : TextNode = + [ for index in 0 .. parameters.Count - 1 do + let param = parameters.[index] + + if index <> 0 then + TextNode.Comma + TextNode.Space + + TextNode.Tick + TextNode.Text param.DisplayName ] + |> TextNode.Node + + let rec renderParameterType (isTopLevel: bool) (typ: FSharpType) : TextNode = + // This correspond to a generic paramter like: 'T + if typ.IsGenericParameter then + TextNode.Node [ TextNode.Tick; TextNode.Text typ.GenericParameter.DisplayName ] + // Not a generic type we can display it as it is + // Example: + // - string + // - int + // - MyObject + else if typ.GenericArguments.Count = 0 then + TextNode.Text typ.TypeDefinition.DisplayName + + // This is a generic type we need more logic + else if + // This is a function, we need to generate something like: + // - 'T -> string + // - 'T -> 'T option + typ.IsFunctionType + then + let separator = TextNode.Node [ TextNode.Space; TextNode.Arrow; TextNode.Space ] + + let result = + [ for index in 0 .. typ.GenericArguments.Count - 1 do + let arg = typ.GenericArguments.[index] + + // Add the separator if this is not the first argument + if index <> 0 then + separator + + // This correspond to a generic paramter like: 'T + if arg.IsGenericParameter then + TextNode.Tick + TextNode.Text arg.GenericParameter.DisplayName + + // This is a type definition like: 'T option or Choice<'T1, 'T2> + else if arg.HasTypeDefinition then + // For some generic types definition we don't add the generic arguments + if + arg.TypeDefinition.DisplayName = "exn" + || arg.TypeDefinition.DisplayName = "unit" + then + + TextNode.Text arg.TypeDefinition.DisplayName + + else + // This is the name of the type definition + // In Choice<'T1, 'T2> this correspond to Choice + TextNode.Text arg.TypeDefinition.DisplayName + TextNode.LessThan + // Render the generic parameters list in the form of 'T1, 'T2 + renderGenericParameters arg.TypeDefinition.GenericParameters + + TextNode.GreaterThan + + else if arg.IsFunctionType then + + let res = + [ for index in 0 .. arg.GenericArguments.Count - 1 do + let arg = arg.GenericArguments.[index] + + if index <> 0 then + TextNode.Space + TextNode.Arrow + TextNode.Space + + renderParameterType false arg ] + + // Try to detect curried case + // Like in: + // let create (f: ('T -> unit) -> (exn -> unit) -> unit): JS.Promise<'T> = jsNative + // FCS gives back an equivalent of : + // let create (f: ('T -> unit) -> ((exn -> unit) -> unit)): JS.Promise<'T> = jsNative + // So we try to detect it to avoid the extract Parents + match res with + | (TextNode.Node(TextNode.LeftParent :: _) :: _) -> TextNode.Node res + + | _ -> + TextNode.Node + [ TextNode.LeftParent + + yield! res + + TextNode.RightParent ] + + else + TextNode.Text "Unkown syntax please open an issue" ] + + // If this is a top level function we don't neeed to add the parenthesis + TextNode.Node + [ if not isTopLevel then + TextNode.LeftParent + + TextNode.Node result + + if not isTopLevel then + TextNode.RightParent ] + + else + let separator = TextNode.Node [ TextNode.Space; TextNode.Comma ] + + let result = + [ for index in 0 .. typ.GenericArguments.Count - 1 do + let arg = typ.GenericArguments.[index] + + // Add the separator if this is not the first argument + if index <> 0 then + separator + + if arg.IsGenericParameter then + TextNode.Tick + TextNode.Text arg.GenericParameter.DisplayName + else + // TODO: Generate an URL with the version of the package + + let url = + // FIXME: This is a temporary fix to avoid the error + try + arg.TypeDefinition.FullName + |> String.toLower + |> String.replace "." "-" + |> String.append ".html" + with _ -> + "" + + let subType = renderParameterType false arg + + TextNode.Anchor(url, arg.TypeDefinition.DisplayName) + TextNode.LessThan + + subType + + TextNode.GreaterThan ] + + TextNode.Node result + + type ParamTypesInformation = + { Infos: (string * TextNode) list + MaxNameLength: int + MaxReturnTypeLength: int } + + static member Init(entityName: string) = + { Infos = [] + MaxNameLength = entityName.Length + MaxReturnTypeLength = 0 } + + /// + /// Extracts parameter types information from a list of parameter types. + /// + /// The goals is to extract the information about the max length of the name and the return type + /// to be able to format the information in a nice way. + /// + /// It will allows us to align the colon, arrows and other symbols. + /// + /// The current state of parameter types information + /// The list of parameter types to extract information from + /// The list of parameters and the max length of the name and return type + let rec extractParamTypesInformation + (state: ParamTypesInformation) + (paramTypes: list * string * ApiDocHtml>) + = + + match paramTypes with + | paramType :: tail -> + match paramType with + | Choice1Of2 fsharpParameter, name, _apiDoc -> + let returnType = renderParameterType true fsharpParameter.Type + + let newState = + { state with + Infos = state.Infos @ [ name, returnType ] + MaxNameLength = System.Math.Max(state.MaxNameLength, name.Length) + MaxReturnTypeLength = System.Math.Max(state.MaxReturnTypeLength, returnType.Length) } + + extractParamTypesInformation newState tail + + // TODO: I didn't encounter this case yet, so I a not sure how to handle it + | Choice2Of2 _fsharpField, _name, _apiDoc -> + let newState = + { state with + Infos = + state.Infos + @ [ "TODO: extractParamTypesInformation -> fsharpField", TextNode.Div [] ] } + + failwith "Not implemented" + + extractParamTypesInformation newState tail + + | [] -> state diff --git a/src/FSharp.Formatting.ApiDocs/Prelude.fs b/src/FSharp.Formatting.ApiDocs/Prelude.fs new file mode 100644 index 000000000..eb404d022 --- /dev/null +++ b/src/FSharp.Formatting.ApiDocs/Prelude.fs @@ -0,0 +1,44 @@ +[] +module internal FSharp.Formatting.ApiDocs.Prelude + +open FSharp.Formatting.HtmlModel +open FSharp.Formatting.HtmlModel.Html + +[] +module Html = + let wrapInClass cls text = span [ Class cls ] [ !!text ] + let keyword text = wrapInClass "keyword" text + let property text = wrapInClass "property" text + + let val' = keyword "val" + let space = !! " " + let spaces count = !!(String.replicate count " ") + let comma = keyword "," + let colon = keyword ":" + let arrow = keyword "->" + let dot = keyword "." + + let greaterThan = keyword ">" + let lessThan = keyword "<" + let nothing = !! "" + let equal = keyword "=" + let leftParent = keyword "(" + let rightParent = keyword ")" + + let minify (html: HtmlElement) = !!(html.ToMinifiedHtml()) + +[] +module String = + + let normalizeEndOfLine (text: string) = text.Replace("\r\n", "\n") + + let splitBy (c: char) (text: string) = text.Split(c) + + let splitLines (text: string) = + text |> normalizeEndOfLine |> splitBy '\n' + + let toLower (text: string) = text.ToLower() + + let replace (oldValue: string) (newValue: string) (text: string) = text.Replace(oldValue, newValue) + + let append (value: string) (text: string) = text + value diff --git a/src/FSharp.Formatting.Common/HtmlModel.fs b/src/FSharp.Formatting.Common/HtmlModel.fs index 17da8ae80..51e6bdd8e 100644 --- a/src/FSharp.Formatting.Common/HtmlModel.fs +++ b/src/FSharp.Formatting.Common/HtmlModel.fs @@ -435,6 +435,176 @@ type internal HtmlElement = | EncodeString of string | CustomElement of element: string * props: HtmlProperties list * children: HtmlElement list + // TODO: The way F# Formatting format the HTML is causing issues because it "beautifies" the HTML too much + // which causes issues with the control over the spaces. + // Do we need to have a beautiful HTML generated? + // In theory, for performance reasons, we should the most minified HTML possible. + member tag.ToMinifiedHtml() = + let rec format tag (props: HtmlProperties list) (children: HtmlElement list) = + let cnt = + if children.Length > 0 then + (children + |> List.map (fun n -> (String.replicate 0 " ") + helper n) + |> String.concat "") + else + "" + + let attrs = + if props.Length > 0 then + " " + (props |> List.map string |> String.concat " ") + else + "" + + sprintf "<%s%s>%s" tag attrs cnt tag + + and formatVoid tag (props: HtmlProperties list) = + let attrs = + if props.Length > 0 then + " " + (props |> List.map string |> String.concat " ") + else + "" + + sprintf "<%s%s/>" tag attrs + + and helper tag = + match tag with + | A(props, children) -> format "a" props children + | Abbr(props, children) -> format "abbr" props children + | Address(props, children) -> format "address" props children + | Area(props) -> formatVoid "area" props + | Article(props, children) -> format "article" props children + | Aside(props, children) -> format "aside" props children + | Audio(props, children) -> format "audio" props children + | B(props, children) -> format "b" props children + | Base(props) -> formatVoid "base" props + | Bdi(props, children) -> format "bdi" props children + | Bdo(props, children) -> format "bdo" props children + | Big(props, children) -> format "big" props children + | Blockquote(props, children) -> format "blockquote" props children + | Body(props, children) -> format "body" props children + | Br(props) -> formatVoid "br" props + | Button(props, children) -> format "button" props children + | Canvas(props, children) -> format "canvas" props children + | Caption(props, children) -> format "caption" props children + | Cite(props, children) -> format "cite" props children + | Code(props, children) -> format "code" props children + | Col(props) -> formatVoid "col" props + | Colgroup(props, children) -> format "colgroup" props children + | Data(props, children) -> format "data" props children + | Datalist(props, children) -> format "datalist" props children + | Dd(props, children) -> format "dd" props children + | Del(props, children) -> format "del" props children + | Details(props, children) -> format "details" props children + | Dfn(props, children) -> format "dfn" props children + | Dialog(props, children) -> format "dialog" props children + | Div(props, children) -> format "div" props children + | Dl(props, children) -> format "dl" props children + | Dt(props, children) -> format "dt" props children + | Em(props, children) -> format "em" props children + | Embed(props) -> formatVoid "embed" props + | Fieldset(props, children) -> format "fieldset" props children + | Figcaption(props, children) -> format "figcaption" props children + | Figure(props, children) -> format "figure" props children + | Footer(props, children) -> format "footer" props children + | Form(props, children) -> format "form" props children + | H1(props, children) -> format "h1" props children + | H2(props, children) -> format "h2" props children + | H3(props, children) -> format "h3" props children + | H4(props, children) -> format "h4" props children + | H5(props, children) -> format "h5" props children + | H6(props, children) -> format "h6" props children + | Head(props, children) -> format "head" props children + | Header(props, children) -> format "header" props children + | Hgroup(props, children) -> format "hgroup" props children + | Hr(props) -> formatVoid "hr" props + | Html(props, children) -> format "html" props children + | I(props, children) -> format "i" props children + | Iframe(props, children) -> format "iframe" props children + | Img(props) -> formatVoid "img" props + | Input(props) -> formatVoid "input" props + | Ins(props, children) -> format "ins" props children + | Kbd(props, children) -> format "kbd" props children + | Keygen(props) -> formatVoid "keygen" props + | Label(props, children) -> format "label" props children + | Legend(props, children) -> format "legend" props children + | Li(props, children) -> format "li" props children + | Link(props) -> formatVoid "link" props + | Main(props, children) -> format "main" props children + | Map(props, children) -> format "map" props children + | Mark(props, children) -> format "mark" props children + | Menu(props, children) -> format "menu" props children + | Menuitem(props) -> formatVoid "menuitem" props + | Meta(props) -> formatVoid "meta" props + | Meter(props, children) -> format "meter" props children + | Nav(props, children) -> format "nav" props children + | Noscript(props, children) -> format "noscript" props children + | Object(props, children) -> format "object" props children + | Ol(props, children) -> format "ol" props children + | Optgroup(props, children) -> format "optgroup" props children + | Option(props, children) -> format "option" props children + | Output(props, children) -> format "output" props children + | P(props, children) -> format "p" props children + | Param(props) -> formatVoid "param" props + | Picture(props, children) -> format "picture" props children + | Pre(props, children) -> format "pre" props children + | Progress(props, children) -> format "progress" props children + | Q(props, children) -> format "q" props children + | Rp(props, children) -> format "rp" props children + | Rt(props, children) -> format "rt" props children + | Ruby(props, children) -> format "ruby" props children + | S(props, children) -> format "s" props children + | Samp(props, children) -> format "samp" props children + | Script(props, children) -> format "script" props children + | Section(props, children) -> format "section" props children + | Select(props, children) -> format "select" props children + | Small(props, children) -> format "small" props children + | Source(props) -> formatVoid "source" props + | Span(props, children) -> format "span" props children + | Strong(props, children) -> format "strong" props children + | Style(props, children) -> format "style" props children + | Sub(props, children) -> format "sub" props children + | Summary(props, children) -> format "summary" props children + | Sup(props, children) -> format "sup" props children + | Table(props, children) -> format "table" props children + | Tbody(props, children) -> format "tbody" props children + | Td(props, children) -> format "td" props children + | Textarea(props, children) -> format "textarea" props children + | Tfoot(props, children) -> format "tfoot" props children + | Th(props, children) -> format "th" props children + | Thead(props, children) -> format "thead" props children + | Time(props, children) -> format "time" props children + | Title(props, children) -> format "title" props children + | Tr(props, children) -> format "tr" props children + | Track(props) -> formatVoid "track" props + | U(props, children) -> format "u" props children + | Ul(props, children) -> format "ul" props children + | Var(props, children) -> format "var" props children + | Video(props, children) -> format "video" props children + | Wbr(props) -> formatVoid "wbr" props + | Svg(props, children) -> format "svg" props children + | Circle(props, children) -> format "circle" props children + | Defs(props, children) -> format "defs" props children + | Ellipse(props, children) -> format "ellipse" props children + | G(props, children) -> format "g" props children + | Image(props, children) -> format "image" props children + | Line(props, children) -> format "line" props children + | LinearGradient(props, children) -> format "radient" props children + | Mask(props, children) -> format "mask" props children + | Path(props, children) -> format "path" props children + | Pattern(props, children) -> format "pattern" props children + | Polygon(props, children) -> format "polygon" props children + | Polyline(props, children) -> format "polyline" props children + | RadialGradient(props, children) -> format "radient" props children + | Rect(props, children) -> format "rect" props children + | Stop(props, children) -> format "stop" props children + | Text(props, children) -> format "text" props children + | Tspan(props, children) -> format "tspan" props children + | String str -> str + | EncodeString str -> System.Web.HttpUtility.HtmlEncode str + | CustomElement(element, props, children) -> format element props children + + helper tag + override tag.ToString() = let rec format tag (props: HtmlProperties list) (children: HtmlElement list) level = let cnt = @@ -745,6 +915,7 @@ module internal Html = let tspan (props: HtmlProperties list) (children: HtmlElement list) = HtmlElement.Tspan(props, children) //let string str = HtmlElement.String str let (!!) str = HtmlElement.String str + let rawString str = HtmlElement.EncodeString str let encode str = HtmlElement.EncodeString str /// Web component from https://iconify.design/docs/ diff --git a/src/fsdocs-tool/Options.fs b/src/fsdocs-tool/Options.fs index 97928d046..a0a44b559 100644 --- a/src/fsdocs-tool/Options.fs +++ b/src/fsdocs-tool/Options.fs @@ -32,5 +32,5 @@ module Common = let waitForKey b = if b then - printf "\nPress any key to continue ..." + printfn "\nPress any key to continue ..." System.Console.ReadKey() |> ignore From 7b86b33b77eb6514de8d5cce5bb312af748d8e27 Mon Sep 17 00:00:00 2001 From: Maxime Mangel Date: Tue, 13 Aug 2024 21:57:42 +0200 Subject: [PATCH 2/7] chore: improve Fantomas configuration --- .editorconfig | 18 +- src/FSharp.Formatting.ApiDocs/GenerateHtml.fs | 1636 ++++++++++------- 2 files changed, 1012 insertions(+), 642 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3c8678113..23440bfa8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,4 +17,20 @@ fsharp_max_infix_operator_expression=80 fsharp_max_value_binding_width=120 [GenerateHtml.fs] -fsharp_experimental_elmish = true \ No newline at end of file +# Specific settings for "View/HTML" related files +# It makes the code more consistent in term of spacing and indentation +fsharp_experimental_elmish = true +fsharp_array_or_list_multiline_formatter = number_of_items +fsharp_max_array_or_list_number_of_items = 0 + +# In general, the following settings are what I use for any F# project. +# I didn't apply them globally yet because it will affect all the projects and I want to +# have confirmation from the team before doing so. +fsharp_alternative_long_member_definitions = true +fsharp_multi_line_lambda_closing_newline = true +fsharp_multiline_bracket_style = aligned +fsharp_keep_max_number_of_blank_lines = 1 +fsharp_align_function_signature_to_indentation = true +fsharp_max_if_then_else_short_width = 0 +fsharp_max_record_number_of_items = 2 +fsharp_record_multiline_formatter = number_of_items \ No newline at end of file diff --git a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs index ab002d806..3a75112f7 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs @@ -21,7 +21,15 @@ let fsdocsSummary (x: ApiDocHtml) = if x.HtmlText.StartsWith("
    ", StringComparison.Ordinal) then
             embed x
         else
    -        div [ Class "fsdocs-summary-contents" ] [ p [ Class "fsdocs-summary" ] [ embed x ] ]
    +        div [
    +            Class "fsdocs-summary-contents"
    +        ] [
    +            p [
    +                Class "fsdocs-summary"
    +            ] [
    +                embed x
    +            ]
    +        ]
     
     let formatXmlComment (commentOpt: XElement option) : string =
     
    @@ -44,7 +52,11 @@ let formatXmlComment (commentOpt: XElement option) : string =
                     lines
                     |> List.map (fun line ->
                         // Add a small protection in case the user didn't align all it's tags
    -                    if line.StartsWith(" ") then line.Substring(1) else line)
    +                    if line.StartsWith(" ") then
    +                        line.Substring(1)
    +                    else
    +                        line
    +                )
                     |> String.concat "\n"
     
                 CommentFormatter.format content
    @@ -75,20 +87,37 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) =
                 let id = UniqueID().ToString()
     
                 code
    -                [ OnMouseOut(sprintf "hideTip(event, '%s', %s)" id id)
    -                  OnMouseOver(sprintf "showTip(event, '%s', %s)" id id) ]
    +                [
    +                    OnMouseOut(sprintf "hideTip(event, '%s', %s)" id id)
    +                    OnMouseOver(sprintf "showTip(event, '%s', %s)" id id)
    +                ]
                     content
     
    -            div [ Class "fsdocs-tip"; Id id ] tip
    +            div
    +                [
    +                    Class "fsdocs-tip"
    +                    Id id
    +                ]
    +                tip
             ]
     
         let sourceLink url =
    -        [ match url with
    -          | None -> ()
    -          | Some href ->
    -              a [ Href href; Class "fsdocs-source-link"; HtmlProperties.Title "Source on GitHub" ] [
    -                  iconifyIcon [ Icon "ri:github-fill"; Height "24"; Width "24" ]
    -              ] ]
    +        [
    +            match url with
    +            | None -> ()
    +            | Some href ->
    +                a [
    +                    Href href
    +                    Class "fsdocs-source-link"
    +                    HtmlProperties.Title "Source on GitHub"
    +                ] [
    +                    iconifyIcon [
    +                        Icon "ri:github-fill"
    +                        Height "24"
    +                        Width "24"
    +                    ]
    +                ]
    +        ]
     
         let removeParen (memberName: string) =
             let firstParen = memberName.IndexOf('(')
    @@ -104,13 +133,21 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) =
                 Class "fsdocs-source-link"
                 HtmlProperties.Title "Copy signature (XML)"
                 OnClick(sprintf "Clipboard_CopyTo('')" xmlDocSig)
    -        ] [ iconifyIcon [ HtmlProperties.Icon "bi:filetype-xml"; Height "24"; Width "24" ] ]
    +        ] [
    +            iconifyIcon [
    +                HtmlProperties.Icon "bi:filetype-xml"
    +                Height "24"
    +                Width "24"
    +            ]
    +        ]
     
         let copyXmlSigIconForSymbol (symbol: FSharpSymbol) =
    -        [ match symbol with
    -          | :? FSharpMemberOrFunctionOrValue as v -> copyXmlSigIcon (removeParen v.XmlDocSig)
    -          | :? FSharpEntity as v -> copyXmlSigIcon (removeParen v.XmlDocSig)
    -          | _ -> () ]
    +        [
    +            match symbol with
    +            | :? FSharpMemberOrFunctionOrValue as v -> copyXmlSigIcon (removeParen v.XmlDocSig)
    +            | :? FSharpEntity as v -> copyXmlSigIcon (removeParen v.XmlDocSig)
    +            | _ -> ()
    +        ]
     
         // Copy XML sig for use in `cref` markdown
         let copyXmlSigIconMarkdown (xmlDocSig: string) =
    @@ -118,21 +155,32 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) =
                 div [] []
             else
                 let delim =
    -                if xmlDocSig.Contains("``") then "```"
    -                elif xmlDocSig.Contains("`") then "``"
    -                else "`"
    +                if xmlDocSig.Contains("``") then
    +                    "```"
    +                elif xmlDocSig.Contains("`") then
    +                    "``"
    +                else
    +                    "`"
     
                 div [
                     Class "fsdocs-source-link"
                     HtmlProperties.Title "Copy signature (Markdown)"
                     OnClick(sprintf "Clipboard_CopyTo('%scref:%s%s')" delim xmlDocSig delim)
    -            ] [ iconifyIcon [ HtmlProperties.Icon "bi:filetype-md"; Height "24"; Width "24" ] ]
    +            ] [
    +                iconifyIcon [
    +                    HtmlProperties.Icon "bi:filetype-md"
    +                    Height "24"
    +                    Width "24"
    +                ]
    +            ]
     
         let copyXmlSigIconForSymbolMarkdown (symbol: FSharpSymbol) =
    -        [ match symbol with
    -          | :? FSharpMemberOrFunctionOrValue as v -> copyXmlSigIconMarkdown (removeParen v.XmlDocSig)
    -          | :? FSharpEntity as v -> copyXmlSigIconMarkdown (removeParen v.XmlDocSig)
    -          | _ -> () ]
    +        [
    +            match symbol with
    +            | :? FSharpMemberOrFunctionOrValue as v -> copyXmlSigIconMarkdown (removeParen v.XmlDocSig)
    +            | :? FSharpEntity as v -> copyXmlSigIconMarkdown (removeParen v.XmlDocSig)
    +            | _ -> ()
    +        ]
     
         let renderValueOrFunctions (entities: ApiDocMember list) =
     
    @@ -140,307 +188,431 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) =
                 []
             else
     
    -            [ h3 [] [ !! "Functions and values" ]
    -
    -              for entity in entities do
    -                  let (ApiDocMemberDetails(usageHtml,
    -                                           paramTypes,
    -                                           returnType,
    -                                           modifiers,
    -                                           typars,
    -                                           baseType,
    -                                           location,
    -                                           compiledName)) =
    -                      entity.Details
    -
    -                  let returnHtml =
    -                      // TODO: Parse the return type information from
    -                      // let x = entity.Symbol :?> FSharpMemberOrFunctionOrValue
    -                      // x.FullType <-- Here we have access to all the type including the argument for the function that we should ignore... (making the processing complex)
    -                      // For now, we are just using returnType.HtmlText to have something ready as parsing from
    -                      // FSharpMemberOrFunctionOrValue seems to be quite complex
    -                      match returnType with
    -                      | Some(_, returnType) ->
    -                          // Remove the starting  and ending 
    -                          returnType.HtmlText.[6 .. returnType.HtmlText.Length - 8]
    -                          // Adapt the text to have basic syntax highlighting
    -                          |> fun text -> text.Replace("<", Html.lessThan.ToMinifiedHtml())
    -                          |> fun text -> text.Replace(">", Html.greaterThan.ToMinifiedHtml())
    -                          |> fun text -> text.Replace(",", Html.comma.ToMinifiedHtml())
    -
    -                      | None -> "unit"
    -
    -                  let initial = Signature.ParamTypesInformation.Init entity.Name
    -
    -                  let paramTypesInfo = Signature.extractParamTypesInformation initial paramTypes
    -
    -                  div [ Class "fsdocs-block" ] [
    -
    -                      div [ Class "actions-buttons" ] [
    -                          yield! sourceLink entity.SourceLocation
    -                          yield! copyXmlSigIconForSymbol entity.Symbol
    -                          yield! copyXmlSigIconForSymbolMarkdown entity.Symbol
    -                      ]
    -
    -                      // This is a value
    -                      if paramTypesInfo.Infos.IsEmpty then
    -                          div [ Class "fsdocs-api-code" ] [
    -                              div [] [ Html.val'; Html.space; !!entity.Name; Html.space; Html.colon; !!returnHtml ]
    -                          ]
    -
    -                      // This is a function
    -                      else
    +            [
    +                h3 [] [
    +                    !! "Functions and values"
    +                ]
     
    -                          div [ Class "fsdocs-api-code" ] [
    -                              [ TextNode.Div [
    -                                    TextNode.Keyword "val"
    -                                    TextNode.Space
    -                                    TextNode.AnchorWithId($"#{entity.Name}", entity.Name, entity.Name)
    -                                    TextNode.Space
    -                                    TextNode.Colon
    -                                ] ]
    -                              |> TextNode.Node
    -                              |> TextNode.ToHtmlElement
    -
    -                              for index in 0 .. paramTypesInfo.Infos.Length - 1 do
    -                                  let (name, returnType) = paramTypesInfo.Infos.[index]
    -
    -                                  div [] [
    -                                      Html.spaces 4 // Equivalent to 'val '
    -                                      !!name
    -                                      Html.spaces (paramTypesInfo.MaxNameLength - name.Length + 1) // Complete with space to align ':'
    -                                      Html.colon
    -                                      Html.space
    -                                      !! returnType.HtmlElement.ToMinifiedHtml()
    -
    -                                      Html.spaces (paramTypesInfo.MaxReturnTypeLength - returnType.Length + 1) // Complete with space to align '->'
    -
    -                                      // Don't add the arrow for the last parameter
    -                                      if index <> paramTypesInfo.Infos.Length - 1 then
    -                                          Html.arrow
    -                                  ]
    -                                  |> Html.minify
    -
    -                              div [] [
    -                                  Html.spaces (4 + paramTypesInfo.MaxNameLength + 1) // Equivalent to 'val ' + the max length of parameter name + ':'
    -                                  Html.arrow
    -                                  Html.space
    -                                  !!returnHtml
    -                              ]
    -                              |> Html.minify
    -                          ]
    -
    -                      match entity.Comment.Xml with
    -                      | Some xmlComment ->
    -                          let comment = xmlComment.ToString()
    -                          !!(CommentFormatter.formatSummaryOnly comment)
    -
    -                          if not paramTypesInfo.Infos.IsEmpty then
    -                              p [] [ strong [] [ !! "Parameters" ] ]
    -
    -
    -                              for (name, returnType) in paramTypesInfo.Infos do
    -                                  let paramDoc =
    -                                      CommentFormatter.tryFormatParam name comment
    -                                      |> Option.map (fun paramDoc -> !!paramDoc)
    -                                      |> Option.defaultValue Html.nothing
    -
    -                                  div [ Class "fsdocs-doc-parameter" ] [
    -                                      [ TextNode.DivWithClass(
    -                                            "fsdocs-api-code",
    -                                            [ TextNode.Property name
    -                                              TextNode.Space
    -                                              TextNode.Colon
    -                                              TextNode.Space
    -                                              returnType ]
    -                                        ) ]
    -                                      |> TextNode.Node
    -                                      |> TextNode.ToHtmlElement
    -
    -                                      paramDoc
    -                                  ]
    -
    -                          match CommentFormatter.tryFormatReturnsOnly comment with
    -                          | Some returnDoc ->
    -                              p [] [ strong [] [ !! "Returns" ] ]
    -
    -                              !!returnDoc
    -
    -                          | None -> ()
    -
    -                      // TODO: Should we r``ender a minimal documentation here with the information we have?
    -                      // For example, we can render the list of parameters and the return type
    -                      // This is to make the documentation more consistent
    -                      // However, these minimal information will be rondontant with the information displayed in the signature
    -                      | None -> ()
    -                  ]
    -
    -              //   hr []
    -
    -              ]
    +                for entity in entities do
    +                    let (ApiDocMemberDetails(usageHtml,
    +                                             paramTypes,
    +                                             returnType,
    +                                             modifiers,
    +                                             typars,
    +                                             baseType,
    +                                             location,
    +                                             compiledName)) =
    +                        entity.Details
    +
    +                    let returnHtml =
    +                        // TODO: Parse the return type information from
    +                        // let x = entity.Symbol :?> FSharpMemberOrFunctionOrValue
    +                        // x.FullType <-- Here we have access to all the type including the argument for the function that we should ignore... (making the processing complex)
    +                        // For now, we are just using returnType.HtmlText to have something ready as parsing from
    +                        // FSharpMemberOrFunctionOrValue seems to be quite complex
    +                        match returnType with
    +                        | Some(_, returnType) ->
    +                            // Remove the starting  and ending 
    +                            returnType.HtmlText.[6 .. returnType.HtmlText.Length - 8]
    +                            // Adapt the text to have basic syntax highlighting
    +                            |> fun text -> text.Replace("<", Html.lessThan.ToMinifiedHtml())
    +                            |> fun text -> text.Replace(">", Html.greaterThan.ToMinifiedHtml())
    +                            |> fun text -> text.Replace(",", Html.comma.ToMinifiedHtml())
    +
    +                        | None -> "unit"
    +
    +                    let initial = Signature.ParamTypesInformation.Init entity.Name
    +
    +                    let paramTypesInfo = Signature.extractParamTypesInformation initial paramTypes
    +
    +                    div [
    +                        Class "fsdocs-block"
    +                    ] [
    +
    +                        div [
    +                            Class "actions-buttons"
    +                        ] [
    +                            yield! sourceLink entity.SourceLocation
    +                            yield! copyXmlSigIconForSymbol entity.Symbol
    +                            yield! copyXmlSigIconForSymbolMarkdown entity.Symbol
    +                        ]
     
    -    let renderMembers header tableHeader (members: ApiDocMember list) =
    -        [ if members.Length > 0 then
    -              h3 [] [ !!header ]
    -
    -              table [ Class "table outer-list fsdocs-member-list" ] [
    -                  thead [] [
    -                      tr [] [
    -                          td [ Class "fsdocs-member-list-header" ] [ !!tableHeader ]
    -                          td [ Class "fsdocs-member-list-header" ] [ !! "Description"; fsdocsDetailsToggle [] ]
    -                      ]
    -                  ]
    -                  tbody [] [
    -                      for m in members do
    -                          tr [] [
    -                              td [ Class "fsdocs-member-usage" ] [
    -
    -                                  codeWithToolTip [
    -                                      // This adds #MemberName anchor. These may be ambiguous due to overloading
    -                                      p [] [ a [ Id m.Name ] [ a [ Href("#" + m.Name) ] [ embed m.UsageHtml ] ] ]
    -                                  ] [
    -                                      div [ Class "member-tooltip" ] [
    -                                          !! "Full Usage: "
    -                                          embed m.UsageHtml
    -                                          br []
    -                                          br []
    -                                          if not m.Parameters.IsEmpty then
    -                                              !! "Parameters: "
    -
    -                                              ul [] [
    -                                                  for p in m.Parameters do
    -                                                      span [] [
    -                                                          b [] [ !!p.ParameterNameText ]
    -                                                          !! ":"
    -                                                          embed p.ParameterType
    -                                                          match p.ParameterDocs with
    -                                                          | None -> ()
    -                                                          | Some d ->
    -                                                              !! " - "
    -                                                              embed d
    -                                                      ]
    -
    -                                                      br []
    -                                              ]
    -
    -                                              br []
    -                                          match m.ReturnInfo.ReturnType with
    -                                          | None -> ()
    -                                          | Some(_, rty) ->
    -                                              span [] [
    -                                                  !!(if m.Kind <> ApiDocMemberKind.RecordField then
    -                                                         "Returns: "
    -                                                     else
    -                                                         "Field type: ")
    -                                                  embed rty
    -                                              ]
    -
    -                                              match m.ReturnInfo.ReturnDocs with
    -                                              | None -> ()
    -                                              | Some d -> embed d
    -
    -                                              br []
    -                                          //!! "Signature: "
    -                                          //encode(m.SignatureTooltip)
    -                                          if not m.Modifiers.IsEmpty then
    -                                              !! "Modifiers: "
    -                                              encode (m.FormatModifiers)
    -                                              br []
    -
    -                                              // We suppress the display of ill-formatted type parameters for places
    -                                              // where these have not been explicitly declared
    -                                              match m.FormatTypeArguments with
    -                                              | None -> ()
    -                                              | Some v ->
    -                                                  !! "Type parameters: "
    -                                                  encode (v)
    -                                      ]
    -                                  ]
    -                              ]
    -
    -                              let smry =
    -                                  div [ Class "fsdocs-summary" ] [
    -                                      fsdocsSummary m.Comment.Summary
    -                                      div [ Class "icon-button-row" ] [
    -                                          yield! sourceLink m.SourceLocation
    -                                          yield! copyXmlSigIconForSymbol m.Symbol
    -                                          yield! copyXmlSigIconForSymbolMarkdown m.Symbol
    -                                      ]
    -                                  ]
    -
    -                              let dtls =
    -                                  [ match m.Comment.Remarks with
    -                                    | Some r -> p [ Class "fsdocs-remarks" ] [ embed r ]
    -                                    | None -> ()
    -
    -                                    match m.ExtendedType with
    -                                    | Some(_, extendedTypeHtml) -> p [] [ !! "Extended Type: "; embed extendedTypeHtml ]
    -                                    | _ -> ()
    -
    -                                    if not m.Parameters.IsEmpty then
    -                                        dl [ Class "fsdocs-params" ] [
    -                                            for parameter in m.Parameters do
    -                                                dt [ Class "fsdocs-param" ] [
    -                                                    span [ Class "fsdocs-param-name" ] [ !!parameter.ParameterNameText ]
    -                                                    !! ":"
    -                                                    embed parameter.ParameterType
    +                        // This is a value
    +                        if paramTypesInfo.Infos.IsEmpty then
    +                            div [
    +                                Class "fsdocs-api-code"
    +                            ] [
    +                                div [] [
    +                                    Html.val'
    +                                    Html.space
    +                                    !!entity.Name
    +                                    Html.space
    +                                    Html.colon
    +                                    !!returnHtml
    +                                ]
    +                            ]
    +
    +                        // This is a function
    +                        else
    +
    +                            div [
    +                                Class "fsdocs-api-code"
    +                            ] [
    +                                [
    +                                    TextNode.Div [
    +                                        TextNode.Keyword "val"
    +                                        TextNode.Space
    +                                        TextNode.AnchorWithId($"#{entity.Name}", entity.Name, entity.Name)
    +                                        TextNode.Space
    +                                        TextNode.Colon
    +                                    ]
    +                                ]
    +                                |> TextNode.Node
    +                                |> TextNode.ToHtmlElement
    +
    +                                for index in 0 .. paramTypesInfo.Infos.Length - 1 do
    +                                    let (name, returnType) = paramTypesInfo.Infos.[index]
    +
    +                                    div [] [
    +                                        Html.spaces 4 // Equivalent to 'val '
    +                                        !!name
    +                                        Html.spaces (paramTypesInfo.MaxNameLength - name.Length + 1) // Complete with space to align ':'
    +                                        Html.colon
    +                                        Html.space
    +                                        !! returnType.HtmlElement.ToMinifiedHtml()
    +
    +                                        Html.spaces (paramTypesInfo.MaxReturnTypeLength - returnType.Length + 1) // Complete with space to align '->'
    +
    +                                        // Don't add the arrow for the last parameter
    +                                        if index <> paramTypesInfo.Infos.Length - 1 then
    +                                            Html.arrow
    +                                    ]
    +                                    |> Html.minify
    +
    +                                div [] [
    +                                    Html.spaces (4 + paramTypesInfo.MaxNameLength + 1) // Equivalent to 'val ' + the max length of parameter name + ':'
    +                                    Html.arrow
    +                                    Html.space
    +                                    !!returnHtml
    +                                ]
    +                                |> Html.minify
    +                            ]
    +
    +                        match entity.Comment.Xml with
    +                        | Some xmlComment ->
    +                            let comment = xmlComment.ToString()
    +                            !!(CommentFormatter.formatSummaryOnly comment)
    +
    +                            if not paramTypesInfo.Infos.IsEmpty then
    +                                p [] [
    +                                    strong [] [
    +                                        !! "Parameters"
    +                                    ]
    +                                ]
    +
    +                                for (name, returnType) in paramTypesInfo.Infos do
    +                                    let paramDoc =
    +                                        CommentFormatter.tryFormatParam name comment
    +                                        |> Option.map (fun paramDoc -> !!paramDoc)
    +                                        |> Option.defaultValue Html.nothing
    +
    +                                    div [
    +                                        Class "fsdocs-doc-parameter"
    +                                    ] [
    +                                        [
    +                                            TextNode.DivWithClass(
    +                                                "fsdocs-api-code",
    +                                                [
    +                                                    TextNode.Property name
    +                                                    TextNode.Space
    +                                                    TextNode.Colon
    +                                                    TextNode.Space
    +                                                    returnType
                                                     ]
    +                                            )
    +                                        ]
    +                                        |> TextNode.Node
    +                                        |> TextNode.ToHtmlElement
     
    -                                                dd [ Class "fsdocs-param-docs" ] [
    -                                                    match parameter.ParameterDocs with
    -                                                    | None -> ()
    -                                                    | Some d -> p [] [ embed d ]
    +                                        paramDoc
    +                                    ]
    +
    +                            match CommentFormatter.tryFormatReturnsOnly comment with
    +                            | Some returnDoc ->
    +                                p [] [
    +                                    strong [] [
    +                                        !! "Returns"
    +                                    ]
    +                                ]
    +
    +                                !!returnDoc
    +
    +                            | None -> ()
    +
    +                        // TODO: Should we r``ender a minimal documentation here with the information we have?
    +                        // For example, we can render the list of parameters and the return type
    +                        // This is to make the documentation more consistent
    +                        // However, these minimal information will be rondontant with the information displayed in the signature
    +                        | None -> ()
    +                    ]
    +
    +            //   hr []
    +
    +            ]
    +
    +    let renderMembers header tableHeader (members: ApiDocMember list) =
    +        [
    +            if members.Length > 0 then
    +                h3 [] [
    +                    !!header
    +                ]
    +
    +                table [
    +                    Class "table outer-list fsdocs-member-list"
    +                ] [
    +                    thead [] [
    +                        tr [] [
    +                            td [
    +                                Class "fsdocs-member-list-header"
    +                            ] [
    +                                !!tableHeader
    +                            ]
    +                            td [
    +                                Class "fsdocs-member-list-header"
    +                            ] [
    +                                !! "Description"
    +                                fsdocsDetailsToggle []
    +                            ]
    +                        ]
    +                    ]
    +                    tbody [] [
    +                        for m in members do
    +                            tr [] [
    +                                td [
    +                                    Class "fsdocs-member-usage"
    +                                ] [
    +
    +                                    codeWithToolTip [
    +                                        // This adds #MemberName anchor. These may be ambiguous due to overloading
    +                                        p [] [
    +                                            a [
    +                                                Id m.Name
    +                                            ] [
    +                                                a [
    +                                                    Href("#" + m.Name)
    +                                                ] [
    +                                                    embed m.UsageHtml
                                                     ]
    +                                            ]
                                             ]
    +                                    ] [
    +                                        div [
    +                                            Class "member-tooltip"
    +                                        ] [
    +                                            !! "Full Usage: "
    +                                            embed m.UsageHtml
    +                                            br []
    +                                            br []
    +                                            if not m.Parameters.IsEmpty then
    +                                                !! "Parameters: "
    +
    +                                                ul [] [
    +                                                    for p in m.Parameters do
    +                                                        span [] [
    +                                                            b [] [
    +                                                                !!p.ParameterNameText
    +                                                            ]
    +                                                            !! ":"
    +                                                            embed p.ParameterType
    +                                                            match p.ParameterDocs with
    +                                                            | None -> ()
    +                                                            | Some d ->
    +                                                                !! " - "
    +                                                                embed d
    +                                                        ]
    +
    +                                                        br []
    +                                                ]
     
    -                                    match m.ReturnInfo.ReturnType with
    -                                    | None -> ()
    -                                    | Some(_, returnTypeHtml) ->
    -                                        dl [ Class "fsdocs-returns" ] [
    -                                            dt [] [
    -                                                span [ Class "fsdocs-return-name" ] [
    +                                                br []
    +                                            match m.ReturnInfo.ReturnType with
    +                                            | None -> ()
    +                                            | Some(_, rty) ->
    +                                                span [] [
                                                         !!(if m.Kind <> ApiDocMemberKind.RecordField then
                                                                "Returns: "
                                                            else
                                                                "Field type: ")
    +                                                    embed rty
                                                     ]
    -                                                embed returnTypeHtml
    -                                            ]
    -                                            dd [ Class "fsdocs-return-docs" ] [
    +
                                                     match m.ReturnInfo.ReturnDocs with
                                                     | None -> ()
    -                                                | Some r -> p [] [ embed r ]
    -                                            ]
    +                                                | Some d -> embed d
    +
    +                                                br []
    +                                            //!! "Signature: "
    +                                            //encode(m.SignatureTooltip)
    +                                            if not m.Modifiers.IsEmpty then
    +                                                !! "Modifiers: "
    +                                                encode (m.FormatModifiers)
    +                                                br []
    +
    +                                                // We suppress the display of ill-formatted type parameters for places
    +                                                // where these have not been explicitly declared
    +                                                match m.FormatTypeArguments with
    +                                                | None -> ()
    +                                                | Some v ->
    +                                                    !! "Type parameters: "
    +                                                    encode (v)
                                             ]
    +                                    ]
    +                                ]
    +
    +                                let smry =
    +                                    div [
    +                                        Class "fsdocs-summary"
    +                                    ] [
    +                                        fsdocsSummary m.Comment.Summary
    +                                        div [
    +                                            Class "icon-button-row"
    +                                        ] [
    +                                            yield! sourceLink m.SourceLocation
    +                                            yield! copyXmlSigIconForSymbol m.Symbol
    +                                            yield! copyXmlSigIconForSymbolMarkdown m.Symbol
    +                                        ]
    +                                    ]
     
    -                                    if not m.Comment.Exceptions.IsEmpty then
    -                                        //p [] [ !! "Exceptions:" ]
    -                                        table [ Class "fsdocs-exception-list" ] [
    -                                            for (nm, link, html) in m.Comment.Exceptions do
    -                                                tr [] [
    -                                                    td
    -                                                        []
    -                                                        (match link with
    -                                                         | None -> []
    -                                                         | Some href -> [ a [ Href href ] [ !!nm ] ])
    -                                                    td [] [ embed html ]
    +                                let dtls =
    +                                    [
    +                                        match m.Comment.Remarks with
    +                                        | Some r ->
    +                                            p [
    +                                                Class "fsdocs-remarks"
    +                                            ] [
    +                                                embed r
    +                                            ]
    +                                        | None -> ()
    +
    +                                        match m.ExtendedType with
    +                                        | Some(_, extendedTypeHtml) ->
    +                                            p [] [
    +                                                !! "Extended Type: "
    +                                                embed extendedTypeHtml
    +                                            ]
    +                                        | _ -> ()
    +
    +                                        if not m.Parameters.IsEmpty then
    +                                            dl [
    +                                                Class "fsdocs-params"
    +                                            ] [
    +                                                for parameter in m.Parameters do
    +                                                    dt [
    +                                                        Class "fsdocs-param"
    +                                                    ] [
    +                                                        span [
    +                                                            Class "fsdocs-param-name"
    +                                                        ] [
    +                                                            !!parameter.ParameterNameText
    +                                                        ]
    +                                                        !! ":"
    +                                                        embed parameter.ParameterType
    +                                                    ]
    +
    +                                                    dd [
    +                                                        Class "fsdocs-param-docs"
    +                                                    ] [
    +                                                        match parameter.ParameterDocs with
    +                                                        | None -> ()
    +                                                        | Some d ->
    +                                                            p [] [
    +                                                                embed d
    +                                                            ]
    +                                                    ]
    +                                            ]
    +
    +                                        match m.ReturnInfo.ReturnType with
    +                                        | None -> ()
    +                                        | Some(_, returnTypeHtml) ->
    +                                            dl [
    +                                                Class "fsdocs-returns"
    +                                            ] [
    +                                                dt [] [
    +                                                    span [
    +                                                        Class "fsdocs-return-name"
    +                                                    ] [
    +                                                        !!(if m.Kind <> ApiDocMemberKind.RecordField then
    +                                                               "Returns: "
    +                                                           else
    +                                                               "Field type: ")
    +                                                    ]
    +                                                    embed returnTypeHtml
                                                     ]
    -                                        ]
    +                                                dd [
    +                                                    Class "fsdocs-return-docs"
    +                                                ] [
    +                                                    match m.ReturnInfo.ReturnDocs with
    +                                                    | None -> ()
    +                                                    | Some r ->
    +                                                        p [] [
    +                                                            embed r
    +                                                        ]
    +                                                ]
    +                                            ]
     
    -                                    for e in m.Comment.Notes do
    -                                        h5 [ Class "fsdocs-note-header" ] [ !! "Note" ]
    +                                        if not m.Comment.Exceptions.IsEmpty then
    +                                            //p [] [ !! "Exceptions:" ]
    +                                            table [
    +                                                Class "fsdocs-exception-list"
    +                                            ] [
    +                                                for (nm, link, html) in m.Comment.Exceptions do
    +                                                    tr [] [
    +                                                        td
    +                                                            []
    +                                                            (match link with
    +                                                             | None -> []
    +                                                             | Some href ->
    +                                                                 [
    +                                                                     a [
    +                                                                         Href href
    +                                                                     ] [
    +                                                                         !!nm
    +                                                                     ]
    +                                                                 ])
    +                                                        td [] [
    +                                                            embed html
    +                                                        ]
    +                                                    ]
    +                                            ]
     
    -                                        p [ Class "fsdocs-note" ] [ embed e ]
    +                                        for e in m.Comment.Notes do
    +                                            h5 [
    +                                                Class "fsdocs-note-header"
    +                                            ] [
    +                                                !! "Note"
    +                                            ]
     
    -                                    for e in m.Comment.Examples do
    -                                        h5 [ Class "fsdocs-example-header" ] [ !! "Example" ]
    +                                            p [
    +                                                Class "fsdocs-note"
    +                                            ] [
    +                                                embed e
    +                                            ]
     
    -                                        p [
    -                                            yield Class "fsdocs-example"
    -                                            match e.Id with
    -                                            | None -> ()
    -                                            | Some id -> yield Id id
    -                                        ] [ embed e ]
    +                                        for e in m.Comment.Examples do
    +                                            h5 [
    +                                                Class "fsdocs-example-header"
    +                                            ] [
    +                                                !! "Example"
    +                                            ]
    +
    +                                            p [
    +                                                yield Class "fsdocs-example"
    +                                                match e.Id with
    +                                                | None -> ()
    +                                                | Some id -> yield Id id
    +                                            ] [
    +                                                embed e
    +                                            ]
                                         //if m.IsObsolete then
                                         //    obsoleteMessage m.ObsoleteMessage
     
    @@ -448,79 +620,116 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) =
                                         //    p [] [!!"CompiledName: "; code [] [!!m.Details.FormatCompiledName]]
                                         ]
     
    -                              td [ Class "fsdocs-member-xmldoc" ] [
    -                                  if List.isEmpty dtls then
    -                                      smry
    -                                  elif String.IsNullOrWhiteSpace(m.Comment.Summary.HtmlText) then
    -                                      div [ Class "fsdocs-member-xmldoc-column" ] [
    -                                          div [ Class "icon-button-row" ] (sourceLink m.SourceLocation)
    -                                          yield! dtls
    -                                      ]
    -                                  else
    -                                      details [] ((summary [] [ smry ]) :: dtls)
    -                              ]
    -                          ]
    -                  ]
    -              ] ]
    +                                td [
    +                                    Class "fsdocs-member-xmldoc"
    +                                ] [
    +                                    if List.isEmpty dtls then
    +                                        smry
    +                                    elif String.IsNullOrWhiteSpace(m.Comment.Summary.HtmlText) then
    +                                        div [
    +                                            Class "fsdocs-member-xmldoc-column"
    +                                        ] [
    +                                            div
    +                                                [
    +                                                    Class "icon-button-row"
    +                                                ]
    +                                                (sourceLink m.SourceLocation)
    +                                            yield! dtls
    +                                        ]
    +                                    else
    +                                        details
    +                                            []
    +                                            ((summary [] [
    +                                                smry
    +                                             ])
    +                                             :: dtls)
    +                                ]
    +                            ]
    +                    ]
    +                ]
    +        ]
     
         let renderEntities (entities: ApiDocEntity list) =
    -        [ if entities.Length > 0 then
    -              let hasTypes = entities |> List.exists (fun e -> e.IsTypeDefinition)
    -
    -              let hasModules = entities |> List.exists (fun e -> not e.IsTypeDefinition)
    -
    -              table [ Class "table outer-list fsdocs-entity-list" ] [
    -                  thead [] [
    -                      tr [] [
    -                          td [] [
    -                              !!(if hasTypes && hasModules then "Type/Module"
    -                                 elif hasTypes then "Type"
    -                                 else "Modules")
    -                          ]
    -                          td [] [ !! "Description" ]
    -                      ]
    -                  ]
    -                  tbody [] [
    -                      for e in entities do
    -                          tr [] [
    -                              td [ Class "fsdocs-entity-name" ] [
    -                                  let nm = e.Name
    -
    -                                  let multi = (entities |> List.filter (fun e -> e.Name = nm) |> List.length) > 1
    -
    -                                  let nmWithSiffix =
    -                                      if multi then
    -                                          (if e.IsTypeDefinition then
    -                                               nm + " (Type)"
    -                                           else
    -                                               nm + " (Module)")
    -                                      else
    -                                          nm
    -
    -                                  // This adds #EntityName anchor. These may currently be ambiguous
    -                                  p [] [
    -                                      a [ Name nm ] [
    -                                          a [ Href(e.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) ] [
    -                                              !!nmWithSiffix
    -                                          ]
    -                                      ]
    -                                  ]
    -                              ]
    -                              td [ Class "fsdocs-entity-xmldoc" ] [
    -                                  div [] [
    -
    -                                      div [ Class "fsdocs-summary-contents" ] [ !!(formatXmlComment e.Comment.Xml) ]
    -
    -                                      div [ Class "icon-button-row" ] [
    -                                          yield! sourceLink e.SourceLocation
    -                                          yield! copyXmlSigIconForSymbol e.Symbol
    -                                          yield! copyXmlSigIconForSymbolMarkdown e.Symbol
    -                                      ]
    -                                  ]
    -                              ]
    -                          ]
    -                  ]
    -              ] ]
    +        [
    +            if entities.Length > 0 then
    +                let hasTypes = entities |> List.exists (fun e -> e.IsTypeDefinition)
    +
    +                let hasModules = entities |> List.exists (fun e -> not e.IsTypeDefinition)
    +
    +                table [
    +                    Class "table outer-list fsdocs-entity-list"
    +                ] [
    +                    thead [] [
    +                        tr [] [
    +                            td [] [
    +                                !!(if hasTypes && hasModules then
    +                                       "Type/Module"
    +                                   elif hasTypes then
    +                                       "Type"
    +                                   else
    +                                       "Modules")
    +                            ]
    +                            td [] [
    +                                !! "Description"
    +                            ]
    +                        ]
    +                    ]
    +                    tbody [] [
    +                        for e in entities do
    +                            tr [] [
    +                                td [
    +                                    Class "fsdocs-entity-name"
    +                                ] [
    +                                    let nm = e.Name
    +
    +                                    let multi = (entities |> List.filter (fun e -> e.Name = nm) |> List.length) > 1
    +
    +                                    let nmWithSiffix =
    +                                        if multi then
    +                                            (if e.IsTypeDefinition then
    +                                                 nm + " (Type)"
    +                                             else
    +                                                 nm + " (Module)")
    +                                        else
    +                                            nm
    +
    +                                    // This adds #EntityName anchor. These may currently be ambiguous
    +                                    p [] [
    +                                        a [
    +                                            Name nm
    +                                        ] [
    +                                            a [
    +                                                Href(e.Url(root, collectionName, qualify, model.FileExtensions.InUrl))
    +                                            ] [
    +                                                !!nmWithSiffix
    +                                            ]
    +                                        ]
    +                                    ]
    +                                ]
    +                                td [
    +                                    Class "fsdocs-entity-xmldoc"
    +                                ] [
    +                                    div [] [
    +
    +                                        div [
    +                                            Class "fsdocs-summary-contents"
    +                                        ] [
    +                                            !!(formatXmlComment e.Comment.Xml)
    +                                        ]
    +
    +                                        div [
    +                                            Class "icon-button-row"
    +                                        ] [
    +                                            yield! sourceLink e.SourceLocation
    +                                            yield! copyXmlSigIconForSymbol e.Symbol
    +                                            yield! copyXmlSigIconForSymbolMarkdown e.Symbol
    +                                        ]
    +                                    ]
    +                                ]
    +                            ]
    +                    ]
    +                ]
    +        ]
     
         let entityContent (info: ApiDocEntityInfo) =
             // Get all the members & comment for the type
    @@ -535,267 +744,385 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) =
                 | Some m when m.RequiresQualifiedAccess -> m.Name + "." + entity.Name
                 | _ -> entity.Name
     
    -        [ h2 [] [ !!(usageName + (if entity.IsTypeDefinition then " Type" else " Module")) ]
    -          dl [ Class "fsdocs-metadata" ] [
    -              dt [] [
    -                  !! "Namespace: "
    -                  a [ Href(info.Namespace.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) ] [
    -                      !!info.Namespace.Name
    -                  ]
    -              ]
    -              dt [] [ !!("Assembly: " + entity.Assembly.Name + ".dll") ]
    -
    -              match info.ParentModule with
    -              | None -> ()
    -              | Some parentModule ->
    -                  dt [] [
    -                      !! "Parent Module: "
    -                      a [ Href(parentModule.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) ] [
    -                          !!parentModule.Name
    -                      ]
    -                  ]
    -
    -
    -              match entity.AbbreviatedType with
    -              | Some(_, abbreviatedTypHtml) -> dt [] [ !! "Abbreviation For: "; embed abbreviatedTypHtml ]
    -
    -              | None -> ()
    -
    -              match entity.BaseType with
    -              | Some(_, baseTypeHtml) -> dt [] [ !! "Base Type: "; embed baseTypeHtml ]
    -              | None -> ()
    -
    -              match entity.AllInterfaces with
    -              | [] -> ()
    -              | l ->
    -                  dt [] [
    -                      !!("All Interfaces: ")
    -                      for (i, (_, ityHtml)) in Seq.indexed l do
    -                          if i <> 0 then
    -                              !! ", "
    -
    -                          embed ityHtml
    -                  ]
    -
    -              if entity.Symbol.IsValueType then
    -                  dt [] [ !!("Kind: Struct") ]
    -
    -              match entity.DelegateSignature with
    -              | Some(_, delegateSigHtml) -> dt [] [ !!("Delegate Signature: "); embed delegateSigHtml ]
    -              | None -> ()
    -
    -              if entity.Symbol.IsProvided then
    -                  dt [] [ !!("This is a provided type definition") ]
    -
    -              if entity.Symbol.IsAttributeType then
    -                  dt [] [ !!("This is an attribute type definition") ]
    -
    -              if entity.Symbol.IsEnum then
    -                  dt [] [ !!("This is an enum type definition") ]
    -
    -          //if info.Entity.IsObsolete then
    -          //    obsoleteMessage entity.ObsoleteMessage
    -          ]
    -          // Show the summary (and sectioned docs without any members)
    -          div [ Class "fsdocs-xmldoc" ] [
    -              div [] [
    -                  //yield! copyXmlSigIconForSymbol entity.Symbol
    -                  //yield! sourceLink entity.SourceLocation
    -                  fsdocsSummary entity.Comment.Summary
    -              ]
    -              // Show the remarks etc.
    -              match entity.Comment.Remarks with
    -              | Some r -> p [ Class "fsdocs-remarks" ] [ embed r ]
    -              | None -> ()
    -              for note in entity.Comment.Notes do
    -                  h5 [ Class "fsdocs-note-header" ] [ !! "Note" ]
    -
    -                  p [ Class "fsdocs-note" ] [ embed note ]
    -
    -              for example in entity.Comment.Examples do
    -                  h5 [ Class "fsdocs-example-header" ] [ !! "Example" ]
    -
    -                  p [ Class "fsdocs-example" ] [ embed example ]
    -
    -          ]
    -
    -          if (byCategory.Length > 1) then
    -              // If there is more than 1 category in the type, generate TOC
    -              h3 [] [ !! "Table of contents" ]
    -
    -              ul [] [
    -                  for (index, _, name) in byCategory do
    -                      li [] [ a [ Href(sprintf "#section%d" index) ] [ !!name ] ]
    -              ]
    -
    -          //
    -
    -          let nestedEntities = entity.NestedEntities |> List.filter (fun e -> not e.IsObsolete)
    -
    -          if (nestedEntities.Length > 0) then
    -              div [] [
    -                  h3 [] [
    -                      !!(if nestedEntities |> List.forall (fun e -> not e.IsTypeDefinition) then
    -                             "Nested modules"
    -                         elif nestedEntities |> List.forall (fun e -> e.IsTypeDefinition) then
    -                             "Types"
    -                         else
    -                             "Types and nested modules")
    -                  ]
    -                  yield! renderEntities nestedEntities
    -              ]
    -
    -          for (index, ms, name) in byCategory do
    -              // Iterate over all the categories and print members. If there are more than one
    -              // categories, print the category heading (as 

    ) and add XML comment from the type - // that is related to this specific category. - if (byCategory.Length > 1) then - h2 [ Id(sprintf "section%d" index) ] [ !!name ] - // 

    - let functionsOrValues = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.ValueOrFunction) - let extensions = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.TypeExtension) - let activePatterns = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.ActivePattern) - let unionCases = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.UnionCase) - let recordFields = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.RecordField) - let staticParameters = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.StaticParameter) - let constructors = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.Constructor) - let instanceMembers = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.InstanceMember) - let staticMembers = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.StaticMember) - div [] (renderValueOrFunctions functionsOrValues) - div [] (renderMembers "Type extensions" "Type extension" extensions) - div [] (renderMembers "Active patterns" "Active pattern" activePatterns) - div [] (renderMembers "Union cases" "Union case" unionCases) - div [] (renderMembers "Record fields" "Record Field" recordFields) - div [] (renderMembers "Static parameters" "Static parameters" staticParameters) - div [] (renderMembers "Constructors" "Constructor" constructors) - div [] (renderMembers "Instance members" "Instance member" instanceMembers) - div [] (renderMembers "Static members" "Static member" staticMembers) ] + [ + h2 [] [ + !!(usageName + + (if entity.IsTypeDefinition then + " Type" + else + " Module")) + ] + dl [ + Class "fsdocs-metadata" + ] [ + dt [] [ + !! "Namespace: " + a [ + Href(info.Namespace.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) + ] [ + !!info.Namespace.Name + ] + ] + dt [] [ + !!("Assembly: " + entity.Assembly.Name + ".dll") + ] + + match info.ParentModule with + | None -> () + | Some parentModule -> + dt [] [ + !! "Parent Module: " + a [ + Href(parentModule.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) + ] [ + !!parentModule.Name + ] + ] + + match entity.AbbreviatedType with + | Some(_, abbreviatedTypHtml) -> + dt [] [ + !! "Abbreviation For: " + embed abbreviatedTypHtml + ] + + | None -> () + + match entity.BaseType with + | Some(_, baseTypeHtml) -> + dt [] [ + !! "Base Type: " + embed baseTypeHtml + ] + | None -> () + + match entity.AllInterfaces with + | [] -> () + | l -> + dt [] [ + !!("All Interfaces: ") + for (i, (_, ityHtml)) in Seq.indexed l do + if i <> 0 then + !! ", " + + embed ityHtml + ] + + if entity.Symbol.IsValueType then + dt [] [ + !!("Kind: Struct") + ] + + match entity.DelegateSignature with + | Some(_, delegateSigHtml) -> + dt [] [ + !!("Delegate Signature: ") + embed delegateSigHtml + ] + | None -> () + + if entity.Symbol.IsProvided then + dt [] [ + !!("This is a provided type definition") + ] + + if entity.Symbol.IsAttributeType then + dt [] [ + !!("This is an attribute type definition") + ] + + if entity.Symbol.IsEnum then + dt [] [ + !!("This is an enum type definition") + ] + + //if info.Entity.IsObsolete then + // obsoleteMessage entity.ObsoleteMessage + ] + // Show the summary (and sectioned docs without any members) + div [ + Class "fsdocs-xmldoc" + ] [ + div [] [ + //yield! copyXmlSigIconForSymbol entity.Symbol + //yield! sourceLink entity.SourceLocation + fsdocsSummary entity.Comment.Summary + ] + // Show the remarks etc. + match entity.Comment.Remarks with + | Some r -> + p [ + Class "fsdocs-remarks" + ] [ + embed r + ] + | None -> () + for note in entity.Comment.Notes do + h5 [ + Class "fsdocs-note-header" + ] [ + !! "Note" + ] + + p [ + Class "fsdocs-note" + ] [ + embed note + ] + + for example in entity.Comment.Examples do + h5 [ + Class "fsdocs-example-header" + ] [ + !! "Example" + ] + + p [ + Class "fsdocs-example" + ] [ + embed example + ] + + ] + + if (byCategory.Length > 1) then + // If there is more than 1 category in the type, generate TOC + h3 [] [ + !! "Table of contents" + ] + + ul [] [ + for (index, _, name) in byCategory do + li [] [ + a [ + Href(sprintf "#section%d" index) + ] [ + !!name + ] + ] + ] + + // + + let nestedEntities = entity.NestedEntities |> List.filter (fun e -> not e.IsObsolete) + + if (nestedEntities.Length > 0) then + div [] [ + h3 [] [ + !!(if nestedEntities |> List.forall (fun e -> not e.IsTypeDefinition) then + "Nested modules" + elif nestedEntities |> List.forall (fun e -> e.IsTypeDefinition) then + "Types" + else + "Types and nested modules") + ] + yield! renderEntities nestedEntities + ] + + for (index, ms, name) in byCategory do + // Iterate over all the categories and print members. If there are more than one + // categories, print the category heading (as

    ) and add XML comment from the type + // that is related to this specific category. + if (byCategory.Length > 1) then + h2 [ + Id(sprintf "section%d" index) + ] [ + !!name + ] + // 

    + let functionsOrValues = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.ValueOrFunction) + let extensions = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.TypeExtension) + let activePatterns = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.ActivePattern) + let unionCases = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.UnionCase) + let recordFields = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.RecordField) + let staticParameters = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.StaticParameter) + let constructors = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.Constructor) + let instanceMembers = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.InstanceMember) + let staticMembers = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.StaticMember) + div [] (renderValueOrFunctions functionsOrValues) + div [] (renderMembers "Type extensions" "Type extension" extensions) + div [] (renderMembers "Active patterns" "Active pattern" activePatterns) + div [] (renderMembers "Union cases" "Union case" unionCases) + div [] (renderMembers "Record fields" "Record Field" recordFields) + div [] (renderMembers "Static parameters" "Static parameters" staticParameters) + div [] (renderMembers "Constructors" "Constructor" constructors) + div [] (renderMembers "Instance members" "Instance member" instanceMembers) + div [] (renderMembers "Static members" "Static member" staticMembers) + ] let namespaceContent (nsIndex, ns: ApiDocNamespace) = let allByCategory = Categorise.entities (nsIndex, ns, false) - [ if allByCategory.Length > 0 then - h2 [ Id ns.UrlHash ] [ !!(ns.Name + " Namespace") ] + [ + if allByCategory.Length > 0 then + h2 [ + Id ns.UrlHash + ] [ + !!(ns.Name + " Namespace") + ] - div [ Class "fsdocs-xmldoc" ] [ - match ns.NamespaceDocs with - | Some nsdocs -> - p [] [ embed nsdocs.Summary ] + div [ + Class "fsdocs-xmldoc" + ] [ + match ns.NamespaceDocs with + | Some nsdocs -> + p [] [ + embed nsdocs.Summary + ] - match nsdocs.Remarks with - | Some r -> p [] [ embed r ] - | None -> () + match nsdocs.Remarks with + | Some r -> + p [] [ + embed r + ] + | None -> () - | None -> () - ] + | None -> () + ] - if (allByCategory.Length > 1) then - h3 [] [ !! "Contents" ] + if (allByCategory.Length > 1) then + h3 [] [ + !! "Contents" + ] - ul [] [ - for category in allByCategory do - li [] [ a [ Href("#category-" + category.CategoryIndex) ] [ !!category.CategoryName ] ] - ] + ul [] [ + for category in allByCategory do + li [] [ + a [ + Href("#category-" + category.CategoryIndex) + ] [ + !!category.CategoryName + ] + ] + ] - for category in allByCategory do - if (allByCategory.Length > 1) then - h3 [] [ - a [ - Class "anchor" - Name("category-" + category.CategoryIndex) - Href("#category-" + category.CategoryIndex) - ] [ !!category.CategoryName ] - ] + for category in allByCategory do + if (allByCategory.Length > 1) then + h3 [] [ + a [ + Class "anchor" + Name("category-" + category.CategoryIndex) + Href("#category-" + category.CategoryIndex) + ] [ + !!category.CategoryName + ] + ] - yield! renderEntities category.CategoryEntites ] + yield! renderEntities category.CategoryEntites + ] let tableOfNamespacesAux () = - [ let categorise = Categorise.model model - - for _allByCategory, ns in categorise do - - // Generate the entry for the namespace - tr [] [ - td [] [ - a [ - Href(ns.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) - HtmlProperties.Title ns.Name - ] [ !!ns.Name ] - ] - td [] [ - match ns.NamespaceDocs with - | Some nsdocs -> embed nsdocs.Summary - | None -> () - ] - ] ] + [ + let categorise = Categorise.model model + + for _allByCategory, ns in categorise do + + // Generate the entry for the namespace + tr [] [ + td [] [ + a [ + Href(ns.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) + HtmlProperties.Title ns.Name + ] [ + !!ns.Name + ] + ] + td [] [ + match ns.NamespaceDocs with + | Some nsdocs -> embed nsdocs.Summary + | None -> () + ] + ] + ] let listOfNamespacesNavAux otherDocs (nsOpt: ApiDocNamespace option) = [ - // For FSharp.Core we make all entries available to other docs else there's not a lot else to show. - // - // For non-FSharp.Core we only show one link "API Reference" in the nav menu - if otherDocs && model.Collection.CollectionName <> "FSharp.Core" then - li [ Class "nav-header" ] [ !! "API Reference" ] - - li [ Class "nav-item" ] [ - a [ - Class "nav-link" - Href(model.IndexFileUrl(root, collectionName, qualify, model.FileExtensions.InUrl)) - ] [ !! "All Namespaces" ] - ] - else - - let categorise = Categorise.model model - - let someExist = categorise.Length > 0 - - if someExist then - li [ Class "nav-header" ] [ !! "Namespaces" ] - - for allByCategory, ns in categorise do - - // Generate the entry for the namespace - li [ - Class( - "nav-item" - + - // add the 'active' class if this is the namespace of the thing being shown - match nsOpt with - | Some ns2 when ns.Name = ns2.Name -> " active" - | _ -> "" - ) - ] [ - span [] [ - a [ - Class( - "nav-link" - + - // add the 'active' class if this is the namespace of the thing being shown - match nsOpt with - | Some ns2 when ns.Name = ns2.Name -> " active" - | _ -> "" - ) - Href(ns.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) - ] [ !!ns.Name ] - - ] - ] - - // In the navigation bar generate the expanded list of entities - // for the active namespace - match nsOpt with - | Some ns2 when ns.Name = ns2.Name -> - ul [ Custom("list-style-type", "none") (* Class "navbar-nav " *) ] [ - for category in allByCategory do - for e in category.CategoryEntites do - li [ Class "nav-item" ] [ - a [ - Class "nav-link" - Href(e.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) - ] [ !!e.Name ] - ] - ] - | _ -> () ] + // For FSharp.Core we make all entries available to other docs else there's not a lot else to show. + // + // For non-FSharp.Core we only show one link "API Reference" in the nav menu + if otherDocs && model.Collection.CollectionName <> "FSharp.Core" then + li [ + Class "nav-header" + ] [ + !! "API Reference" + ] + + li [ + Class "nav-item" + ] [ + a [ + Class "nav-link" + Href(model.IndexFileUrl(root, collectionName, qualify, model.FileExtensions.InUrl)) + ] [ + !! "All Namespaces" + ] + ] + else + + let categorise = Categorise.model model + + let someExist = categorise.Length > 0 + + if someExist then + li [ + Class "nav-header" + ] [ + !! "Namespaces" + ] + + for allByCategory, ns in categorise do + + // Generate the entry for the namespace + li [ + Class( + "nav-item" + + + // add the 'active' class if this is the namespace of the thing being shown + match nsOpt with + | Some ns2 when ns.Name = ns2.Name -> " active" + | _ -> "" + ) + ] [ + span [] [ + a [ + Class( + "nav-link" + + + // add the 'active' class if this is the namespace of the thing being shown + match nsOpt with + | Some ns2 when ns.Name = ns2.Name -> " active" + | _ -> "" + ) + Href(ns.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) + ] [ + !!ns.Name + ] + + ] + ] + + // In the navigation bar generate the expanded list of entities + // for the active namespace + match nsOpt with + | Some ns2 when ns.Name = ns2.Name -> + ul [ + Custom("list-style-type", "none") (* Class "navbar-nav " *) + ] [ + for category in allByCategory do + for e in category.CategoryEntites do + li [ + Class "nav-item" + ] [ + a [ + Class "nav-link" + Href(e.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) + ] [ + !!e.Name + ] + ] + ] + | _ -> () + ] let listOfNamespacesNav otherDocs (nsOpt: ApiDocNamespace option) = let noTemplatingFallback () = @@ -815,9 +1142,13 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = let title = "All Namespaces" let link = model.IndexFileUrl(root, collectionName, qualify, model.FileExtensions.InUrl) - [ { Menu.MenuItem.Link = link - Menu.MenuItem.Content = title - Menu.MenuItem.IsActive = true } ] + [ + { + Menu.MenuItem.Link = link + Menu.MenuItem.Content = title + Menu.MenuItem.IsActive = true + } + ] Menu.createMenu menuTemplateFolder false "API Reference" menuItems @@ -833,41 +1164,64 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = let link = ns.Url(root, collectionName, qualify, model.FileExtensions.InUrl) let name = ns.Name - { Menu.MenuItem.Link = link - Menu.MenuItem.Content = name - Menu.MenuItem.IsActive = false }) + { + Menu.MenuItem.Link = link + Menu.MenuItem.Content = name + Menu.MenuItem.IsActive = false + } + ) Menu.createMenu menuTemplateFolder false "Namespaces" menuItems /// Get the substitutions relevant to all member _.GlobalSubstitutions: Substitutions = let toc = listOfNamespacesNav true None - [ yield (ParamKeys.``fsdocs-list-of-namespaces``, toc); yield ParamKeys.``fsdocs-body-class``, "api-docs" ] + + [ + yield (ParamKeys.``fsdocs-list-of-namespaces``, toc) + yield ParamKeys.``fsdocs-body-class``, "api-docs" + ] member _.Generate(outDir: string, templateOpt, collectionName, globalParameters) = let getSubstitutons parameters toc (content: HtmlElement) pageTitle = - [| yield! parameters - yield (ParamKeys.``fsdocs-list-of-namespaces``, toc) - yield (ParamKeys.``fsdocs-content``, content.ToString()) - yield (ParamKeys.``fsdocs-source``, String.Empty) - yield (ParamKeys.``fsdocs-tooltips``, String.Empty) - yield (ParamKeys.``fsdocs-page-title``, pageTitle) - yield (ParamKeys.``fsdocs-page-content-list``, PageContentList.EmptyContent) - yield (ParamKeys.``fsdocs-meta-tags``, String.Empty) - yield! globalParameters |] + [| + yield! parameters + yield (ParamKeys.``fsdocs-list-of-namespaces``, toc) + yield (ParamKeys.``fsdocs-content``, content.ToString()) + yield (ParamKeys.``fsdocs-source``, String.Empty) + yield (ParamKeys.``fsdocs-tooltips``, String.Empty) + yield (ParamKeys.``fsdocs-page-title``, pageTitle) + yield (ParamKeys.``fsdocs-page-content-list``, PageContentList.EmptyContent) + yield (ParamKeys.``fsdocs-meta-tags``, String.Empty) + yield! globalParameters + |] let collection = model.Collection (let content = div [] [ - h1 [] [ !! "API Reference" ] - h2 [] [ !! "Available Namespaces:" ] - table [ Class "table outer-list fsdocs-member-list" ] [ + h1 [] [ + !! "API Reference" + ] + h2 [] [ + !! "Available Namespaces:" + ] + table [ + Class "table outer-list fsdocs-member-list" + ] [ thead [] [ tr [] [ - td [ Class "fsdocs-member-list-header" ] [ !! "Namespace" ] - td [ Class "fsdocs-member-list-header" ] [ !! "Description" ] + td [ + Class "fsdocs-member-list-header" + ] [ + !! "Namespace" + ] + td [ + Class "fsdocs-member-list-header" + ] [ + !! "Description" + ] ] ] tbody [] (tableOfNamespacesAux ()) From e0083f00616311a1814f169ec6e6ea3ed6e4193e Mon Sep 17 00:00:00 2001 From: Maxime Mangel Date: Sat, 17 Aug 2024 16:46:35 +0200 Subject: [PATCH 3/7] chore: initialise a ReferenceProject used to visually test the rendering of the different F# syntax + this project will also be used for unit test --- .editorconfig | 4 +- FSharp.Formatting.sln | 15 ++++ build.fsx | 34 ++++++++ .../files/ReferenceProject/Classes.fs | 77 +++++++++++++++++++ .../ReferenceProject/DiscriminatedUnions.fs | 12 +++ .../files/ReferenceProject/Functions.fs | 13 ++++ .../ReferenceProject/GlobalReferences.fs | 17 ++++ .../files/ReferenceProject/Interfaces.fs | 23 ++++++ .../files/ReferenceProject/Modules.fs | 11 +++ .../files/ReferenceProject/Namespaces.fs | 5 ++ .../files/ReferenceProject/Records.fs | 35 +++++++++ .../ReferenceProject/ReferenceProject.fsproj | 22 ++++++ .../files/ReferenceProject/Tuples.fs | 7 ++ .../files/ReferenceProject/docs/index.md | 3 + 14 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Classes.fs create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/DiscriminatedUnions.fs create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Functions.fs create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/GlobalReferences.fs create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Interfaces.fs create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Modules.fs create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Namespaces.fs create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Records.fs create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/ReferenceProject.fsproj create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Tuples.fs create mode 100644 tests/FSharp.ApiDocs.Tests/files/ReferenceProject/docs/index.md diff --git a/.editorconfig b/.editorconfig index 23440bfa8..f2cee255e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,7 +16,7 @@ fsharp_max_array_or_list_width=120 fsharp_max_infix_operator_expression=80 fsharp_max_value_binding_width=120 -[GenerateHtml.fs] +[{GenerateHtml.fs,tests/FSharp.ApiDocs.Tests/files/ReferenceProject/**/*.fs}] # Specific settings for "View/HTML" related files # It makes the code more consistent in term of spacing and indentation fsharp_experimental_elmish = true @@ -32,5 +32,5 @@ fsharp_multiline_bracket_style = aligned fsharp_keep_max_number_of_blank_lines = 1 fsharp_align_function_signature_to_indentation = true fsharp_max_if_then_else_short_width = 0 -fsharp_max_record_number_of_items = 2 +fsharp_max_record_number_of_items = 0 # Keep records consistent fsharp_record_multiline_formatter = number_of_items \ No newline at end of file diff --git a/FSharp.Formatting.sln b/FSharp.Formatting.sln index b57604b97..c653e6d18 100644 --- a/FSharp.Formatting.sln +++ b/FSharp.Formatting.sln @@ -128,6 +128,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "content", "content", "{FAD5 docs\content\fsdocs-theme-set-dark.js = docs\content\fsdocs-theme-set-dark.js EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{DD76B368-3C5C-4E4A-B3B2-812E950BD497}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FSharp.ApiDocs.Tests", "FSharp.ApiDocs.Tests", "{DE36A7E8-8F98-4763-B859-F452BCA9A675}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "files", "files", "{DFDABFED-63CB-46D1-B27D-BF674A820903}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ReferenceProject", "tests\FSharp.ApiDocs.Tests\files\ReferenceProject\ReferenceProject.fsproj", "{CDDD197C-6F51-4BDC-A2C2-87622A784A72}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -230,6 +238,10 @@ Global {CB78F0EA-8005-4735-A02C-B86CEDC29D85}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB78F0EA-8005-4735-A02C-B86CEDC29D85}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB78F0EA-8005-4735-A02C-B86CEDC29D85}.Release|Any CPU.Build.0 = Release|Any CPU + {CDDD197C-6F51-4BDC-A2C2-87622A784A72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDDD197C-6F51-4BDC-A2C2-87622A784A72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDDD197C-6F51-4BDC-A2C2-87622A784A72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDDD197C-6F51-4BDC-A2C2-87622A784A72}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -265,6 +277,9 @@ Global {188DC91F-2202-4495-ACD2-542D7C30364E} = {C7804F57-7FC6-4CF6-BDF6-127D6F9EBEA6} {FAD5C374-4748-4A3D-A435-FFA425916F3A} = {312E452A-1068-4804-89E7-0AFBAD5F885F} {52B949AA-A3F7-4894-B713-804BAEB71118} = {4AE0198D-EDE5-40B0-A5CD-FC7B6F891D94} + {DE36A7E8-8F98-4763-B859-F452BCA9A675} = {DD76B368-3C5C-4E4A-B3B2-812E950BD497} + {DFDABFED-63CB-46D1-B27D-BF674A820903} = {DE36A7E8-8F98-4763-B859-F452BCA9A675} + {CDDD197C-6F51-4BDC-A2C2-87622A784A72} = {DFDABFED-63CB-46D1-B27D-BF674A820903} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {76F121F8-70E0-49FB-9ADF-C7B660C0EB67} diff --git a/build.fsx b/build.fsx index 6706d59d7..b92f509a4 100644 --- a/build.fsx +++ b/build.fsx @@ -93,4 +93,38 @@ pipeline "Verify" { runIfOnlySpecified true } +let referenceProjectDir = "./tests/FSharp.ApiDocs.Tests/files/ReferenceProject" + +// TODO: Revisit to see how we can use `dotnet watch` to run a local version of the tool +// against ReferenceProject +// dotnet watch change the CWD and fsdocs-tool does not seems to allow changing the CWD +pipeline "APIDocsReference" { + + stage "Clean up" { + // Remove temporary files + run (fun _ -> + Shell.cleanDirs [ + "./tests/FSharp.ApiDocs.Tests/files/ReferenceProject/.fsdocs" + "./tests/FSharp.ApiDocs.Tests/files/ReferenceProject/.tmp" + "./tests/FSharp.ApiDocs.Tests/files/ReferenceProject/.bin" + "./tests/FSharp.ApiDocs.Tests/files/ReferenceProject/.obj" + ] + ) + } + + stage "Build project" { + // Make sure we have the required information for generating the API docs + workingDir referenceProjectDir + run "dotnet build" + } + + stage "Generate API Docs" { + // Run a local version of the tool against the ReferenceProject + workingDir referenceProjectDir + run "dotnet run --project ../../../../src/fsdocs-tool -- watch --nolaunch --projects ReferenceProject.fsproj --sourcefolder ../../../../src/fsdocs-tool/../../tests/FSharp.ApiDocs.Tests/files/ReferenceProject" + } + + runIfOnlySpecified +} + tryPrintPipelineCommandHelp () diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Classes.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Classes.fs new file mode 100644 index 000000000..2e3a49cbc --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Classes.fs @@ -0,0 +1,77 @@ +module ReferenceProject.Classes + +open System.Runtime.InteropServices + +// TODO: +// - SRTP syntax +// - Abstract classes +// - Attributes ? Like AllowNullLiteral + +type Empty = + class end + +type EmptyConstructor() = + class end + +type SeveralConstructors() = + new (_prefix : int) = SeveralConstructors() + new (_prefix : int, _indentSize : int) = SeveralConstructors() + +// https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/members/explicit-fields-the-val-keyword +type ExplicitFields () = + member val ExplicitFieldGetSet = 0 with get, set + member val ExplicitFieldGet = 0 with get + +// https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/members/properties +type Properties () = + static member StaticProperty = 0 + static member StaticPropertyGetOnly with get () = 0 + static member StaticPropertySetOnly with set (_value : int) = () + static member StaticPropertyGetSet with get() = 0 and set(_value : int) = () + static member val StaticPropertyWithAutoImpl = 0 with get, set + +// https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/members/methods +type InstanceMethods () = + member this.Void () = () + + // Non curried arguments + member this.Echo (_message : string) = _message + member this.Add (a : int) (b : int) = a + b + + // Curried arguments + member this.AddCurried (a : int, b : int) = a + b + + // Methods with overloads + member this.Log (_message : string) = () + member this.Log (_message : string, _level : int) = () + member this.Log (_message : string, _level : int, ?_prefix : string) = () + +type StaticMethods () = + static member StaticVoid () = () + + // Non curried arguments + static member StaticEcho (_message : string) = _message + static member StaticAdd (a : int) (b : int) = a + b + + // Curried arguments + static member StaticAddCurried (a : int, b : int) = a + b + + // Static methods with overloads + static member StaticLog (_message : string) = () + static member StaticLog (_message : string, _level : int) = () + static member StaticLog (_message : string, _level : int, ?_prefix : string) = () + +[] +type AbstractMethods () = + abstract member AbstractMethod : unit -> unit + abstract member AbstractMethodWithUnknownArguments : string -> int -> unit + abstract member AbstractMethodWithNamedArguments : message : string -> level : int -> unit + +type OptionalInterop () = + member _.AddOne([] i) = i + 1 + +type InterfaceImplementation () = + interface Interfaces.InterfaceC with + member this.MethodA () = () + member this.MethodB () = () + member this.MethodC () = () \ No newline at end of file diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/DiscriminatedUnions.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/DiscriminatedUnions.fs new file mode 100644 index 000000000..d1b74a37d --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/DiscriminatedUnions.fs @@ -0,0 +1,12 @@ +module ReferenceProject.DiscriminatedUnions + +type SingleCase = + | SingleCase of string + +type NamedArguments = + | NamedArguments of prefix: string * indentSize: int + +type MultipleCases = + | Case1 + | Case2 of string + | Case3 of message : string * callback : (int -> int) \ No newline at end of file diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Functions.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Functions.fs new file mode 100644 index 000000000..de1282842 --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Functions.fs @@ -0,0 +1,13 @@ +module ReferenceProject.Functions + +/// +/// This function calculates the sum of two numbers. +/// +/// The first number. +/// The second number. +/// The sum of the two numbers. +let add (a: int) (b: int) = a + b + +let emptyFunction () = () + +let tupleArguments (a: int, b: int) = a + b diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/GlobalReferences.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/GlobalReferences.fs new file mode 100644 index 000000000..5128ccfe0 --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/GlobalReferences.fs @@ -0,0 +1,17 @@ +module ReferenceProject.GlobalReferences + +// Types in this file are used to be referenced by other files in the project. +// This is to test things like type resolution and cross-file linking. + +type CallBack = unit -> unit + +type UserClass(firstName: string, lastName: string) = + member this.FirstName = firstName + member this.LastName = lastName + member this.FullName = firstName + " " + lastName + +type UserRecord = + { + FirstName: string + LastName: string + } diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Interfaces.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Interfaces.fs new file mode 100644 index 000000000..884799a52 --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Interfaces.fs @@ -0,0 +1,23 @@ +module ReferenceProject.Interfaces + +type Empty = + interface end + +type InstanceMethods = + abstract member Method : unit -> unit + +type StaticMethods = + static member Version = "This is version 1.0" + static member Log (_message: string) = () + +// Interfaces for inheritance testing +type InterfaceA = + abstract member MethodA : unit -> unit + +type InterfaceB = + abstract member MethodB : unit -> unit + +type InterfaceC = + inherit InterfaceA + inherit InterfaceB + abstract member MethodC : unit -> unit \ No newline at end of file diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Modules.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Modules.fs new file mode 100644 index 000000000..1cb5b0483 --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Modules.fs @@ -0,0 +1,11 @@ +module ReferenceProject.Modules + +module ModuleA = + + module ModuleA_A = + + let answer = 42 + + module ModuleA_B = + + let answer = 42 \ No newline at end of file diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Namespaces.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Namespaces.fs new file mode 100644 index 000000000..7a466a659 --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Namespaces.fs @@ -0,0 +1,5 @@ +namespace NamespaceA + +module ModuleA = + + let answer = 42 \ No newline at end of file diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Records.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Records.fs new file mode 100644 index 000000000..bc873b16f --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Records.fs @@ -0,0 +1,35 @@ +module ReferenceProject.Records + +type OneField = + { + Field: int + } + +type SeveralFields = + { + FirstName: string + LastName: string + Age: int + } + +type WithAnonymousRecord = + { + IndentationLevel: int + Data: + {| + Prefix: string + Time: System.DateTime + |} + } + +type WithFunction = + { + Function: int -> int + } + +// Should we display something about the attributes? Some of them? +[] +type WithAttributes = + { + Field: string + } diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/ReferenceProject.fsproj b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/ReferenceProject.fsproj new file mode 100644 index 000000000..d7b49261d --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/ReferenceProject.fsproj @@ -0,0 +1,22 @@ + + + + library + net8.0 + true + $(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Tuples.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Tuples.fs new file mode 100644 index 000000000..b12e22591 --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Tuples.fs @@ -0,0 +1,7 @@ +module ReferenceProject.Tuples + +open ReferenceProject.GlobalReferences + +type Tuple2 = int * int + +type UserRank = int * UserClass \ No newline at end of file diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/docs/index.md b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/docs/index.md new file mode 100644 index 000000000..06c093d9b --- /dev/null +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/docs/index.md @@ -0,0 +1,3 @@ +# This project is used to test the generation of API documentation for F# projects. + +It is both used for testing the generation but also visual inspection of the generated documentation. \ No newline at end of file From f6a835a7b90b96a858e42c48b1b1a4918b3c53f1 Mon Sep 17 00:00:00 2001 From: Maxime Mangel Date: Sun, 18 Aug 2024 16:45:30 +0200 Subject: [PATCH 4/7] chore: save progress before exploring VSCode like API structure --- .editorconfig | 5 +- docs/content/fsdocs-default.css | 4 +- .../FSharp.Formatting.ApiDocs.fsproj | 3 + .../Generate/Common.fs | 40 +++ .../Generate/Module.fs | 243 +++++++++++++++++ .../Generate/Record.fs | 155 +++++++++++ src/FSharp.Formatting.ApiDocs/GenerateHtml.fs | 247 +++++------------- src/FSharp.Formatting.ApiDocs/Prelude.fs | 6 + .../files/ReferenceProject/Records.fs | 20 ++ 9 files changed, 534 insertions(+), 189 deletions(-) create mode 100644 src/FSharp.Formatting.ApiDocs/Generate/Common.fs create mode 100644 src/FSharp.Formatting.ApiDocs/Generate/Module.fs create mode 100644 src/FSharp.Formatting.ApiDocs/Generate/Record.fs diff --git a/.editorconfig b/.editorconfig index f2cee255e..24835aeba 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,7 +16,10 @@ fsharp_max_array_or_list_width=120 fsharp_max_infix_operator_expression=80 fsharp_max_value_binding_width=120 -[{GenerateHtml.fs,tests/FSharp.ApiDocs.Tests/files/ReferenceProject/**/*.fs}] +[{ + src/FSharp.Formatting.ApiDocs/GenerateHtml.fs + src/FSharp.Formatting.ApiDocs/Generate/**.fs + ,tests/FSharp.ApiDocs.Tests/files/ReferenceProject/**/*.fs}] # Specific settings for "View/HTML" related files # It makes the code more consistent in term of spacing and indentation fsharp_experimental_elmish = true diff --git a/docs/content/fsdocs-default.css b/docs/content/fsdocs-default.css index f811770ec..aacd189d2 100644 --- a/docs/content/fsdocs-default.css +++ b/docs/content/fsdocs-default.css @@ -1292,7 +1292,8 @@ dialog { a.record-field-name, a.union-case-property, a.property { - /* color: darken($primary, 4%); */ + color: var(--code-property-color); + text-decoration: none; &:hover { text-decoration: underline; @@ -1392,4 +1393,5 @@ dialog { justify-content: flex-start; align-items: center; } + } \ No newline at end of file diff --git a/src/FSharp.Formatting.ApiDocs/FSharp.Formatting.ApiDocs.fsproj b/src/FSharp.Formatting.ApiDocs/FSharp.Formatting.ApiDocs.fsproj index b3ae7573d..bfe9669b6 100644 --- a/src/FSharp.Formatting.ApiDocs/FSharp.Formatting.ApiDocs.fsproj +++ b/src/FSharp.Formatting.ApiDocs/FSharp.Formatting.ApiDocs.fsproj @@ -15,6 +15,9 @@ + + + diff --git a/src/FSharp.Formatting.ApiDocs/Generate/Common.fs b/src/FSharp.Formatting.ApiDocs/Generate/Common.fs new file mode 100644 index 000000000..602f7d670 --- /dev/null +++ b/src/FSharp.Formatting.ApiDocs/Generate/Common.fs @@ -0,0 +1,40 @@ +module internal FSharp.Formatting.ApiDocs.Generate.Common + +open FSharp.Formatting.ApiDocs +open FSharp.Formatting.HtmlModel +open System.Xml.Linq +open System.Text.RegularExpressions + +let formatXmlComment (commentOpt: XElement option) : string = + + match commentOpt with + | Some comment -> + let docComment = comment.ToString() + + let pattern = $"""((?'xml_doc'(?:(?!)(?!<\/member>)[\s\S])*)<\/member\s*>)""" + + let m = Regex.Match(docComment, pattern) + + // Remove the and tags + if m.Success then + let xmlDoc = m.Groups.["xml_doc"].Value + + let lines = xmlDoc |> String.splitLines |> Array.toList + + // Remove the non meaning full indentation + let content = + lines + |> List.map (fun line -> + // Add a small protection in case the user didn't align all it's tags + if line.StartsWith(" ") then + line.Substring(1) + else + line + ) + |> String.concat "\n" + + CommentFormatter.format content + else + CommentFormatter.format docComment + + | None -> "" \ No newline at end of file diff --git a/src/FSharp.Formatting.ApiDocs/Generate/Module.fs b/src/FSharp.Formatting.ApiDocs/Generate/Module.fs new file mode 100644 index 000000000..d5ad31eb3 --- /dev/null +++ b/src/FSharp.Formatting.ApiDocs/Generate/Module.fs @@ -0,0 +1,243 @@ +module internal FSharp.Formatting.ApiDocs.Generate.Module + +open FSharp.Formatting.HtmlModel +open FSharp.Formatting.HtmlModel.Html +open FSharp.Formatting.ApiDocs.GenerateSignature +open FSharp.Formatting.ApiDocs + +let sectionTitle (title: string) = + strong [] [ + !!title + ] + +let private renderSection (linkGenerator: ApiDocEntity -> string) (title: string) (entities: ApiDocEntity list) = + [ + if not entities.IsEmpty then + sectionTitle title + + p [] [ + table [] [ + thead [] [ + tr [] [ + th [ + Width "25%" + ] [ + !! "Type" + ] + th [ + Width "75%" + ] [ + !! "Description" + ] + ] + ] + tbody [] [ + for entity in entities do + tr [] [ + td [] [ + a [ + Href(linkGenerator entity) + ] [ + !!entity.Name + ] + ] + td [] [ + !!(Common.formatXmlComment entity.Comment.Xml) + ] + ] + ] + ] + ] + ] + +let private renderDeclaredTypes (entities: ApiDocEntity list) (linkGenerator: ApiDocEntity -> string) = + entities + |> List.filter (fun entity -> entity.IsTypeDefinition) + |> renderSection linkGenerator "Declared types" + +let private renderDeclaredModules (entities: ApiDocEntity list) (linkGenerator: ApiDocEntity -> string) = + entities + |> List.filter (fun entity -> entity.Symbol.IsFSharpModule) + |> renderSection linkGenerator "Declared modules" + +let private renderValueOrFunctions (entities: ApiDocMember list) (linkGenerator: ApiDocEntity -> string) = + if entities.IsEmpty then + [] + else + + [ + sectionTitle "Functions and values" + + for entity in entities do + let (ApiDocMemberDetails(usageHtml, + paramTypes, + returnType, + modifiers, + typars, + baseType, + location, + compiledName)) = + entity.Details + + let returnHtml = + // TODO: Parse the return type information from + // let x = entity.Symbol :?> FSharpMemberOrFunctionOrValue + // x.FullType <-- Here we have access to all the type including the argument for the function that we should ignore... (making the processing complex) + // For now, we are just using returnType.HtmlText to have something ready as parsing from + // FSharpMemberOrFunctionOrValue seems to be quite complex + match returnType with + | Some(_, returnType) -> + // Remove the starting and ending + returnType.HtmlText.[6 .. returnType.HtmlText.Length - 8] + // Adapt the text to have basic syntax highlighting + |> fun text -> text.Replace("<", Html.lessThan.ToMinifiedHtml()) + |> fun text -> text.Replace(">", Html.greaterThan.ToMinifiedHtml()) + |> fun text -> text.Replace(",", Html.comma.ToMinifiedHtml()) + + | None -> "unit" + + let initial = Signature.ParamTypesInformation.Init entity.Name + + let paramTypesInfo = Signature.extractParamTypesInformation initial paramTypes + + div [ + Class "fsdocs-block" + ] [ + + div [ + Class "actions-buttons" + ] [ + // yield! sourceLink entity.SourceLocation + // yield! copyXmlSigIconForSymbol entity.Symbol + // yield! copyXmlSigIconForSymbolMarkdown entity.Symbol + ] + + // This is a value + if paramTypesInfo.Infos.IsEmpty then + div [ + Class "fsdocs-api-code" + ] [ + div [] [ + Html.val' + Html.space + !!entity.Name + Html.space + Html.colon + !!returnHtml + ] + ] + + // This is a function + else + + div [ + Class "fsdocs-api-code" + ] [ + [ + TextNode.Div [ + TextNode.Keyword "val" + TextNode.Space + TextNode.AnchorWithId($"#{entity.Name}", entity.Name, entity.Name) + TextNode.Space + TextNode.Colon + ] + ] + |> TextNode.Node + |> TextNode.ToHtmlElement + + for index in 0 .. paramTypesInfo.Infos.Length - 1 do + let (name, returnType) = paramTypesInfo.Infos.[index] + + div [] [ + Html.spaces 4 // Equivalent to 'val ' + !!name + Html.spaces (paramTypesInfo.MaxNameLength - name.Length + 1) // Complete with space to align ':' + Html.colon + Html.space + !! returnType.HtmlElement.ToMinifiedHtml() + + Html.spaces (paramTypesInfo.MaxReturnTypeLength - returnType.Length + 1) // Complete with space to align '->' + + // Don't add the arrow for the last parameter + if index <> paramTypesInfo.Infos.Length - 1 then + Html.arrow + ] + |> Html.minify + + div [] [ + Html.spaces (4 + paramTypesInfo.MaxNameLength + 1) // Equivalent to 'val ' + the max length of parameter name + ':' + Html.arrow + Html.space + !!returnHtml + ] + |> Html.minify + ] + + match entity.Comment.Xml with + | Some xmlComment -> + let comment = xmlComment.ToString() + !!(CommentFormatter.formatSummaryOnly comment) + + if not paramTypesInfo.Infos.IsEmpty then + p [] [ + strong [] [ + !! "Parameters" + ] + ] + + for (name, returnType) in paramTypesInfo.Infos do + let paramDoc = + CommentFormatter.tryFormatParam name comment + |> Option.map (fun paramDoc -> !!paramDoc) + |> Option.defaultValue Html.nothing + + div [ + Class "fsdocs-doc-parameter" + ] [ + [ + TextNode.DivWithClass( + "fsdocs-api-code", + [ + TextNode.Property name + TextNode.Space + TextNode.Colon + TextNode.Space + returnType + ] + ) + ] + |> TextNode.Node + |> TextNode.ToHtmlElement + + paramDoc + ] + + match CommentFormatter.tryFormatReturnsOnly comment with + | Some returnDoc -> + p [] [ + strong [] [ + !! "Returns" + ] + ] + + !!returnDoc + + | None -> () + + // TODO: Should we render a minimal documentation here with the information we have? + // For example, we can render the list of parameters and the return type + // This is to make the documentation more consistent + // However, these minimal information will be rondontant with the information displayed in the signature + | None -> () + ] + + // hr [] + + ] + +let renderModule (entityInfo: ApiDocEntityInfo) (linkGenerator: ApiDocEntity -> string) : HtmlElement list = + [ + yield! renderDeclaredTypes entityInfo.Entity.NestedEntities linkGenerator + yield! renderDeclaredModules entityInfo.Entity.NestedEntities linkGenerator + yield! renderValueOrFunctions entityInfo.Entity.ValuesAndFuncs linkGenerator + ] diff --git a/src/FSharp.Formatting.ApiDocs/Generate/Record.fs b/src/FSharp.Formatting.ApiDocs/Generate/Record.fs new file mode 100644 index 000000000..f9bd402e5 --- /dev/null +++ b/src/FSharp.Formatting.ApiDocs/Generate/Record.fs @@ -0,0 +1,155 @@ +module internal FSharp.Formatting.ApiDocs.Generate.Record + +open FSharp.Formatting.HtmlModel +open FSharp.Formatting.HtmlModel.Html +open FSharp.Formatting.ApiDocs.GenerateSignature +open FSharp.Formatting.ApiDocs +open FSharp.Compiler.Symbols + +module Seq = + + let collecti (f: int -> 'T -> 'U list) (s: seq<'T>) : 'U seq = + s |> Seq.mapi f |> Seq.concat + +let renderRecordType (entityInfo: ApiDocEntityInfo) = + let entity = entityInfo.Entity + + div [ + Class "fsdocs-api-code" + ] [ + div [] [ + Html.keyword "type" + Html.space + !!entity.Name + Html.space + Html.equal + ] + div [] [ + Html.spaces 4 + Html.leftBrace + ] + + for field in entity.RecordFields do + match field.ReturnInfo.ReturnType with + | Some(_, returnType) -> + let escapedReturnType = + // Remove the starting and ending + returnType.HtmlText.[6 .. returnType.HtmlText.Length - 8] + + div [ + Class "record-field" + ] [ + Html.spaces 8 + a [ + Class "record-field-name" + Href("#" + field.Name) + ] [ + !!field.Name + ] + Html.space + Html.colon + Html.space + span [ + Class "record-field-type" + ] [ + !!escapedReturnType + ] + ] + + | None -> () + + div [] [ + Html.spaces 4 + Html.rightBrace + ] + + for m in entity.InstanceMembers do + match m.Symbol with + | :? FSharpMemberOrFunctionOrValue as symbol -> + div [] [ + + Html.spaces 4 + Html.keyword "member" + Html.space + Html.keyword "this" + Html.dot + !!symbol.DisplayName + + printfn "Parameters: %A" m.Parameters + printfn "CurriedParameterGroups: %A" symbol.CurriedParameterGroups + + if symbol.CurriedParameterGroups.Count = 0 then + !!"unit" + else + for parameterGroup in symbol.CurriedParameterGroups do + // Can this case happen? + if parameterGroup.Count = 0 then + () + else if parameterGroup.Count = 1 then + let parameter = parameterGroup.[0] + Html.space + !!parameter.DisplayName + !!"dwdwd" + Html.space + Html.arrow + Html.space + else // Tupled arguments + yield! parameterGroup + |> Seq.collecti (fun index parameter -> + [ + Html.space + if index <> 0 then + Html.star + Html.space + !!parameter.DisplayName + // Format the type + // parameter.Type + ] + ) + + match m.ReturnInfo.ReturnType with + | Some(_, returnType) -> + // Only add ' : ' if there is a return type + // This is to work around https://github.com/fsprojects/FSharp.Formatting/issues/734 + // I think this still generate incorrect code, because reading the implementation of returnType + // it seems to return `None` if the return type is `unit` + // For now, let's consider that returning `unit` from a member property is not a common case + Html.space + Html.colon + Html.space + !!returnType.HtmlText + | None -> () + + match symbol.HasGetterMethod, symbol.HasSetterMethod with + | true, true -> + Html.space + Html.keyword "with" + Html.space + Html.keyword "get" + Html.comma + Html.space + Html.keyword "set" + | true, false -> + Html.space + Html.keyword "with" + Html.space + Html.keyword "get" + | false, true -> + Html.space + Html.keyword "with" + Html.space + Html.keyword "set" + | false, false -> () + ] + + | unkownSymbol -> + div [] [ + !! $"'%s{unkownSymbol.ToString()}' symbol not supported, please report an issue at " + a [ + Href "https://github.com/fsprojects/FSharp.Formatting" + ] [ + !! "FSharp.Formatting." + ] + ] + ] + |> Html.minify diff --git a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs index 3a75112f7..62fef2d2b 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs @@ -182,183 +182,6 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = | _ -> () ] - let renderValueOrFunctions (entities: ApiDocMember list) = - - if entities.IsEmpty then - [] - else - - [ - h3 [] [ - !! "Functions and values" - ] - - for entity in entities do - let (ApiDocMemberDetails(usageHtml, - paramTypes, - returnType, - modifiers, - typars, - baseType, - location, - compiledName)) = - entity.Details - - let returnHtml = - // TODO: Parse the return type information from - // let x = entity.Symbol :?> FSharpMemberOrFunctionOrValue - // x.FullType <-- Here we have access to all the type including the argument for the function that we should ignore... (making the processing complex) - // For now, we are just using returnType.HtmlText to have something ready as parsing from - // FSharpMemberOrFunctionOrValue seems to be quite complex - match returnType with - | Some(_, returnType) -> - // Remove the starting and ending - returnType.HtmlText.[6 .. returnType.HtmlText.Length - 8] - // Adapt the text to have basic syntax highlighting - |> fun text -> text.Replace("<", Html.lessThan.ToMinifiedHtml()) - |> fun text -> text.Replace(">", Html.greaterThan.ToMinifiedHtml()) - |> fun text -> text.Replace(",", Html.comma.ToMinifiedHtml()) - - | None -> "unit" - - let initial = Signature.ParamTypesInformation.Init entity.Name - - let paramTypesInfo = Signature.extractParamTypesInformation initial paramTypes - - div [ - Class "fsdocs-block" - ] [ - - div [ - Class "actions-buttons" - ] [ - yield! sourceLink entity.SourceLocation - yield! copyXmlSigIconForSymbol entity.Symbol - yield! copyXmlSigIconForSymbolMarkdown entity.Symbol - ] - - // This is a value - if paramTypesInfo.Infos.IsEmpty then - div [ - Class "fsdocs-api-code" - ] [ - div [] [ - Html.val' - Html.space - !!entity.Name - Html.space - Html.colon - !!returnHtml - ] - ] - - // This is a function - else - - div [ - Class "fsdocs-api-code" - ] [ - [ - TextNode.Div [ - TextNode.Keyword "val" - TextNode.Space - TextNode.AnchorWithId($"#{entity.Name}", entity.Name, entity.Name) - TextNode.Space - TextNode.Colon - ] - ] - |> TextNode.Node - |> TextNode.ToHtmlElement - - for index in 0 .. paramTypesInfo.Infos.Length - 1 do - let (name, returnType) = paramTypesInfo.Infos.[index] - - div [] [ - Html.spaces 4 // Equivalent to 'val ' - !!name - Html.spaces (paramTypesInfo.MaxNameLength - name.Length + 1) // Complete with space to align ':' - Html.colon - Html.space - !! returnType.HtmlElement.ToMinifiedHtml() - - Html.spaces (paramTypesInfo.MaxReturnTypeLength - returnType.Length + 1) // Complete with space to align '->' - - // Don't add the arrow for the last parameter - if index <> paramTypesInfo.Infos.Length - 1 then - Html.arrow - ] - |> Html.minify - - div [] [ - Html.spaces (4 + paramTypesInfo.MaxNameLength + 1) // Equivalent to 'val ' + the max length of parameter name + ':' - Html.arrow - Html.space - !!returnHtml - ] - |> Html.minify - ] - - match entity.Comment.Xml with - | Some xmlComment -> - let comment = xmlComment.ToString() - !!(CommentFormatter.formatSummaryOnly comment) - - if not paramTypesInfo.Infos.IsEmpty then - p [] [ - strong [] [ - !! "Parameters" - ] - ] - - for (name, returnType) in paramTypesInfo.Infos do - let paramDoc = - CommentFormatter.tryFormatParam name comment - |> Option.map (fun paramDoc -> !!paramDoc) - |> Option.defaultValue Html.nothing - - div [ - Class "fsdocs-doc-parameter" - ] [ - [ - TextNode.DivWithClass( - "fsdocs-api-code", - [ - TextNode.Property name - TextNode.Space - TextNode.Colon - TextNode.Space - returnType - ] - ) - ] - |> TextNode.Node - |> TextNode.ToHtmlElement - - paramDoc - ] - - match CommentFormatter.tryFormatReturnsOnly comment with - | Some returnDoc -> - p [] [ - strong [] [ - !! "Returns" - ] - ] - - !!returnDoc - - | None -> () - - // TODO: Should we r``ender a minimal documentation here with the information we have? - // For example, we can render the list of parameters and the return type - // This is to make the documentation more consistent - // However, these minimal information will be rondontant with the information displayed in the signature - | None -> () - ] - - // hr [] - - ] let renderMembers header tableHeader (members: ApiDocMember list) = [ @@ -731,6 +554,56 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = ] ] + let generateEntityPage (entityInfo: ApiDocEntityInfo) = + let generateTopMetadata (name: string) (content: HtmlElement) = + div [] [ + strong [] [ + !!name + ] + + content + ] + + [ + h2 [] [ + !!entityInfo.Entity.Name + ] + + generateTopMetadata + "Namespace: " + (a [ + Href(entityInfo.Namespace.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) + ] [ + !!entityInfo.Namespace.Name + ]) + + match entityInfo.ParentModule with + | Some parentModule -> + generateTopMetadata + "Parent: " + (a [ + Href(parentModule.Url(root, collectionName, qualify, model.FileExtensions.InUrl)) + ] [ + !!parentModule.Name + ]) + | None -> () + + let symbol = entityInfo.Entity.Symbol + + if symbol.IsFSharpRecord then + Generate.Record.renderRecordType entityInfo + else if symbol.IsFSharpModule then + let linkGenerator (entity : ApiDocEntity) = + entity.Url(root, collectionName, qualify, model.FileExtensions.InUrl) + + yield! Generate.Module.renderModule entityInfo linkGenerator + else + // Module + // Namespace + // Union + !! "TODO" + ] + let entityContent (info: ApiDocEntityInfo) = // Get all the members & comment for the type let entity = info.Entity @@ -939,7 +812,7 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = let constructors = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.Constructor) let instanceMembers = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.InstanceMember) let staticMembers = ms |> List.filter (fun m -> m.Kind = ApiDocMemberKind.StaticMember) - div [] (renderValueOrFunctions functionsOrValues) + // div [] (renderValueOrFunctions functionsOrValues) div [] (renderMembers "Type extensions" "Type extension" extensions) div [] (renderMembers "Active patterns" "Active pattern" activePatterns) div [] (renderMembers "Union cases" "Union case" unionCases) @@ -1199,7 +1072,7 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = let collection = model.Collection - (let content = + let content = div [] [ h1 [] [ !! "API Reference" @@ -1228,17 +1101,17 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = ] ] - let pageTitle = sprintf "%s (API Reference)" collectionName + let pageTitle = sprintf "%s (API Reference)" collectionName - let toc = listOfNamespacesNav false None + let toc = listOfNamespacesNav false None - let substitutions = getSubstitutons model.Substitutions toc content pageTitle + let substitutions = getSubstitutons model.Substitutions toc content pageTitle - let outFile = - Path.Combine(outDir, model.IndexOutputFile(collectionName, model.Qualify, model.FileExtensions.InFile)) + let outFile = + Path.Combine(outDir, model.IndexOutputFile(collectionName, model.Qualify, model.FileExtensions.InFile)) - printfn " Generating %s" outFile - SimpleTemplating.UseFileAsSimpleTemplate(substitutions, templateOpt, outFile)) + printfn " Generating %s" outFile + SimpleTemplating.UseFileAsSimpleTemplate(substitutions, templateOpt, outFile) //printfn "Namespaces = %A" [ for ns in collection.Namespaces -> ns.Name ] @@ -1256,7 +1129,7 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = SimpleTemplating.UseFileAsSimpleTemplate(substitutions, templateOpt, outFile) for info in model.EntityInfos do - let content = div [] (entityContent info) + let content = div [] (generateEntityPage info) let pageTitle = sprintf "%s (%s)" info.Entity.Name collectionName diff --git a/src/FSharp.Formatting.ApiDocs/Prelude.fs b/src/FSharp.Formatting.ApiDocs/Prelude.fs index eb404d022..4490365fe 100644 --- a/src/FSharp.Formatting.ApiDocs/Prelude.fs +++ b/src/FSharp.Formatting.ApiDocs/Prelude.fs @@ -24,6 +24,12 @@ module Html = let equal = keyword "=" let leftParent = keyword "(" let rightParent = keyword ")" + let leftBracket = keyword "[" + let rightBracket = keyword "]" + let leftBrace = keyword "{" + let rightBrace = keyword "}" + + let star = keyword "*" let minify (html: HtmlElement) = !!(html.ToMinifiedHtml()) diff --git a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Records.fs b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Records.fs index bc873b16f..1c6bebad2 100644 --- a/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Records.fs +++ b/tests/FSharp.ApiDocs.Tests/files/ReferenceProject/Records.fs @@ -33,3 +33,23 @@ type WithAttributes = { Field: string } + +type WithInstanceMethod = + { + FieldA : string + } + + member this.MyVoidMethod () = () + member this.MyAddMethodCurry (a : int, b : int) = a + b + member this.MyAddMethodUncurry (a : int) (b : int) = a + b + member this.MyPropertyWithGetterWorksWithUnit with get () = () + member this.MyPropertyWithGetter with get () = 0 + member this.MyPropertyWithSetter with set (_value : int) = () + member this.MyPropertyWithGetterAndSetter with get () = 0 and set (_value : int) = () + +type WithStaticMethod = + { + FieldA : string + } + + static member MyStaticMethod() = () \ No newline at end of file From 6ffdf66cd9f85602fab178dfc5a165e5702f82f6 Mon Sep 17 00:00:00 2001 From: Maxime Mangel Date: Sun, 18 Aug 2024 17:40:32 +0200 Subject: [PATCH 5/7] chore: save generation result before manual editing for easier port after experimentation --- rework-prototype/content/fsdocs-default.css | 1397 +++++++++++++++++ .../content/fsdocs-details-set-expanded.js | 9 + .../content/fsdocs-details-toggle.js | 46 + rework-prototype/content/fsdocs-search.js | 126 ++ .../content/fsdocs-theme-set-dark.js | 5 + .../content/fsdocs-theme-toggle.js | 38 + rework-prototype/content/fsdocs-theme.css | 1 + rework-prototype/content/fsdocs-theme.js | 35 + rework-prototype/content/fsdocs-tips.js | 59 + .../content/img/github-pages-settings.png | Bin 0 -> 33534 bytes rework-prototype/content/prism/prism.css | 507 ++++++ rework-prototype/content/prism/prism.js | 16 + rework-prototype/index.html | 164 ++ rework-prototype/index.json | 1 + rework-prototype/reference/index.html | 190 +++ .../reference/namespacea-modulea.html | 185 +++ rework-prototype/reference/namespacea.html | 201 +++ ...erenceproject-classes-abstractmethods.html | 174 ++ .../referenceproject-classes-empty.html | 174 ++ ...renceproject-classes-emptyconstructor.html | 174 ++ ...ferenceproject-classes-explicitfields.html | 174 ++ ...erenceproject-classes-instancemethods.html | 174 ++ ...oject-classes-interfaceimplementation.html | 174 ++ ...erenceproject-classes-optionalinterop.html | 174 ++ .../referenceproject-classes-properties.html | 174 ++ ...ceproject-classes-severalconstructors.html | 174 ++ ...eferenceproject-classes-staticmethods.html | 174 ++ .../reference/referenceproject-classes.html | 284 ++++ ...ect-discriminatedunions-multiplecases.html | 174 ++ ...ct-discriminatedunions-namedarguments.html | 174 ++ ...roject-discriminatedunions-singlecase.html | 174 ++ .../referenceproject-discriminatedunions.html | 214 +++ .../reference/referenceproject-functions.html | 218 +++ ...enceproject-globalreferences-callback.html | 174 ++ ...nceproject-globalreferences-userclass.html | 174 ++ ...ceproject-globalreferences-userrecord.html | 184 +++ .../referenceproject-globalreferences.html | 214 +++ .../referenceproject-interfaces-empty.html | 174 ++ ...nceproject-interfaces-instancemethods.html | 174 ++ ...eferenceproject-interfaces-interfacea.html | 174 ++ ...eferenceproject-interfaces-interfaceb.html | 174 ++ ...eferenceproject-interfaces-interfacec.html | 174 ++ ...renceproject-interfaces-staticmethods.html | 174 ++ .../referenceproject-interfaces.html | 244 +++ ...enceproject-modules-modulea-modulea_a.html | 193 +++ ...enceproject-modules-modulea-modulea_b.html | 193 +++ .../referenceproject-modules-modulea.html | 212 +++ .../reference/referenceproject-modules.html | 194 +++ .../referenceproject-records-onefield.html | 184 +++ ...eferenceproject-records-severalfields.html | 184 +++ ...ceproject-records-withanonymousrecord.html | 184 +++ ...ferenceproject-records-withattributes.html | 184 +++ ...referenceproject-records-withfunction.html | 184 +++ ...nceproject-records-withinstancemethod.html | 187 +++ ...renceproject-records-withstaticmethod.html | 187 +++ .../reference/referenceproject-records.html | 254 +++ .../referenceproject-tuples-tuple2.html | 174 ++ .../referenceproject-tuples-userrank.html | 174 ++ .../reference/referenceproject-tuples.html | 204 +++ .../reference/referenceproject.html | 404 +++++ .../Generate/Record.fs | 28 + src/FSharp.Formatting.ApiDocs/GenerateHtml.fs | 3 + 62 files changed, 11319 insertions(+) create mode 100644 rework-prototype/content/fsdocs-default.css create mode 100644 rework-prototype/content/fsdocs-details-set-expanded.js create mode 100644 rework-prototype/content/fsdocs-details-toggle.js create mode 100644 rework-prototype/content/fsdocs-search.js create mode 100644 rework-prototype/content/fsdocs-theme-set-dark.js create mode 100644 rework-prototype/content/fsdocs-theme-toggle.js create mode 100644 rework-prototype/content/fsdocs-theme.css create mode 100644 rework-prototype/content/fsdocs-theme.js create mode 100644 rework-prototype/content/fsdocs-tips.js create mode 100644 rework-prototype/content/img/github-pages-settings.png create mode 100644 rework-prototype/content/prism/prism.css create mode 100644 rework-prototype/content/prism/prism.js create mode 100644 rework-prototype/index.html create mode 100644 rework-prototype/index.json create mode 100644 rework-prototype/reference/index.html create mode 100644 rework-prototype/reference/namespacea-modulea.html create mode 100644 rework-prototype/reference/namespacea.html create mode 100644 rework-prototype/reference/referenceproject-classes-abstractmethods.html create mode 100644 rework-prototype/reference/referenceproject-classes-empty.html create mode 100644 rework-prototype/reference/referenceproject-classes-emptyconstructor.html create mode 100644 rework-prototype/reference/referenceproject-classes-explicitfields.html create mode 100644 rework-prototype/reference/referenceproject-classes-instancemethods.html create mode 100644 rework-prototype/reference/referenceproject-classes-interfaceimplementation.html create mode 100644 rework-prototype/reference/referenceproject-classes-optionalinterop.html create mode 100644 rework-prototype/reference/referenceproject-classes-properties.html create mode 100644 rework-prototype/reference/referenceproject-classes-severalconstructors.html create mode 100644 rework-prototype/reference/referenceproject-classes-staticmethods.html create mode 100644 rework-prototype/reference/referenceproject-classes.html create mode 100644 rework-prototype/reference/referenceproject-discriminatedunions-multiplecases.html create mode 100644 rework-prototype/reference/referenceproject-discriminatedunions-namedarguments.html create mode 100644 rework-prototype/reference/referenceproject-discriminatedunions-singlecase.html create mode 100644 rework-prototype/reference/referenceproject-discriminatedunions.html create mode 100644 rework-prototype/reference/referenceproject-functions.html create mode 100644 rework-prototype/reference/referenceproject-globalreferences-callback.html create mode 100644 rework-prototype/reference/referenceproject-globalreferences-userclass.html create mode 100644 rework-prototype/reference/referenceproject-globalreferences-userrecord.html create mode 100644 rework-prototype/reference/referenceproject-globalreferences.html create mode 100644 rework-prototype/reference/referenceproject-interfaces-empty.html create mode 100644 rework-prototype/reference/referenceproject-interfaces-instancemethods.html create mode 100644 rework-prototype/reference/referenceproject-interfaces-interfacea.html create mode 100644 rework-prototype/reference/referenceproject-interfaces-interfaceb.html create mode 100644 rework-prototype/reference/referenceproject-interfaces-interfacec.html create mode 100644 rework-prototype/reference/referenceproject-interfaces-staticmethods.html create mode 100644 rework-prototype/reference/referenceproject-interfaces.html create mode 100644 rework-prototype/reference/referenceproject-modules-modulea-modulea_a.html create mode 100644 rework-prototype/reference/referenceproject-modules-modulea-modulea_b.html create mode 100644 rework-prototype/reference/referenceproject-modules-modulea.html create mode 100644 rework-prototype/reference/referenceproject-modules.html create mode 100644 rework-prototype/reference/referenceproject-records-onefield.html create mode 100644 rework-prototype/reference/referenceproject-records-severalfields.html create mode 100644 rework-prototype/reference/referenceproject-records-withanonymousrecord.html create mode 100644 rework-prototype/reference/referenceproject-records-withattributes.html create mode 100644 rework-prototype/reference/referenceproject-records-withfunction.html create mode 100644 rework-prototype/reference/referenceproject-records-withinstancemethod.html create mode 100644 rework-prototype/reference/referenceproject-records-withstaticmethod.html create mode 100644 rework-prototype/reference/referenceproject-records.html create mode 100644 rework-prototype/reference/referenceproject-tuples-tuple2.html create mode 100644 rework-prototype/reference/referenceproject-tuples-userrank.html create mode 100644 rework-prototype/reference/referenceproject-tuples.html create mode 100644 rework-prototype/reference/referenceproject.html diff --git a/rework-prototype/content/fsdocs-default.css b/rework-prototype/content/fsdocs-default.css new file mode 100644 index 000000000..aacd189d2 --- /dev/null +++ b/rework-prototype/content/fsdocs-default.css @@ -0,0 +1,1397 @@ +:root { + --monospace-font: "Fira Code", monospace; + --system-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + --heading-font-family: var(--system-font); + + --spacing-50: 4px; + --spacing-100: 8px; + --spacing-200: 12px; + --spacing-300: 16px; + --spacing-400: 24px; + --spacing-500: 32px; + --spacing-600: 48px; + --spacing-700: 64px; + --spacing-800: 96px; + --spacing-900: 128px; + --spacing-950: 192px; + + --font-50: 12px; + --font-100: 14px; + --font-200: 16px; + --font-300: 18px; + --font-400: 20px; + --font-500: 24px; + --font-600: 30px; + --font-700: 36px; + --font-800: 48px; + --font-900: 60px; + --font-950: 72px; + + --line-height: 1.5; + --heading-line-height: 1.25; + --radius: 6px; + + --container-sm: 768px; + --container-md: 960px; + --container-lg: 1024px; + --container-xl: 1200px; + --container-xxl: 1400px; + --container-xxxl: 1800px; + --main-menu-width: 260px; + --page-menu-width: var(--main-menu-width); + --header-height: 60px; + --body-grid-template-columns: var(--main-menu-width) minmax(0, 1fr); + --body-grid-template-columns-xl: var(--main-menu-width) minmax(0, 1fr) var(--page-menu-width); + --main-menu-grid-row: 2; + --main-menu-grid-column: 1; + --main-grid-row: 2; + --main-grid-column: 2; + --dialog-width: 500px; + --api-docs-first-column-min-width: 320px; + --api-docs-second-column-min-width: 240px; + + /* light theme */ + --primary: #1e8bc3; + --background: #f5f5f6; + --text-color: #020202; + --text-hover: #282828; + --heading-color: #2e293a; + --code-background: #ffffff; + --code-color: #1a4b0b; + --header-background: #f9fbfc; + --header-border: #e8ecf1; + --header-link-color: var(--text-color); + --mobile-menu-background: var(--header-background); + --menu-color: var(--text-color); + --menu-item-hover-background: #eff0f1; + --menu-item-hover-color: var(--menu-color); + --doc-tip-background: #F7F7F7; + --link-color: #4871f7; + --link-hover: #91aafa; + --search-background: rgb(229, 231, 235); + --nav-category: rgb(156, 163, 175); + --scrollbar-track-background: #424242; + --scrollbar-track-border: #4A4A4A; + --scrollbar-thumb-background: #686868; + --shadow-color: hsla(0, 0%, 0%, .1); + --main-shadow-color: hsla(0, 0%, 0%, .025); + --aside-background: var(--header-background); + --blockquote-bacground-color: var(--header-background); + --blockquote-color: var(--text-color); + --on-this-page-color: var(--menu-color); + --page-menu-background-color: var(--header-background); + --page-menu-background-border-color: var(--header-border); + --page-menu-background-hover-border-color: var(--text-color); + --nav-item-border-color: var(--header-border); + --nav-item-active-border-color: var(--text-color); + --dialog-background-color: var(--header-background); + --dialog-empty-color: var(--nav-category); + --dialog-icon-color: var(--text-color); + --dialog-link-color: var(--link-color); + --dialog-link-hover-color: var(--header-background); + --dialog-link-hover-background-color: var(--link-hover); + --code-fence-border-color: transparent; + + --header-brand-text-transform: none; + + --code-strings-color: #0093A1; + --code-printf-color: #6B2FBA; + --code-escaped-color: #EA8675; + --code-identifiers-color: #6B2FBA; + --code-module-color: #009999; + --code-reference-color: #4974D1; + --code-value-color: #1B6600; + --code-interface-color: #43AEC6; + --code-typearg-color: #43AEC6; + --code-disposable-color: #43AEC6; + --code-property-color: #43AEC6; + --code-punctuation-color: #43AEC6; + --code-punctuation2-color: var(--text-color); + --code-function-color: #6B2FBA; + --code-function2-color: #6B2FBA; + --code-activepattern-color: #4ec9b0; + --code-unioncase-color: #4ec9b0; + --code-enumeration-color: #8C6C41; + --code-keywords-color: #0F54D6; + --code-comment-color: #707070; + --code-operators-color: #0F54D6; + --code-numbers-color: #009999; + --code-linenumbers-color: #80b0b0; + --code-mutable-color: #1b6600; + --code-inactive-color: #808080; + --code-preprocessor-color: #af75c1; + --code-fsioutput-color: #808080; + --code-tooltip-color: #d1d1d1; + +} + +/* dark theme */ + +[data-theme=dark] { + --primary: #81cfe0; + --background: rgb(20, 21, 26); + --text-color: #F7F7F7; + --text-hover: #FFF; + --heading-color: rgb(229, 231, 235); + --code-background: #28282D; + --code-color: #f5f5f6; + --header-background: #0c1318; + --header-border: #9b9b9b; + --menu-item-hover-background: #2c2624; + --doc-tip-background: #2e293a; + --link-color: #c5eff7; + --search-background: #020202; + --nav-category: rgb(207, 211, 215); + --code-strings-color: #86b4b9; + --code-printf-color: #6B2FBA; + --code-escaped-color: #EA8675; + --code-identifiers-color: #d1b3f5; + --code-module-color: #15e1e1; + --code-reference-color: #40fddd; + --code-value-color: #ffb4e9; + --code-interface-color: #43AEC6; + --code-typearg-color: #43AEC6; + --code-disposable-color: #6dd6f1; + --code-property-color: #6acfe7; + --code-punctuation-color: #43AEC6; + --code-punctuation2-color: var(--text-color); + --code-function-color: #6B2FBA; + --code-function2-color: #cbda9d; + --code-activepattern-color: #4ec9b0; + --code-unioncase-color: #4ec9b0; + --code-enumeration-color: #8C6C41; + --code-keywords-color: #a7c2f8; + --code-comment-color: #84d16e; + --code-operators-color: #b4c6ee; + --code-numbers-color: #009999; + --code-linenumbers-color: #80b0b0; + --code-mutable-color: #1b6600; + --code-inactive-color: #808080; + --code-preprocessor-color: #af75c1; + --code-fsioutput-color: #808080; + --code-tooltip-color: #d1d1d1; +} + +/* CSS Reset, source: https://www.joshwcomeau.com/css/custom-css-reset/ */ +*, *::before, *::after { + box-sizing: border-box; +} + +* { + margin: 0; +} + +html { + overflow-y: hidden; +} + +body { + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +picture, video, canvas, svg { + display: block; + max-width: 100%; +} + +input, button, textarea, select { + font: inherit; +} + +p, h1, h2, h3, h4, h5, h6 { + overflow-wrap: break-word; +} + +/* Main layout */ +body { + font-family: var(--system-font); + background-color: var(--background); + color: var(--text-color); + line-height: var(--line-height); + scroll-padding-top: var(--header-height); + scroll-behavior: smooth; +} + +header { + background-color: var(--header-background); + padding: var(--spacing-300); + height: var(--header-height); + display: flex; + align-items: center; + justify-content: space-between; + position: sticky; + top: 0; + z-index: 100; + box-shadow: 0 1px 1px var(--shadow-color); + + & .start { + display: flex; + align-items: center; + + & #menu-toggle { + position: relative; + height: var(--spacing-500); + width: var(--spacing-500); + border: 1px solid var(--header-border); + border-radius: var(--radius); + box-shadow: 0 1px 1px var(--shadow-color); + + & .icon { + top: 4px; + left: 4px; + width: calc(var(--spacing-500) - 4px); + height: calc(var(--spacing-500) - 4px); + position: absolute; + color: var(--header-link-color); + + &.open { + display: none; + } + } + + & input[type=checkbox] { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + appearance: none; + cursor: pointer; + } + + & .menu { + visibility: hidden; + height: 0; + opacity: 0; + width: 100%; + transition: all 0.2s ease-in-out; + position: fixed; + top: var(--header-height); + left: 0; + background-color: var(--mobile-menu-background); + list-style: none; + padding: var(--spacing-300); + overflow-y: auto; + } + + & input:checked + .menu { + visibility: visible; + opacity: 1; + height: calc(100vh - var(--header-height)); + } + + &:has(input:checked) { + .icon.open { + display: block; + } + + .icon.closed { + display: none; + } + } + } + + > a { + display: flex; + justify-content: center; + align-items: center; + text-decoration: none; + color: var(--header-link-color); + } + + & img { + margin: 0 var(--spacing-200); + border-radius: var(--radius); + height: calc(var(--spacing-500) - 2px); + } + + & strong { + line-height: var(--spacing-500); + font-size: var(--font-200); + display: block; + text-transform: var(--header-brand-text-transform); + font-weight: 500; + } + } + + & .end { + display: flex; + align-items: center; + + & a { + display: none; + color: var(--header-link-color); + } + + & > .themeToggle, & > .search { + cursor: pointer; + height: var(--spacing-500); + align-items: center; + margin: 0 var(--spacing-100); + } + + & > .search { + display: flex; + color: var(--header-link-color); + } + } +} + +aside { + display: none; +} + +main { + height: calc(100dvh - var(--header-height)); +} + +#content { + padding: var(--spacing-300); + + > *:first-child { + margin-top: 0; + } +} + +#fsdocs-page-menu { + display: none; + padding: var(--spacing-300); + background-color: var(--page-menu-background-color); + border-left: 1px solid var(--page-menu-background-border-color); + + &:has(.empty) { + display: none; + } + + > #on-this-page { + font-size: var(--font-100); + line-height: 1.5; + color: var(--on-this-page-color); + font-weight: 500; + margin: 0 0 var(--spacing-50); + } + + & ul { + list-style: none; + padding: 0; + margin: 0; + + & li { + border-left: 1px solid var(--header-border); + margin: 0; + + &:hover, &:focus { + border-color: var(--page-menu-background-hover-border-color); + } + + & a { + color: var(--menu-color); + text-decoration: none; + padding: var(--spacing-50) var(--spacing-100); + display: block; + overflow-x: hidden; + text-overflow: ellipsis; + } + + &.level-3 { + padding-left: var(--spacing-100); + } + + &.level-4 { + padding-left: var(--spacing-300); + } + } + } +} + +/* menu items */ +.menu { + padding: 0; + + & li { + list-style: none; + margin: 0; + } + + .nav-header { + margin-top: var(--spacing-300); + text-transform: uppercase; + font-size: var(--font-200); + font-weight: 500; + color: var(--menu-color); + } +} + +.nav-header:first-child { + margin-top: 0; +} + +.nav-item { + border-left: 1px solid var(--nav-item-border-color); + + & a { + color: var(--menu-color); + text-decoration: none; + font-size: var(--font-200); + padding: var(--spacing-100); + display: block; + overflow-x: hidden; + text-overflow: ellipsis; + + &:hover { + background-color: var(--menu-item-hover-background); + color: var(--menu-item-hover-color); + } + } + + &:hover, &.active { + border-color: var(--nav-item-active-border-color); + } + + &.active { + font-weight: 600; + } +} + +@media screen and (min-width: 768px) { + #menu-toggle { + display: none; + } + + body { + display: grid; + grid-template-rows: var(--header-height) minmax(0, 1fr); + grid-template-columns:var(--body-grid-template-columns); + gap: 0; + } + + header { + border-bottom: 1px solid var(--header-border); + grid-row: 1; + grid-column: span 2; + box-shadow: none; + + & .end { + > a { + display: flex; + align-items: center; + text-decoration: none; + + &:hover { + color: var(--link-hover); + } + } + } + } + + aside, main { + height: calc(100vh - var(--header-height)); + } + + aside { + position: sticky; + top: var(--header-height); + } + + #fsdocs-main-menu { + display: block; + padding: var(--spacing-300) var(--spacing-500); + background-color: var(--aside-background); + width: var(--main-menu-width); + border-right: 1px solid var(--header-border); + grid-row: var(--main-menu-grid-row); + grid-column: var(--main-menu-grid-column); + overflow-y: auto; + } + + main { + grid-row: var(--main-grid-row); + grid-column: var(--main-grid-column); + box-shadow: inset 1px 1px var(--main-shadow-color); + border-radius: 0; + } + + #content { + padding-left: var(--spacing-300); + padding-right: var(--spacing-300); + } +} + +@media screen and (min-width: 768px) { + #content { + max-width: calc(100vw - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + margin: 0 auto; + } +} + +@media screen and (min-width: 960px) { + #content { + max-width: calc(var(--container-md) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +@media screen and (min-width: 1024px) { + #content { + max-width: calc(var(--container-lg) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +@media screen and (min-width: 1200px) { + body { + grid-template-columns: var(--body-grid-template-columns-xl); + + &.api-docs { + grid-template-columns: var(--body-grid-template-columns); + + #content { + max-width: calc(var(--container-xl) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } + + #fsdocs-page-menu { + display: none; + } + } + } + + header { + grid-column: span 3; + } + + #fsdocs-page-menu { + grid-column: 3; + display: block; + } + + #content { + max-width: calc(var(--container-xl) - var(--main-menu-width) - var(--page-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +@media screen and (min-width: 1400px) { + body { + &.api-docs, &:has(#fsdocs-page-menu .empty) { + #content { + max-width: calc(var(--container-xxl) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } + } + } + + #content { + max-width: calc(var(--container-xxl) - var(--main-menu-width) - var(--page-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +@media screen and (min-width: 1800px) { + body { + &.api-docs, &:has(#fsdocs-page-menu .empty) { + #content { + max-width: calc(var(--container-xxxl) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + } + } + } + + #content { + max-width: calc(var(--container-xxxl) - var(--main-menu-width) - var(--page-menu-width) - var(--spacing-300) - var(--spacing-300)); + } +} + +/* Headings */ +h1, h2, h3, h4, h5, h6 { + font-family: var(--heading-font-family); +} + +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { + color: var(--heading-color); + text-decoration: none; +} + +h1 { + font-size: var(--font-600); + line-height: var(--heading-line-height); + margin-bottom: var(--spacing-400); + margin-top: var(--spacing-50); +} + +h2 { + font-size: var(--font-500); + line-height: var(--heading-line-height); + margin-top: var(--spacing-400); + margin-bottom: var(--spacing-300); +} + +h3 { + font-size: var(--font-400); + line-height: var(--heading-line-height); + margin-top: var(--spacing-300); + margin-bottom: var(--spacing-200); +} + +h4 { + font-weight: bold; +} + +h4, h5, h6 { + font-size: var(--font-300); + margin-top: var(--spacing-200); + margin-bottom: var(--spacing-200); +} + +@media screen and (min-width: 768px) { + h1 { + font-size: var(--font-800); + margin-bottom: var(--spacing-400); + line-height: var(--heading-line-height); + } + + h2 { + font-size: var(--font-700); + margin-top: var(--spacing-500); + margin-bottom: var(--spacing-400); + } + + h3 { + font-size: var(--font-600); + margin-top: var(--spacing-500); + margin-bottom: var(--spacing-200); + } + + h4 { + font-size: var(--font-500); + } + + h4, h5, h6 { + margin-top: var(--spacing-300); + } +} + +/* Common items */ +a { + color: var(--link-color); +} + +p { + line-height: 1.8; + + &:not(:last-child) { + margin-bottom: var(--spacing-300); + } +} + +ol, ul { + padding-left: var(--spacing-400); +} + +ol li, ul li { + margin: var(--spacing-100) 0; +} + +img { + max-width: 100%; +} + +#content > table { + margin: var(--spacing-300) 0; +} + +blockquote { + border-left: var(--spacing-50) solid var(--primary); + margin: var(--spacing-200) 0; + margin-left: var(--spacing-200); + padding: var(--spacing-100) var(--spacing-300); + background-color: var(--blockquote-bacground-color); + color: var(--blockquote-color); + + > p { + margin: 0; + padding: 0; + } +} + +@media screen and (min-width: 768px) { + blockquote { + margin-left: var(--spacing-400); + } +} + +/* Code snippets */ + +/* reset browser style */ + + +code, table.pre, pre { + background-color: var(--code-background); + color: var(--code-color); + font-family: var(--monospace-font); + font-variant-ligatures: none; + font-size: var(--font-200); + -webkit-text-size-adjust: 100%; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + font-size: inherit; +} + +table.pre, #content > pre.fssnip { + border: 1px solid var(--code-fence-border-color); +} + +table.pre, pre.fssnip.highlighted { + margin: var(--spacing-300) 0; + padding: var(--spacing-200); +} + +table.pre .snippet pre.fssnip { + padding: 0; + margin: 0; +} + +p > code, li > code { + padding: 2px var(--spacing-50); +} + +table.pre, pre > code { + display: block; +} + +pre.fssnip > code { + max-width: initial; + margin-bottom: initial; +} + +/* avoid problems with transparent background colors */ +pre.fssnip.highlighted > code, table.pre .fssnip, table.pre .fssnip code { + background-color: transparent; +} + +/* Custom scrollbar styling */ +body, aside, #menu-toggle .menu, table.pre, code, +.fsdocs-entity-xmldoc > div > pre, div.fsdocs-summary > pre, +dialog ul, div.fsdocs-tip, .fsdocs-xmldoc > pre { + overflow-x: auto; + max-width: 100%; + + &::-webkit-scrollbar { + height: var(--spacing-100); + width: var(--spacing-100); + } + + &::-webkit-scrollbar-track { + background-color: var(--scrollbar-track-background); + border: 1px solid var(--scrollbar-track-border); + } + + &::-webkit-scrollbar-thumb { + background-color: var(--scrollbar-thumb-background); + } +} + +body, aside, #menu-toggle .menu, table.pre, code, +.fsdocs-entity-xmldoc > div > pre, div.fsdocs-summary > pre, +dialog ul, div.fsdocs-tip, .fsdocs-xmldoc > pre { + @media screen and (min-width: 768px) { + &::-webkit-scrollbar { + height: var(--spacing-200); + width: var(--spacing-300); + } + } +} + +table.pre, code, pre.fssnip { + border-radius: var(--radius); +} + +/* Code coloring */ +.param-name, +.return-name, +.param { + font-weight: 900; + font-size: var(--font-100); + font-family: var(--monospace-font); + font-variant-ligatures: none; +} + +.fssnip { + /* strings --- and stlyes for other string related formats */ + + & span.s { + color: var(--code-strings-color); + } + + /* printf formatters */ + + & span.pf { + color: var(--code-printf-color); + } + + /* escaped chars */ + + & span.e { + color: var(--code-escaped-color); + } + + /* identifiers --- and styles for more specific identifier types */ + + & span.id { + color: var(--code-identifiers-color);; + } + + /* module */ + + & span.m { + color: var(--code-module-color); + } + + /* reference type */ + + & span.rt { + color: var(--code-reference-color); + } + + /* value type */ + + & span.vt { + color: var(--code-value-color); + } + + /* interface */ + + & span.if { + color: var(--code-interface-color); + } + + /* type argument */ + + & span.ta { + color: var(--code-typearg-color); + } + + /* disposable */ + + & span.d { + color: var(--code-disposable-color); + } + + /* property */ + + & span.prop { + color: var(--code-property-color); + } + + /* punctuation */ + + & span.p { + color: var(--code-punctuation-color); + } + + & span.pn { + color: var(--code-punctuation2-color); + } + + /* function */ + + & span.f { + color: var(--code-function-color); + } + + & span.fn { + color: var(--code-function2-color); + } + + /* active pattern */ + + & span.pat { + color: var(--code-activepattern-color); + } + + /* union case */ + + & span.u { + color: var(--code-unioncase-color); + } + + /* enumeration */ + + & span.e { + color: var(--code-enumeration-color); + } + + /* keywords */ + + & span.k { + color: var(--code-keywords-color); + } + + /* comment */ + + & span.c { + color: var(--code-comment-color); + font-weight: 400; + font-style: italic; + } + + /* operators */ + + & span.o { + color: var(--code-operators-color); + } + + /* numbers */ + + & span.n { + color: var(--code-numbers-color); + } + + /* line number */ + + & span.l { + color: var(--code-linenumbers-color); + } + + /* mutable var or ref cell */ + + & span.v { + color: var(--code-mutable-color); + font-weight: bold; + } + + /* inactive code */ + + & span.inactive { + color: var(--code-inactive-color); + } + + /* preprocessor */ + + & span.prep { + color: var(--code-preprocessor-color); + } + + /* fsi output */ + + & span.fsi { + color: var(--code-fsioutput-color); + } +} + +/* tooltips */ +div.fsdocs-tip { + z-index: 1000; + display: none; + background-color: var(--doc-tip-background); + border-radius: var(--radius); + border: 1px solid var(--header-border); + padding: var(--spacing-200); + font-family: var(--monospace-font); + font-variant-ligatures: none; + color: var(--code-color); + box-shadow: 0 1px 1px var(--shadow-color); + + & code { + color: var(--code-color); + } +} + +span[onmouseout] { + cursor: pointer; +} + +/* API docs */ +#content > div > h2:first-child { + margin-top: 0; +} + +.fsdocs-member-list-header { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; +} + +.fsdocs-xmldoc { + & pre { + overflow-x: auto; + } +} + +.table { + width: 100%; + table-layout: fixed; + + & thead tr td { + font-weight: bold; + padding: var(--spacing-400) 0; + } + + & tr { + display: flex; + flex-flow: row wrap; + column-gap: var(--spacing-300); + + & td:first-of-type { + flex: 25 0 0; + min-width: var(--api-docs-first-column-min-width); + overflow-x: hidden; + text-overflow: ellipsis; + overflow-wrap: break-word; + + & p { + margin: unset; + } + } + + & td:nth-of-type(2) { + flex: 75 0 0; + min-width: var(--api-docs-second-column-min-width); + } + } + + & tbody td { + border-top: 1px solid var(--header-border); + padding: var(--spacing-300) 0; + } + + .fsdocs-entity-xmldoc { + > div { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + + & p.fsdocs-summary { + margin: 0; + flex-grow: 1; + } + + } + } + + .fsdocs-summary-contents { + width: 100%; + } + + .fsdocs-member-xmldoc-column { + width: 100%; + display: flex; + flex-direction: column; + justify-content: flex-start; + + > * { + margin: var(--spacing-200) 0 var(--spacing-200) var(--spacing-300); + + &:first-child:is(.icon-button-row) { + margin-block: 0; + } + + &:nth-child(2) { + margin-top: 0; + } + + &:last-child { + margin-bottom: 0; + } + } + } + + .icon-button-row { + display: flex; + flex-direction: row; + justify-content: flex-end; + align-items: flex-start; + height: calc(-1 * var(--spacing-200)); + } + + .fsdocs-member-xmldoc { + & summary { + display: list-item; + counter-increment: list-item 0; + list-style: disclosure-closed outside; + cursor: pointer; + + > .fsdocs-summary { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + + & p.fsdocs-summary { + margin: 0; + flex-grow: 1; + } + + & pre { + margin-bottom: var(--spacing-200); + padding: var(--spacing-50); + flex-grow: 1; + overflow-x: auto; + } + } + } + + & details[open] summary { + list-style-type: disclosure-open; + margin-bottom: var(--spacing-200); + } + + & details > * { + margin: var(--spacing-200) 0 var(--spacing-200) var(--spacing-300); + + &:is(summary) { + margin-block: 0; + } + + &:first-child { + margin-top: 0; + } + + &:last-child { + margin-bottom: 0; + } + } + + .fsdocs-return-name, .fsdocs-param-name { + font-weight: 500; + } + + .fsdocs-param-docs p { + margin: var(--spacing-200) 0; + } + + .fsdocs-example-header { + font-size: var(--font-200); + } + + > div.fsdocs-summary { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + margin: 0 0 0 var(--spacing-300); + + & p { + margin: 0; + } + } + } +} + +.fsdocs-source-link { + display: none; + padding: 0 var(--spacing-100); + color: var(--text-color); + cursor: pointer; + height: var(--font-500); + width: var(--font-500); + margin: 0 var(--spacing-50); + + &:hover { + color: var(--primary); + } +} + +@media screen and (min-width: 768px) { + .fsdocs-source-link { + display: block; + } +} + +/* Search */ +::backdrop { + background-color: #020202; + opacity: 0.5; +} + +dialog { + background-color: var(--dialog-background-color); + margin: var(--spacing-700) auto; + padding: var(--spacing-100); + border: none; + opacity: 0; + visibility: hidden; + transition: all 0.2s ease-in-out; + border-radius: var(--radius); + width: var(--dialog-width); + + &[open] { + opacity: 1; + visibility: visible; + } + + & input[type=search] { + margin: 0; + display: block; + width: 100%; + padding: var(--spacing-200); + outline: 1px solid var(--primary); + border-radius: var(--radius); + border: none; + + &::placeholder { + font-size: var(--font-400); + } + } + + .empty { + color: var(--dialog-empty-color); + text-align: center; + font-size: var(--font-100); + margin: var(--spacing-100); + margin-bottom: 0; + } + + & ul { + overflow-y: auto; + max-height: calc(50vh - var(--spacing-700) - var(--spacing-700)); + list-style: none; + padding: 0; + + & li { + margin: 0; + border-bottom: 1px solid var(--header-border); + + &:hover { + & a, & a iconify-icon { + background-color: var(--dialog-link-hover-background-color); + color: var(--dialog-link-hover-color); + } + } + + & a { + display: flex; + padding: var(--spacing-300); + overflow-x: hidden; + color: var(--dialog-link-color); + + & iconify-icon { + color: var(--dialog-icon-color); + width: 24px; + margin-right: var(--spacing-200); + } + } + } + } +} + +/* Variables don't seem to work on ::backdrop */ +[data-theme=dark] { + ::backdrop { + opacity: 0.75; + } +} + + + + + +/* Code */ + +.fsdocs-api-code { + font-family: var(--monospace-font); + margin-bottom: 1rem; + + a.record-field-name, + a.union-case-property, + a.property { + color: var(--code-property-color); + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + + .property[id]:target, + a[id]:target { + animation-name: blink; + animation-direction: normal; + animation-duration: 0.75s; + animation-iteration-count: 2; + animation-timing-function: ease; + } + + span { + &.property { + color: var(--code-property-color); + } + + &.keyword { + color: var(--code-keywords-color); + } + + &.type { + color: var(--code-reference-color); + } + } + +} + +/* + Animations for blinking the target of a link + + It makes it easier to see where the link is pointing to +*/ +@keyframes blink { + 0% { + background-color: var(--primary); + color: var(--background); + } + 100% { + background-color: transparent; + color: var(--link-color); + } +} + +.docs-example:not(:last-child) { + margin-bottom: var(--spacing-300); +} + +/* + If there is parameter right after this one, add some margin. + + We don't want to do it for all of them, because the last one is followed by a `hr` which already adds spacing around it. +*/ +.fsdocs-doc-parameter { + margin-bottom: var(--spacing-300); +} + +/* +.button { + padding: .5rem .75rem; + color: var(--text-color); + cursor: pointer; + border-radius: var(--radius); + + &:has(iconify-icon) { + display: flex; + justify-content: center; + align-items: center; + } + + &:hover { + background-color: var(--shadow-color); + } +} */ + +.fsdocs-block { + position: relative; + padding: 1rem; + + &:not(:first-child) { + border-top: 1px solid var(--shadow-color); + } + + .actions-buttons { + /* Buttons are in the top right of the current block */ + position: absolute; + top: 1rem; + right: 1rem; + + /* Should be extract as an independant .buttons class when reworking the CSS */ + display: flex; + gap: .25rem; + flex-wrap: wrap; + justify-content: flex-start; + align-items: center; + } + +} \ No newline at end of file diff --git a/rework-prototype/content/fsdocs-details-set-expanded.js b/rework-prototype/content/fsdocs-details-set-expanded.js new file mode 100644 index 000000000..f1518cd1e --- /dev/null +++ b/rework-prototype/content/fsdocs-details-set-expanded.js @@ -0,0 +1,9 @@ +const expandDetails = !!JSON.parse(localStorage.getItem('details-expanded')); + +addEventListener('load', _ => { + if (expandDetails) { + for (const details of document.getElementsByTagName('details')) { + details.setAttribute('open', 'true'); + } + } +}); diff --git a/rework-prototype/content/fsdocs-details-toggle.js b/rework-prototype/content/fsdocs-details-toggle.js new file mode 100644 index 000000000..b8a3f67b5 --- /dev/null +++ b/rework-prototype/content/fsdocs-details-toggle.js @@ -0,0 +1,46 @@ +import { LitElement, html, css } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-core.min.js'; + +const detailsExpanded = !!JSON.parse(localStorage.getItem('details-expanded')); + +export class DetailsToggle extends LitElement { + static properties = { + _detailsExpanded: { state: true, type: Boolean }, + }; + + constructor() { + super(); + this._detailsExpanded = detailsExpanded; + document.addEventListener('detailstoggled', e => this._detailsExpanded = !!e?.detail?.expanding); + } + + static styles = css` + :host { + cursor: pointer; + } + `; + + toggleDetails() { + this._detailsExpanded = !this._detailsExpanded; + localStorage.setItem('details-expanded', JSON.stringify(this._detailsExpanded)); + if (this._detailsExpanded) { + for (const details of document.getElementsByTagName('details')) { + details.setAttribute('open', 'true'); + } + } else { + for (const details of document.getElementsByTagName('details')) { + details.removeAttribute('open'); + } + } + document.dispatchEvent(new CustomEvent('detailstoggled', { detail: { expanding: this._detailsExpanded } })); + } + + render() { + const icon = this._detailsExpanded ? 'carbon:collapse-categories' : 'carbon:expand-categories'; + const title = this._detailsExpanded ? 'Collapse details' : 'Expand details'; + return html` + + `; + } +} + +customElements.define('fsdocs-details-toggle', DetailsToggle); diff --git a/rework-prototype/content/fsdocs-search.js b/rework-prototype/content/fsdocs-search.js new file mode 100644 index 000000000..9e4c21de2 --- /dev/null +++ b/rework-prototype/content/fsdocs-search.js @@ -0,0 +1,126 @@ +import Fuse from "https://esm.sh/fuse.js@7.0.0"; + +const searchBtn = document.querySelector("#search-btn"); + +function hideSearchBtn() { + // Hide search icon if we can't search in the first place. + searchBtn.style.display = 'none'; +} + +function debounce(mainFunction, delay) { + // Declare a variable called 'timer' to store the timer ID + let timer; + + // Return an anonymous function that takes in any number of arguments + return function (...args) { + // Clear the previous timer to prevent the execution of 'mainFunction' + clearTimeout(timer); + + // Set a new timer that will execute 'mainFunction' after the specified delay + timer = setTimeout(() => { + mainFunction(...args); + }, delay); + }; +} + +const root = document.documentElement.getAttribute("data-root"); +if (root && searchBtn) { + let fuse = null; + const searchIndexUrl = `${root}/index.json`; + fetch(searchIndexUrl, {}) + .then(response => response.json()) + .then(index => { + fuse = new Fuse(index, { + includeScore: true, + keys: ['uri', 'title', 'content', 'headings'], + includeMatches: true, + limit: 20, + ignoreLocation: true, + threshold: 0.6, + minMatchCharLength: 2, + ignoreFieldNorm: true, + shouldSort: true + }); + }) + .catch(() => { + hideSearchBtn(); + }) + + const searchDialog = document.querySelector("dialog"); + const empty = document.querySelector("dialog .empty"); + const resultsElement = document.querySelector("dialog ul"); + const searchBox = document.querySelector("dialog input[type=search]"); + + searchBtn.addEventListener("click", () => { + searchDialog.showModal(); + }) + + searchDialog.addEventListener("click", ev => { + if (ev.target.tagName === "DIALOG") { + searchBox.value = ''; + searchDialog.close() + } + }) + + function searchAux(searchTerm) { + if (!fuse) return; + + const results = fuse.search(searchTerm); + if (results.length === 0) { + clearResults(); + empty.textContent = "No results were found"; + } else { + if (location.hostname === 'localhost'){ + console.table(results); + } + + empty.style.display = 'none'; + const newResultNodes = + results + .map(result => { + const item = result.item; + const li = document.createElement("li"); + const a = document.createElement("a"); + a.setAttribute("href", item.uri); + const icon = document.createElement("iconify-icon"); + icon.setAttribute("width", "24"); + icon.setAttribute("height", "24"); + icon.setAttribute("icon", item.type === "content" ? "iconoir:page" : "bxs:file-doc") + a.append(icon, item.title); + li.appendChild(a); + return li; + }); + resultsElement.replaceChildren(...newResultNodes); + } + } + + const search = debounce(searchAux, 250); + + function clearResults() { + empty.style.display = 'block'; + resultsElement.replaceChildren(); + } + + searchBox.addEventListener('keyup', ev => { + ev.stopPropagation(); + const searchTerm = ev.target.value; + if (!searchTerm) { + empty.textContent = "Type something to start searching."; + clearResults(); + } else { + search(searchTerm); + } + }); + + window.addEventListener('keyup', ev => { + if (ev.key === 'Escape' && searchDialog.open) { + searchDialog.close(); + } + + if (ev.key === '/' && !searchDialog.open) { + searchDialog.showModal(); + } + }) +} else { + hideSearchBtn(); +} diff --git a/rework-prototype/content/fsdocs-theme-set-dark.js b/rework-prototype/content/fsdocs-theme-set-dark.js new file mode 100644 index 000000000..b6eeaba3f --- /dev/null +++ b/rework-prototype/content/fsdocs-theme-set-dark.js @@ -0,0 +1,5 @@ +const prefersDark = window.matchMedia("@media (prefers-color-scheme: dark)").matches; +let currentTheme = localStorage.getItem('theme') ?? (prefersDark ? 'dark' : 'light'); +if (currentTheme === 'dark') { + window.document.documentElement.setAttribute("data-theme", 'dark'); +} diff --git a/rework-prototype/content/fsdocs-theme-toggle.js b/rework-prototype/content/fsdocs-theme-toggle.js new file mode 100644 index 000000000..5e32f9e3c --- /dev/null +++ b/rework-prototype/content/fsdocs-theme-toggle.js @@ -0,0 +1,38 @@ +import {LitElement, html, css} from 'https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-core.min.js'; + +const prefersDark = window.matchMedia("@media (prefers-color-scheme: dark)").matches; +let currentTheme = localStorage.getItem('theme') ?? (prefersDark ? 'dark' : 'light'); + +export class ThemeToggle extends LitElement { + static properties = { + _theme: {state: true, type: String}, + }; + + constructor() { + super(); + this._theme = currentTheme; + } + + static styles = css` + :host { + cursor: pointer; + box-sizing: border-box; + transform: translateY(3px); + } + `; + + changeTheme() { + this._theme = this._theme === 'light' ? 'dark' : 'light'; + localStorage.setItem('theme', this._theme); + window.document.documentElement.setAttribute("data-theme", this._theme); + } + + render() { + const icon = this._theme === 'light' ? 'basil:moon-solid' : 'basil:sun-solid'; + return html` + + `; + } +} + +customElements.define('fsdocs-theme-toggle', ThemeToggle); diff --git a/rework-prototype/content/fsdocs-theme.css b/rework-prototype/content/fsdocs-theme.css new file mode 100644 index 000000000..cd0e6a975 --- /dev/null +++ b/rework-prototype/content/fsdocs-theme.css @@ -0,0 +1 @@ +/* Override any variables here */ \ No newline at end of file diff --git a/rework-prototype/content/fsdocs-theme.js b/rework-prototype/content/fsdocs-theme.js new file mode 100644 index 000000000..eea7d521f --- /dev/null +++ b/rework-prototype/content/fsdocs-theme.js @@ -0,0 +1,35 @@ +// Automatically scroll to the active aside menu item. +const mainMenu = document.getElementById('fsdocs-main-menu'); +function scrollToActiveItem(activeItem) { + const halfMainMenuHeight = mainMenu.offsetHeight / 2 + if(activeItem.offsetTop > halfMainMenuHeight){ + mainMenu.scrollTop = (activeItem.offsetTop - halfMainMenuHeight) - (activeItem.offsetHeight / 2); + } +} + +const activeItem = document.querySelector("aside .nav-item.active"); +if (activeItem && mainMenu) { + scrollToActiveItem(activeItem); +} + +function scrollToAndExpandSelectedMember() { + if (location.hash) { + const details = document.querySelector(`tr > td.fsdocs-member-usage:has(a[href='${location.hash}']) ~ td.fsdocs-member-xmldoc > details`); + details?.setAttribute('open', 'true'); + const header = document.querySelector(`a[href='${location.hash}']`); + header?.scrollIntoView({ behavior: 'instant'}); + } +} + +scrollToAndExpandSelectedMember(); +addEventListener('hashchange', scrollToAndExpandSelectedMember); + +if(location.pathname.startsWith('/reference/')) { + // Scroll to API Reference header + const navHeaders = document.querySelectorAll(".nav-header"); + for (const navHeader of navHeaders) { + if (navHeader.textContent && navHeader.textContent.trim() === 'API Reference') { + scrollToActiveItem(navHeader); + } + } +} \ No newline at end of file diff --git a/rework-prototype/content/fsdocs-tips.js b/rework-prototype/content/fsdocs-tips.js new file mode 100644 index 000000000..787e183f4 --- /dev/null +++ b/rework-prototype/content/fsdocs-tips.js @@ -0,0 +1,59 @@ +let currentTip = null; +let currentTipElement = null; + +function hideTip(evt, name, unique) { + const el = document.getElementById(name); + el.style.display = "none"; + currentTip = null; +} + +function hideUsingEsc(e) { + hideTip(e, currentTipElement, currentTip); +} + +function showTip(evt, name, unique, owner) { + document.onkeydown = hideUsingEsc; + if (currentTip === unique) return; + currentTip = unique; + currentTipElement = name; + + const offset = 20; + let x = evt.clientX; + let y = evt.clientY + offset; + + const el = document.getElementById(name); + el.style.position = "absolute"; + el.style.display = "block"; + el.style.left = `${x}px`; + el.style.top = `${y}px`; + const maxWidth = document.documentElement.clientWidth - x - 16; + el.style.maxWidth = `${maxWidth}px`; + + const rect = el.getBoundingClientRect(); + // Move tooltip if it is out of sight + if(rect.bottom > window.innerHeight) { + y = y - el.clientHeight - offset; + el.style.top = `${y}px`; + } + + if (rect.right > window.innerWidth) { + x = y - el.clientWidth - offset; + el.style.left = `${x}px`; + const maxWidth = document.documentElement.clientWidth - x - 16; + el.style.maxWidth = `${maxWidth}px`; + } +} + +function Clipboard_CopyTo(value) { + const tempInput = document.createElement("input"); + tempInput.value = value; + document.body.appendChild(tempInput); + tempInput.select(); + document.execCommand("copy"); + document.body.removeChild(tempInput); +} + +window.showTip = showTip; +window.hideTip = hideTip; +// Used by API documentation +window.Clipboard_CopyTo = Clipboard_CopyTo; \ No newline at end of file diff --git a/rework-prototype/content/img/github-pages-settings.png b/rework-prototype/content/img/github-pages-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..a7657705daa724182a7158891b44660fd41f9a39 GIT binary patch literal 33534 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≪zkbrk9J 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 code[class*="language-"] { + padding: 0.2em 0.3em; + border-radius: 0.3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.cdata { + color: hsl(230, 4%, 64%); +} + +.token.doctype, +.token.punctuation, +.token.entity { + color: hsl(230, 8%, 24%); +} + +.token.attr-name, +.token.class-name, +.token.boolean, +.token.constant, +.token.number, +.token.atrule { + color: hsl(35, 99%, 36%); +} + +.token.keyword { + color: hsl(301, 63%, 40%); +} + +.token.property, +.token.tag, +.token.symbol, +.token.deleted, +.token.important { + color: hsl(5, 74%, 59%); +} + +.token.selector, +.token.string, +.token.char, +.token.builtin, +.token.inserted, +.token.regex, +.token.attr-value, +.token.attr-value > .token.punctuation { + color: hsl(119, 34%, 47%); +} + +.token.variable, +.token.operator, +.token.function { + color: hsl(221, 87%, 60%); +} + +.token.url { + color: hsl(198, 99%, 37%); +} + +/* HTML overrides */ +.token.attr-value > .token.punctuation.attr-equals, +.token.special-attr > .token.attr-value > .token.value.css { + color: hsl(230, 8%, 24%); +} + +/* CSS overrides */ +.language-css .token.selector { + color: hsl(5, 74%, 59%); +} + +.language-css .token.property { + color: hsl(230, 8%, 24%); +} + +.language-css .token.function, +.language-css .token.url > .token.function { + color: hsl(198, 99%, 37%); +} + +.language-css .token.url > .token.string.url { + color: hsl(119, 34%, 47%); +} + +.language-css .token.important, +.language-css .token.atrule .token.rule { + color: hsl(301, 63%, 40%); +} + +/* JS overrides */ +.language-javascript .token.operator { + color: hsl(301, 63%, 40%); +} + +.language-javascript + .token.template-string + > .token.interpolation + > .token.interpolation-punctuation.punctuation { + color: hsl(344, 84%, 43%); +} + +/* JSON overrides */ +.language-json .token.operator { + color: hsl(230, 8%, 24%); +} + +.language-json .token.null.keyword { + color: hsl(35, 99%, 36%); +} + +/* MD overrides */ +.language-markdown .token.url, +.language-markdown .token.url > .token.operator, +.language-markdown .token.url-reference.url > .token.string { + color: hsl(230, 8%, 24%); +} + +.language-markdown .token.url > .token.content { + color: hsl(221, 87%, 60%); +} + +.language-markdown .token.url > .token.url, +.language-markdown .token.url-reference.url { + color: hsl(198, 99%, 37%); +} + +.language-markdown .token.blockquote.punctuation, +.language-markdown .token.hr.punctuation { + color: hsl(230, 4%, 64%); + font-style: italic; +} + +.language-markdown .token.code-snippet { + color: hsl(119, 34%, 47%); +} + +.language-markdown .token.bold .token.content { + color: hsl(35, 99%, 36%); +} + +.language-markdown .token.italic .token.content { + color: hsl(301, 63%, 40%); +} + +.language-markdown .token.strike .token.content, +.language-markdown .token.strike .token.punctuation, +.language-markdown .token.list.punctuation, +.language-markdown .token.title.important > .token.punctuation { + color: hsl(5, 74%, 59%); +} + +/* General */ +.token.bold { + font-weight: bold; +} + +.token.comment, +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + +.token.namespace { + opacity: 0.8; +} + +/* Plugin overrides */ +/* Selectors should have higher specificity than those in the plugins' default stylesheets */ + +/* Show Invisibles plugin overrides */ +.token.token.tab:not(:empty):before, +.token.token.cr:before, +.token.token.lf:before, +.token.token.space:before { + color: hsla(230, 8%, 24%, 0.2); +} + +/* Toolbar plugin overrides */ +/* Space out all buttons and move them away from the right edge of the code block */ +div.code-toolbar > .toolbar.toolbar > .toolbar-item { + &:not(:last-child) { + margin-right: 0.5rem; + } +} + +/* Styling the buttons */ +div.code-toolbar > .toolbar.toolbar > .toolbar-item > button, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > a, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > span { + background: hsl(230, 1%, 90%); + color: hsl(230, 6%, 44%); + padding: 0.5rem; + border-radius: 0.3rem; +} + +div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:hover, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > button:focus, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:hover, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > a:focus, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:hover, +div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus { + background: hsl(230, 1%, 78%); /* custom: darken(--syntax-bg, 20%) */ + color: hsl(230, 8%, 24%); + cursor: pointer; +} + +/* Line Highlight plugin overrides */ +/* The highlighted line itself */ +.line-highlight.line-highlight { + background: hsla(230, 8%, 24%, 0.05); +} + +/* Default line numbers in Line Highlight plugin */ +.line-highlight.line-highlight:before, +.line-highlight.line-highlight[data-end]:after { + background: hsl(230, 1%, 90%); + color: hsl(230, 8%, 24%); + padding: 0.1em 0.6em; + border-radius: 0.3em; + box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2); /* same as Toolbar plugin default */ +} + +/* Hovering over a linkable line number (in the gutter area) */ +/* Requires Line Numbers plugin as well */ +pre[id].linkable-line-numbers.linkable-line-numbers + span.line-numbers-rows + > span:hover:before { + background-color: hsla(230, 8%, 24%, 0.05); +} + +/* Line Numbers and Command Line plugins overrides */ +/* Line separating gutter from coding area */ +.line-numbers.line-numbers .line-numbers-rows, +.command-line .command-line-prompt { + border-right-color: hsla(230, 8%, 24%, 0.2); +} + +/* Stuff in the gutter */ +.line-numbers .line-numbers-rows > span:before, +.command-line .command-line-prompt > span:before { + color: hsl(230, 1%, 62%); +} + +/* Match Braces plugin overrides */ +/* Note: Outline colour is inherited from the braces */ +.rainbow-braces .token.token.punctuation.brace-level-1, +.rainbow-braces .token.token.punctuation.brace-level-5, +.rainbow-braces .token.token.punctuation.brace-level-9 { + color: hsl(5, 74%, 59%); +} + +.rainbow-braces .token.token.punctuation.brace-level-2, +.rainbow-braces .token.token.punctuation.brace-level-6, +.rainbow-braces .token.token.punctuation.brace-level-10 { + color: hsl(119, 34%, 47%); +} + +.rainbow-braces .token.token.punctuation.brace-level-3, +.rainbow-braces .token.token.punctuation.brace-level-7, +.rainbow-braces .token.token.punctuation.brace-level-11 { + color: hsl(221, 87%, 60%); +} + +.rainbow-braces .token.token.punctuation.brace-level-4, +.rainbow-braces .token.token.punctuation.brace-level-8, +.rainbow-braces .token.token.punctuation.brace-level-12 { + color: hsl(301, 63%, 40%); +} + +/* Diff Highlight plugin overrides */ +/* Taken from https://github.com/atom/github/blob/master/styles/variables.less */ +pre.diff-highlight > code .token.token.deleted:not(.prefix), +pre > code.diff-highlight .token.token.deleted:not(.prefix) { + background-color: hsla(353, 100%, 66%, 0.15); +} + +pre.diff-highlight > code .token.token.deleted:not(.prefix)::-moz-selection, +pre.diff-highlight > code .token.token.deleted:not(.prefix) *::-moz-selection, +pre > code.diff-highlight .token.token.deleted:not(.prefix)::-moz-selection, +pre > code.diff-highlight .token.token.deleted:not(.prefix) *::-moz-selection { + background-color: hsla(353, 95%, 66%, 0.25); +} + +pre.diff-highlight > code .token.token.deleted:not(.prefix)::selection, +pre.diff-highlight > code .token.token.deleted:not(.prefix) *::selection, +pre > code.diff-highlight .token.token.deleted:not(.prefix)::selection, +pre > code.diff-highlight .token.token.deleted:not(.prefix) *::selection { + background-color: hsla(353, 95%, 66%, 0.25); +} + +pre.diff-highlight > code .token.token.inserted:not(.prefix), +pre > code.diff-highlight .token.token.inserted:not(.prefix) { + background-color: hsla(137, 100%, 55%, 0.15); +} + +pre.diff-highlight > code .token.token.inserted:not(.prefix)::-moz-selection, +pre.diff-highlight > code .token.token.inserted:not(.prefix) *::-moz-selection, +pre > code.diff-highlight .token.token.inserted:not(.prefix)::-moz-selection, +pre > code.diff-highlight .token.token.inserted:not(.prefix) *::-moz-selection { + background-color: hsla(135, 73%, 55%, 0.25); +} + +pre.diff-highlight > code .token.token.inserted:not(.prefix)::selection, +pre.diff-highlight > code .token.token.inserted:not(.prefix) *::selection, +pre > code.diff-highlight .token.token.inserted:not(.prefix)::selection, +pre > code.diff-highlight .token.token.inserted:not(.prefix) *::selection { + background-color: hsla(135, 73%, 55%, 0.25); +} + +/* Previewers plugin overrides */ +/* Based on https://github.com/atom-community/atom-ide-datatip/blob/master/styles/atom-ide-datatips.less and https://github.com/atom/atom/blob/master/packages/one-light-ui */ +/* Border around popup */ +.prism-previewer.prism-previewer:before, +.prism-previewer-gradient.prism-previewer-gradient div { + border-color: hsl(0, 0, 95%); +} + +/* Angle and time should remain as circles and are hence not included */ +.prism-previewer-color.prism-previewer-color:before, +.prism-previewer-gradient.prism-previewer-gradient div, +.prism-previewer-easing.prism-previewer-easing:before { + border-radius: 0.3em; +} + +/* Triangles pointing to the code */ +.prism-previewer.prism-previewer:after { + border-top-color: hsl(0, 0, 95%); +} + +.prism-previewer-flipped.prism-previewer-flipped.after { + border-bottom-color: hsl(0, 0, 95%); +} + +/* Background colour within the popup */ +.prism-previewer-angle.prism-previewer-angle:before, +.prism-previewer-time.prism-previewer-time:before, +.prism-previewer-easing.prism-previewer-easing { + background: hsl(0, 0%, 100%); +} + +/* For angle, this is the positive area (eg. 90deg will display one quadrant in this colour) */ +/* For time, this is the alternate colour */ +.prism-previewer-angle.prism-previewer-angle circle, +.prism-previewer-time.prism-previewer-time circle { + stroke: hsl(230, 8%, 24%); + stroke-opacity: 1; +} + +/* Stroke colours of the handle, direction point, and vector itself */ +.prism-previewer-easing.prism-previewer-easing circle, +.prism-previewer-easing.prism-previewer-easing path, +.prism-previewer-easing.prism-previewer-easing line { + stroke: hsl(230, 8%, 24%); +} + +/* Fill colour of the handle */ +.prism-previewer-easing.prism-previewer-easing circle { + fill: transparent; +} + +/* Prism toolbar */ + +div.code-toolbar { + position: relative; +} + +div.code-toolbar > .toolbar { + position: absolute; + z-index: 10; + top: 1em; + right: 1em; + transition: opacity 0.3s ease-in-out; + opacity: 0; +} + +div.code-toolbar:hover > .toolbar { + opacity: 1; +} + +/* Separate line b/c rules are thrown out if selector is invalid. + IE11 and old Edge versions don't support :focus-within. */ +div.code-toolbar:focus-within > .toolbar { + opacity: 1; +} + +div.code-toolbar > .toolbar > .toolbar-item { + display: inline-block; +} + +div.code-toolbar > .toolbar > .toolbar-item > a { + cursor: pointer; +} + +div.code-toolbar > .toolbar > .toolbar-item > button { + background: none; + border: 0; + color: inherit; + font: inherit; + line-height: normal; + overflow: visible; + padding: 0; + -webkit-user-select: none; /* for button */ + -moz-user-select: none; + -ms-user-select: none; +} + +div.code-toolbar > .toolbar > .toolbar-item > a, +div.code-toolbar > .toolbar > .toolbar-item > button, +div.code-toolbar > .toolbar > .toolbar-item > span { + color: #bbb; + font-size: .8em; + padding: 0 .5em; + background: #f5f2f0; + background: rgba(224, 224, 224, 0.2); + box-shadow: 0 2px 0 0 rgba(0,0,0,0.2); + border-radius: .5em; +} + +div.code-toolbar > .toolbar > .toolbar-item > a:hover, +div.code-toolbar > .toolbar > .toolbar-item > a:focus, +div.code-toolbar > .toolbar > .toolbar-item > button:hover, +div.code-toolbar > .toolbar > .toolbar-item > button:focus, +div.code-toolbar > .toolbar > .toolbar-item > span:hover, +div.code-toolbar > .toolbar > .toolbar-item > span:focus { + color: inherit; + text-decoration: none; +} diff --git a/rework-prototype/content/prism/prism.js b/rework-prototype/content/prism/prism.js new file mode 100644 index 000000000..3809d6ee8 --- /dev/null +++ b/rework-prototype/content/prism/prism.js @@ -0,0 +1,16 @@ +/* PrismJS 1.29.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+dart+fsharp+python+rust&plugins=line-highlight+line-numbers+custom-class+toolbar+copy-to-clipboard */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; +!function(e){var a=[/\b(?:async|sync|yield)\*/,/\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extends|extension|external|factory|final|finally|for|get|hide|if|implements|import|in|interface|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/],n="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp(n+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}}}};e.languages.dart=e.languages.extend("clike",{"class-name":[s,{pattern:RegExp(n+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()])"),lookbehind:!0,inside:s.inside}],keyword:a,operator:/\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/}),e.languages.insertBefore("dart","string",{"string-literal":{pattern:/r?(?:("""|''')[\s\S]*?\1|(["'])(?:\\.|(?!\2)[^\\\r\n])*\2(?!\2))/,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:\w+|\{(?:[^{}]|\{[^{}]*\})*\})/,lookbehind:!0,inside:{punctuation:/^\$\{?|\}$/,expression:{pattern:/[\s\S]+/,inside:e.languages.dart}}},string:/[\s\S]+/}},string:void 0}),e.languages.insertBefore("dart","class-name",{metadata:{pattern:/@\w+/,alias:"function"}}),e.languages.insertBefore("dart","class-name",{generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":s,keyword:a,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(Prism); +Prism.languages.fsharp=Prism.languages.extend("clike",{comment:[{pattern:/(^|[^\\])\(\*(?!\))[\s\S]*?\*\)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(?:"""[\s\S]*?"""|@"(?:""|[^"])*"|"(?:\\[\s\S]|[^\\"])*")B?/,greedy:!0},"class-name":{pattern:/(\b(?:exception|inherit|interface|new|of|type)\s+|\w\s*:\s*|\s:\??>\s*)[.\w]+\b(?:\s*(?:->|\*)\s*[.\w]+\b)*(?!\s*[:.])/,lookbehind:!0,inside:{operator:/->|\*/,punctuation:/\./}},keyword:/\b(?:let|return|use|yield)(?:!\B|\b)|\b(?:abstract|and|as|asr|assert|atomic|base|begin|break|checked|class|component|const|constraint|constructor|continue|default|delegate|do|done|downcast|downto|eager|elif|else|end|event|exception|extern|external|false|finally|fixed|for|fun|function|functor|global|if|in|include|inherit|inline|interface|internal|land|lazy|lor|lsl|lsr|lxor|match|member|method|mixin|mod|module|mutable|namespace|new|not|null|object|of|open|or|override|parallel|private|process|protected|public|pure|rec|sealed|select|sig|static|struct|tailcall|then|to|trait|true|try|type|upcast|val|virtual|void|volatile|when|while|with)\b/,number:[/\b0x[\da-fA-F]+(?:LF|lf|un)?\b/,/\b0b[01]+(?:uy|y)?\b/,/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[fm]|e[+-]?\d+)?\b/i,/\b\d+(?:[IlLsy]|UL|u[lsy]?)?\b/],operator:/([<>~&^])\1\1|([*.:<>&])\2|<-|->|[!=:]=|?|\??(?:<=|>=|<>|[-+*/%=<>])\??|[!?^&]|~[+~-]|:>|:\?>?/}),Prism.languages.insertBefore("fsharp","keyword",{preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(^#)\b(?:else|endif|if|light|line|nowarn)\b/,lookbehind:!0,alias:"keyword"}}}}),Prism.languages.insertBefore("fsharp","punctuation",{"computation-expression":{pattern:/\b[_a-z]\w*(?=\s*\{)/i,alias:"keyword"}}),Prism.languages.insertBefore("fsharp","string",{annotation:{pattern:/\[<.+?>\]/,greedy:!0,inside:{punctuation:/^\[<|>\]$/,"class-name":{pattern:/^\w+$|(^|;\s*)[A-Z]\w*(?=\()/,lookbehind:!0},"annotation-content":{pattern:/[\s\S]+/,inside:Prism.languages.fsharp}}},char:{pattern:/'(?:[^\\']|\\(?:.|\d{3}|x[a-fA-F\d]{2}|u[a-fA-F\d]{4}|U[a-fA-F\d]{8}))'B?/,greedy:!0}}); +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; +!function(e){for(var a="/\\*(?:[^*/]|\\*(?!/)|/(?!\\*)|)*\\*/",t=0;t<2;t++)a=a.replace(//g,(function(){return a}));a=a.replace(//g,(function(){return"[^\\s\\S]"})),e.languages.rust={comment:[{pattern:RegExp("(^|[^\\\\])"+a),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism); +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document&&document.querySelector){var e,t="line-numbers",i="linkable-line-numbers",n=/\n(?!$)/g,r=!0;Prism.plugins.lineHighlight={highlightLines:function(o,u,c){var h=(u="string"==typeof u?u:o.getAttribute("data-line")||"").replace(/\s+/g,"").split(",").filter(Boolean),d=+o.getAttribute("data-line-offset")||0,f=(function(){if(void 0===e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding="0",t.style.border="0",t.innerHTML=" 
     ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}()?parseInt:parseFloat)(getComputedStyle(o).lineHeight),p=Prism.util.isActive(o,t),g=o.querySelector("code"),m=p?o:g||o,v=[],y=g.textContent.match(n),b=y?y.length+1:1,A=g&&m!=g?function(e,t){var i=getComputedStyle(e),n=getComputedStyle(t);function r(e){return+e.substr(0,e.length-2)}return t.offsetTop+r(n.borderTopWidth)+r(n.paddingTop)-r(i.paddingTop)}(o,g):0;h.forEach((function(e){var t=e.split("-"),i=+t[0],n=+t[1]||i;if(!((n=Math.min(b+d,n))i&&r.setAttribute("data-end",String(n)),r.style.top=(i-d-1)*f+A+"px",r.textContent=new Array(n-i+2).join(" \n")}));v.push((function(){r.style.width=o.scrollWidth+"px"})),v.push((function(){m.appendChild(r)}))}}));var P=o.id;if(p&&Prism.util.isActive(o,i)&&P){l(o,i)||v.push((function(){o.classList.add(i)}));var E=parseInt(o.getAttribute("data-start")||"1");s(".line-numbers-rows > span",o).forEach((function(e,t){var i=t+E;e.onclick=function(){var e=P+"."+i;r=!1,location.hash=e,setTimeout((function(){r=!0}),1)}}))}return function(){v.forEach(a)}}};var o=0;Prism.hooks.add("before-sanity-check",(function(e){var t=e.element.parentElement;if(u(t)){var i=0;s(".line-highlight",t).forEach((function(e){i+=e.textContent.length,e.parentNode.removeChild(e)})),i&&/^(?: \n)+$/.test(e.code.slice(-i))&&(e.code=e.code.slice(0,-i))}})),Prism.hooks.add("complete",(function e(i){var n=i.element.parentElement;if(u(n)){clearTimeout(o);var r=Prism.plugins.lineNumbers,s=i.plugins&&i.plugins.lineNumbers;l(n,t)&&r&&!s?Prism.hooks.add("line-numbers",e):(Prism.plugins.lineHighlight.highlightLines(n)(),o=setTimeout(c,1))}})),window.addEventListener("hashchange",c),window.addEventListener("resize",(function(){s("pre").filter(u).map((function(e){return Prism.plugins.lineHighlight.highlightLines(e)})).forEach(a)}))}function s(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function l(e,t){return e.classList.contains(t)}function a(e){e()}function u(e){return!!(e&&/pre/i.test(e.nodeName)&&(e.hasAttribute("data-line")||e.id&&Prism.util.isActive(e,i)))}function c(){var e=location.hash.slice(1);s(".temporary.line-highlight").forEach((function(e){e.parentNode.removeChild(e)}));var t=(e.match(/\.([\d,-]+)$/)||[,""])[1];if(t&&!document.getElementById(e)){var i=e.slice(0,e.lastIndexOf(".")),n=document.getElementById(i);n&&(n.hasAttribute("data-line")||n.setAttribute("data-line",""),Prism.plugins.lineHighlight.highlightLines(n,t,"temporary ")(),r&&document.querySelector(".temporary.line-highlight").scrollIntoView())}}}(); +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var e="line-numbers",n=/\n(?!$)/g,t=Prism.plugins.lineNumbers={getLine:function(n,t){if("PRE"===n.tagName&&n.classList.contains(e)){var i=n.querySelector(".line-numbers-rows");if(i){var r=parseInt(n.getAttribute("data-start"),10)||1,s=r+(i.children.length-1);ts&&(t=s);var l=t-r;return i.children[l]}}},resize:function(e){r([e])},assumeViewportIndependence:!0},i=void 0;window.addEventListener("resize",(function(){t.assumeViewportIndependence&&i===window.innerWidth||(i=window.innerWidth,r(Array.prototype.slice.call(document.querySelectorAll("pre.line-numbers"))))})),Prism.hooks.add("complete",(function(t){if(t.code){var i=t.element,s=i.parentNode;if(s&&/pre/i.test(s.nodeName)&&!i.querySelector(".line-numbers-rows")&&Prism.util.isActive(i,e)){i.classList.remove(e),s.classList.add(e);var l,o=t.code.match(n),a=o?o.length+1:1,u=new Array(a+1).join("");(l=document.createElement("span")).setAttribute("aria-hidden","true"),l.className="line-numbers-rows",l.innerHTML=u,s.hasAttribute("data-start")&&(s.style.counterReset="linenumber "+(parseInt(s.getAttribute("data-start"),10)-1)),t.element.appendChild(l),r([s]),Prism.hooks.run("line-numbers",t)}}})),Prism.hooks.add("line-numbers",(function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0}))}function r(e){if(0!=(e=e.filter((function(e){var n,t=(n=e,n?window.getComputedStyle?getComputedStyle(n):n.currentStyle||null:null)["white-space"];return"pre-wrap"===t||"pre-line"===t}))).length){var t=e.map((function(e){var t=e.querySelector("code"),i=e.querySelector(".line-numbers-rows");if(t&&i){var r=e.querySelector(".line-numbers-sizer"),s=t.textContent.split(n);r||((r=document.createElement("span")).className="line-numbers-sizer",t.appendChild(r)),r.innerHTML="0",r.style.display="block";var l=r.getBoundingClientRect().height;return r.innerHTML="",{element:e,lines:s,lineHeights:[],oneLinerHeight:l,sizer:r}}})).filter(Boolean);t.forEach((function(e){var n=e.sizer,t=e.lines,i=e.lineHeights,r=e.oneLinerHeight;i[t.length-1]=void 0,t.forEach((function(e,t){if(e&&e.length>1){var s=n.appendChild(document.createElement("span"));s.style.display="block",s.textContent=e}else i[t]=r}))})),t.forEach((function(e){for(var n=e.sizer,t=e.lineHeights,i=0,r=0;r + + + + + + + + + + + + + + + + + This project is used to test the generation of API documentation for F# projects. + | ReferenceProject + + + + + + + + + + + + + + + + + + + +
    +
    + + + Header menu logo + ReferenceProject + +
    +
    + + + + + +
    +
    + +
    +
    +

    This project is used to test the generation of API documentation for F# projects.

    +

    It is both used for testing the generation but also visual inspection of the generated documentation.

    + + +
    +
    + + + +
    +
      +

      Type something to start searching.

      +
      +
      + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/index.json b/rework-prototype/index.json new file mode 100644 index 000000000..93e9222aa --- /dev/null +++ b/rework-prototype/index.json @@ -0,0 +1 @@ +[{"uri":"/reference/namespacea.html","title":"NamespaceA","content":"ModuleA","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject.html","title":"ReferenceProject","content":"Classes \nDiscriminatedUnions \nFunctions \nGlobalReferences \nInterfaces \nModules \nRecords \nTuples","headings":[],"type":"apiDocs"},{"uri":"/reference/namespacea-modulea.html","title":"ModuleA","content":"ModuleA \n \nModuleA.answer \nanswer","headings":[],"type":"apiDocs"},{"uri":"/reference/namespacea-modulea.html#answer","title":"ModuleA.answer","content":"ModuleA.answer \nanswer \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes.html","title":"Classes","content":"Classes \n \nClasses.AbstractMethods \nAbstractMethods \nClasses.Empty \nEmpty \nClasses.EmptyConstructor \nEmptyConstructor \nClasses.ExplicitFields \nExplicitFields \nClasses.InstanceMethods \nInstanceMethods \nClasses.InterfaceImplementation \nInterfaceImplementation \nClasses.OptionalInterop \nOptionalInterop \nClasses.Properties \nProperties \nClasses.SeveralConstructors \nSeveralConstructors \nClasses.StaticMethods \nStaticMethods","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-abstractmethods.html","title":"AbstractMethods","content":"AbstractMethods \n \nAbstractMethods.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \nAbstractMethods.AbstractMethod \nAbstractMethod \nAbstractMethods.AbstractMethodWithNamedArguments \nAbstractMethodWithNamedArguments \nAbstractMethods.AbstractMethodWithUnknownArguments \nAbstractMethodWithUnknownArguments","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-abstractmethods.html#\u0060\u0060.ctor\u0060\u0060","title":"AbstractMethods.\u0060\u0060.ctor\u0060\u0060","content":"AbstractMethods.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-abstractmethods.html#AbstractMethod","title":"AbstractMethods.AbstractMethod","content":"AbstractMethods.AbstractMethod \nAbstractMethod \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-abstractmethods.html#AbstractMethodWithNamedArguments","title":"AbstractMethods.AbstractMethodWithNamedArguments","content":"AbstractMethods.AbstractMethodWithNamedArguments \nAbstractMethodWithNamedArguments \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-abstractmethods.html#AbstractMethodWithUnknownArguments","title":"AbstractMethods.AbstractMethodWithUnknownArguments","content":"AbstractMethods.AbstractMethodWithUnknownArguments \nAbstractMethodWithUnknownArguments \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-empty.html","title":"Empty","content":"Empty \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-emptyconstructor.html","title":"EmptyConstructor","content":"EmptyConstructor \n \nEmptyConstructor.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-emptyconstructor.html#\u0060\u0060.ctor\u0060\u0060","title":"EmptyConstructor.\u0060\u0060.ctor\u0060\u0060","content":"EmptyConstructor.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-explicitfields.html","title":"ExplicitFields","content":"ExplicitFields \n \nExplicitFields.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \nExplicitFields.ExplicitFieldGet \nExplicitFieldGet \nExplicitFields.ExplicitFieldGetSet \nExplicitFieldGetSet","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-explicitfields.html#\u0060\u0060.ctor\u0060\u0060","title":"ExplicitFields.\u0060\u0060.ctor\u0060\u0060","content":"ExplicitFields.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-explicitfields.html#ExplicitFieldGet","title":"ExplicitFields.ExplicitFieldGet","content":"ExplicitFields.ExplicitFieldGet \nExplicitFieldGet \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-explicitfields.html#ExplicitFieldGetSet","title":"ExplicitFields.ExplicitFieldGetSet","content":"ExplicitFields.ExplicitFieldGetSet \nExplicitFieldGetSet \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-instancemethods.html","title":"InstanceMethods","content":"InstanceMethods \n \nInstanceMethods.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \nInstanceMethods.Add \nAdd \nInstanceMethods.AddCurried \nAddCurried \nInstanceMethods.Echo \nEcho \nInstanceMethods.Log \nLog \nInstanceMethods.Log \nLog \nInstanceMethods.Log \nLog \nInstanceMethods.Void \nVoid","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-instancemethods.html#\u0060\u0060.ctor\u0060\u0060","title":"InstanceMethods.\u0060\u0060.ctor\u0060\u0060","content":"InstanceMethods.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-instancemethods.html#Add","title":"InstanceMethods.Add","content":"InstanceMethods.Add \nAdd \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-instancemethods.html#AddCurried","title":"InstanceMethods.AddCurried","content":"InstanceMethods.AddCurried \nAddCurried \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-instancemethods.html#Echo","title":"InstanceMethods.Echo","content":"InstanceMethods.Echo \nEcho \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-instancemethods.html#Log","title":"InstanceMethods.Log","content":"InstanceMethods.Log \nLog \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-instancemethods.html#Log","title":"InstanceMethods.Log","content":"InstanceMethods.Log \nLog \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-instancemethods.html#Log","title":"InstanceMethods.Log","content":"InstanceMethods.Log \nLog \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-instancemethods.html#Void","title":"InstanceMethods.Void","content":"InstanceMethods.Void \nVoid \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-interfaceimplementation.html","title":"InterfaceImplementation","content":"InterfaceImplementation \n \nInterfaceImplementation.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-interfaceimplementation.html#\u0060\u0060.ctor\u0060\u0060","title":"InterfaceImplementation.\u0060\u0060.ctor\u0060\u0060","content":"InterfaceImplementation.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-optionalinterop.html","title":"OptionalInterop","content":"OptionalInterop \n \nOptionalInterop.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \nOptionalInterop.AddOne \nAddOne","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-optionalinterop.html#\u0060\u0060.ctor\u0060\u0060","title":"OptionalInterop.\u0060\u0060.ctor\u0060\u0060","content":"OptionalInterop.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-optionalinterop.html#AddOne","title":"OptionalInterop.AddOne","content":"OptionalInterop.AddOne \nAddOne \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-properties.html","title":"Properties","content":"Properties \n \nProperties.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \nProperties.StaticPropertyWithAutoImpl \nStaticPropertyWithAutoImpl \nProperties.StaticPropertyGetOnly \nStaticPropertyGetOnly \nProperties.StaticProperty \nStaticProperty \nProperties.StaticPropertyGetSet \nStaticPropertyGetSet \nProperties.StaticPropertySetOnly \nStaticPropertySetOnly","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-properties.html#\u0060\u0060.ctor\u0060\u0060","title":"Properties.\u0060\u0060.ctor\u0060\u0060","content":"Properties.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-properties.html#StaticPropertyWithAutoImpl","title":"Properties.StaticPropertyWithAutoImpl","content":"Properties.StaticPropertyWithAutoImpl \nStaticPropertyWithAutoImpl \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-properties.html#StaticPropertyGetOnly","title":"Properties.StaticPropertyGetOnly","content":"Properties.StaticPropertyGetOnly \nStaticPropertyGetOnly \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-properties.html#StaticProperty","title":"Properties.StaticProperty","content":"Properties.StaticProperty \nStaticProperty \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-properties.html#StaticPropertyGetSet","title":"Properties.StaticPropertyGetSet","content":"Properties.StaticPropertyGetSet \nStaticPropertyGetSet \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-properties.html#StaticPropertySetOnly","title":"Properties.StaticPropertySetOnly","content":"Properties.StaticPropertySetOnly \nStaticPropertySetOnly \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-severalconstructors.html","title":"SeveralConstructors","content":"SeveralConstructors \n \nSeveralConstructors.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \nSeveralConstructors.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \nSeveralConstructors.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-severalconstructors.html#\u0060\u0060.ctor\u0060\u0060","title":"SeveralConstructors.\u0060\u0060.ctor\u0060\u0060","content":"SeveralConstructors.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-severalconstructors.html#\u0060\u0060.ctor\u0060\u0060","title":"SeveralConstructors.\u0060\u0060.ctor\u0060\u0060","content":"SeveralConstructors.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-severalconstructors.html#\u0060\u0060.ctor\u0060\u0060","title":"SeveralConstructors.\u0060\u0060.ctor\u0060\u0060","content":"SeveralConstructors.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-staticmethods.html","title":"StaticMethods","content":"StaticMethods \n \nStaticMethods.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \nStaticMethods.StaticAdd \nStaticAdd \nStaticMethods.StaticAddCurried \nStaticAddCurried \nStaticMethods.StaticEcho \nStaticEcho \nStaticMethods.StaticLog \nStaticLog \nStaticMethods.StaticLog \nStaticLog \nStaticMethods.StaticLog \nStaticLog \nStaticMethods.StaticVoid \nStaticVoid","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-staticmethods.html#\u0060\u0060.ctor\u0060\u0060","title":"StaticMethods.\u0060\u0060.ctor\u0060\u0060","content":"StaticMethods.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-staticmethods.html#StaticAdd","title":"StaticMethods.StaticAdd","content":"StaticMethods.StaticAdd \nStaticAdd \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-staticmethods.html#StaticAddCurried","title":"StaticMethods.StaticAddCurried","content":"StaticMethods.StaticAddCurried \nStaticAddCurried \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-staticmethods.html#StaticEcho","title":"StaticMethods.StaticEcho","content":"StaticMethods.StaticEcho \nStaticEcho \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-staticmethods.html#StaticLog","title":"StaticMethods.StaticLog","content":"StaticMethods.StaticLog \nStaticLog \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-staticmethods.html#StaticLog","title":"StaticMethods.StaticLog","content":"StaticMethods.StaticLog \nStaticLog \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-staticmethods.html#StaticLog","title":"StaticMethods.StaticLog","content":"StaticMethods.StaticLog \nStaticLog \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-classes-staticmethods.html#StaticVoid","title":"StaticMethods.StaticVoid","content":"StaticMethods.StaticVoid \nStaticVoid \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-discriminatedunions.html","title":"DiscriminatedUnions","content":"DiscriminatedUnions \n \nDiscriminatedUnions.MultipleCases \nMultipleCases \nDiscriminatedUnions.NamedArguments \nNamedArguments \nDiscriminatedUnions.SingleCase \nSingleCase","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-discriminatedunions-multiplecases.html","title":"MultipleCases","content":"MultipleCases \n \nMultipleCases.Case1 \nCase1 \nMultipleCases.Case2 \nCase2 \nMultipleCases.Case3 \nCase3","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-discriminatedunions-multiplecases.html#Case1","title":"MultipleCases.Case1","content":"MultipleCases.Case1 \nCase1 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-discriminatedunions-multiplecases.html#Case2","title":"MultipleCases.Case2","content":"MultipleCases.Case2 \nCase2 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-discriminatedunions-multiplecases.html#Case3","title":"MultipleCases.Case3","content":"MultipleCases.Case3 \nCase3 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-discriminatedunions-namedarguments.html","title":"NamedArguments","content":"NamedArguments \n \nNamedArguments.NamedArguments \nNamedArguments","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-discriminatedunions-namedarguments.html#NamedArguments","title":"NamedArguments.NamedArguments","content":"NamedArguments.NamedArguments \nNamedArguments \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-discriminatedunions-singlecase.html","title":"SingleCase","content":"SingleCase \n \nSingleCase.SingleCase \nSingleCase","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-discriminatedunions-singlecase.html#SingleCase","title":"SingleCase.SingleCase","content":"SingleCase.SingleCase \nSingleCase \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-functions.html","title":"Functions","content":"Functions \n \nFunctions.add \nadd \nFunctions.emptyFunction \nemptyFunction \nFunctions.tupleArguments \ntupleArguments","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-functions.html#add","title":"Functions.add","content":"Functions.add \nadd \n\n This function calculates the sum of two numbers.\n ","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-functions.html#emptyFunction","title":"Functions.emptyFunction","content":"Functions.emptyFunction \nemptyFunction \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-functions.html#tupleArguments","title":"Functions.tupleArguments","content":"Functions.tupleArguments \ntupleArguments \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences.html","title":"GlobalReferences","content":"GlobalReferences \n \nGlobalReferences.CallBack \nCallBack \nGlobalReferences.UserClass \nUserClass \nGlobalReferences.UserRecord \nUserRecord","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences-callback.html","title":"CallBack","content":"CallBack \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences-userclass.html","title":"UserClass","content":"UserClass \n \nUserClass.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \nUserClass.FirstName \nFirstName \nUserClass.LastName \nLastName \nUserClass.FullName \nFullName","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences-userclass.html#\u0060\u0060.ctor\u0060\u0060","title":"UserClass.\u0060\u0060.ctor\u0060\u0060","content":"UserClass.\u0060\u0060.ctor\u0060\u0060 \n\u0060\u0060.ctor\u0060\u0060 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences-userclass.html#FirstName","title":"UserClass.FirstName","content":"UserClass.FirstName \nFirstName \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences-userclass.html#LastName","title":"UserClass.LastName","content":"UserClass.LastName \nLastName \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences-userclass.html#FullName","title":"UserClass.FullName","content":"UserClass.FullName \nFullName \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences-userrecord.html","title":"UserRecord","content":"UserRecord \n \nUserRecord.FirstName \nFirstName \nUserRecord.LastName \nLastName","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences-userrecord.html#FirstName","title":"UserRecord.FirstName","content":"UserRecord.FirstName \nFirstName \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-globalreferences-userrecord.html#LastName","title":"UserRecord.LastName","content":"UserRecord.LastName \nLastName \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces.html","title":"Interfaces","content":"Interfaces \n \nInterfaces.Empty \nEmpty \nInterfaces.InstanceMethods \nInstanceMethods \nInterfaces.InterfaceA \nInterfaceA \nInterfaces.InterfaceB \nInterfaceB \nInterfaces.InterfaceC \nInterfaceC \nInterfaces.StaticMethods \nStaticMethods","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-empty.html","title":"Empty","content":"Empty \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-instancemethods.html","title":"InstanceMethods","content":"InstanceMethods \n \nInstanceMethods.Method \nMethod","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-instancemethods.html#Method","title":"InstanceMethods.Method","content":"InstanceMethods.Method \nMethod \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-interfacea.html","title":"InterfaceA","content":"InterfaceA \n \nInterfaceA.MethodA \nMethodA","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-interfacea.html#MethodA","title":"InterfaceA.MethodA","content":"InterfaceA.MethodA \nMethodA \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-interfaceb.html","title":"InterfaceB","content":"InterfaceB \n \nInterfaceB.MethodB \nMethodB","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-interfaceb.html#MethodB","title":"InterfaceB.MethodB","content":"InterfaceB.MethodB \nMethodB \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-interfacec.html","title":"InterfaceC","content":"InterfaceC \n \nInterfaceC.MethodC \nMethodC","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-interfacec.html#MethodC","title":"InterfaceC.MethodC","content":"InterfaceC.MethodC \nMethodC \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-staticmethods.html","title":"StaticMethods","content":"StaticMethods \n \nStaticMethods.Log \nLog \nStaticMethods.Version \nVersion","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-staticmethods.html#Log","title":"StaticMethods.Log","content":"StaticMethods.Log \nLog \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-interfaces-staticmethods.html#Version","title":"StaticMethods.Version","content":"StaticMethods.Version \nVersion \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-modules.html","title":"Modules","content":"Modules \n \nModules.ModuleA \nModuleA","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-modules-modulea.html","title":"ModuleA","content":"ModuleA \n \nModuleA.ModuleA_A \nModuleA_A \nModuleA.ModuleA_B \nModuleA_B","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-modules-modulea-modulea_a.html","title":"ModuleA_A","content":"ModuleA_A \n \nModuleA_A.answer \nanswer","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-modules-modulea-modulea_a.html#answer","title":"ModuleA_A.answer","content":"ModuleA_A.answer \nanswer \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-modules-modulea-modulea_b.html","title":"ModuleA_B","content":"ModuleA_B \n \nModuleA_B.answer \nanswer","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-modules-modulea-modulea_b.html#answer","title":"ModuleA_B.answer","content":"ModuleA_B.answer \nanswer \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records.html","title":"Records","content":"Records \n \nRecords.OneField \nOneField \nRecords.SeveralFields \nSeveralFields \nRecords.WithAnonymousRecord \nWithAnonymousRecord \nRecords.WithAttributes \nWithAttributes \nRecords.WithFunction \nWithFunction \nRecords.WithInstanceMethod \nWithInstanceMethod \nRecords.WithStaticMethod \nWithStaticMethod","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-onefield.html","title":"OneField","content":"OneField \n \nOneField.Field \nField","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-onefield.html#Field","title":"OneField.Field","content":"OneField.Field \nField \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-severalfields.html","title":"SeveralFields","content":"SeveralFields \n \nSeveralFields.FirstName \nFirstName \nSeveralFields.LastName \nLastName \nSeveralFields.Age \nAge","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-severalfields.html#FirstName","title":"SeveralFields.FirstName","content":"SeveralFields.FirstName \nFirstName \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-severalfields.html#LastName","title":"SeveralFields.LastName","content":"SeveralFields.LastName \nLastName \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-severalfields.html#Age","title":"SeveralFields.Age","content":"SeveralFields.Age \nAge \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withanonymousrecord.html","title":"WithAnonymousRecord","content":"WithAnonymousRecord \n \nWithAnonymousRecord.IndentationLevel \nIndentationLevel \nWithAnonymousRecord.Data \nData","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withanonymousrecord.html#IndentationLevel","title":"WithAnonymousRecord.IndentationLevel","content":"WithAnonymousRecord.IndentationLevel \nIndentationLevel \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withanonymousrecord.html#Data","title":"WithAnonymousRecord.Data","content":"WithAnonymousRecord.Data \nData \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withattributes.html","title":"WithAttributes","content":"WithAttributes \n \nWithAttributes.Field \nField","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withattributes.html#Field","title":"WithAttributes.Field","content":"WithAttributes.Field \nField \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withfunction.html","title":"WithFunction","content":"WithFunction \n \nWithFunction.Function \nFunction","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withfunction.html#Function","title":"WithFunction.Function","content":"WithFunction.Function \nFunction \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withinstancemethod.html","title":"WithInstanceMethod","content":"WithInstanceMethod \n \nWithInstanceMethod.MyAddMethodCurry \nMyAddMethodCurry \nWithInstanceMethod.MyAddMethodUncurry \nMyAddMethodUncurry \nWithInstanceMethod.MyVoidMethod \nMyVoidMethod \nWithInstanceMethod.MyPropertyWithGetter \nMyPropertyWithGetter \nWithInstanceMethod.MyPropertyWithGetterWorksWithUnit \nMyPropertyWithGetterWorksWithUnit \nWithInstanceMethod.MyPropertyWithGetterAndSetter \nMyPropertyWithGetterAndSetter \nWithInstanceMethod.MyPropertyWithSetter \nMyPropertyWithSetter \nWithInstanceMethod.FieldA \nFieldA","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withinstancemethod.html#MyAddMethodCurry","title":"WithInstanceMethod.MyAddMethodCurry","content":"WithInstanceMethod.MyAddMethodCurry \nMyAddMethodCurry \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withinstancemethod.html#MyAddMethodUncurry","title":"WithInstanceMethod.MyAddMethodUncurry","content":"WithInstanceMethod.MyAddMethodUncurry \nMyAddMethodUncurry \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withinstancemethod.html#MyVoidMethod","title":"WithInstanceMethod.MyVoidMethod","content":"WithInstanceMethod.MyVoidMethod \nMyVoidMethod \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withinstancemethod.html#MyPropertyWithGetter","title":"WithInstanceMethod.MyPropertyWithGetter","content":"WithInstanceMethod.MyPropertyWithGetter \nMyPropertyWithGetter \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withinstancemethod.html#MyPropertyWithGetterWorksWithUnit","title":"WithInstanceMethod.MyPropertyWithGetterWorksWithUnit","content":"WithInstanceMethod.MyPropertyWithGetterWorksWithUnit \nMyPropertyWithGetterWorksWithUnit \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withinstancemethod.html#MyPropertyWithGetterAndSetter","title":"WithInstanceMethod.MyPropertyWithGetterAndSetter","content":"WithInstanceMethod.MyPropertyWithGetterAndSetter \nMyPropertyWithGetterAndSetter \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withinstancemethod.html#MyPropertyWithSetter","title":"WithInstanceMethod.MyPropertyWithSetter","content":"WithInstanceMethod.MyPropertyWithSetter \nMyPropertyWithSetter \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withinstancemethod.html#FieldA","title":"WithInstanceMethod.FieldA","content":"WithInstanceMethod.FieldA \nFieldA \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withstaticmethod.html","title":"WithStaticMethod","content":"WithStaticMethod \n \nWithStaticMethod.MyStaticMethod \nMyStaticMethod \nWithStaticMethod.FieldA \nFieldA","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withstaticmethod.html#MyStaticMethod","title":"WithStaticMethod.MyStaticMethod","content":"WithStaticMethod.MyStaticMethod \nMyStaticMethod \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-records-withstaticmethod.html#FieldA","title":"WithStaticMethod.FieldA","content":"WithStaticMethod.FieldA \nFieldA \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-tuples.html","title":"Tuples","content":"Tuples \n \nTuples.Tuple2 \nTuple2 \nTuples.UserRank \nUserRank","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-tuples-tuple2.html","title":"Tuple2","content":"Tuple2 \n \nTuple2.Item1 \nItem1 \nTuple2.Item2 \nItem2","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-tuples-tuple2.html#Item1","title":"Tuple2.Item1","content":"Tuple2.Item1 \nItem1 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-tuples-tuple2.html#Item2","title":"Tuple2.Item2","content":"Tuple2.Item2 \nItem2 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-tuples-userrank.html","title":"UserRank","content":"UserRank \n \nUserRank.Item1 \nItem1 \nUserRank.Item2 \nItem2","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-tuples-userrank.html#Item1","title":"UserRank.Item1","content":"UserRank.Item1 \nItem1 \n","headings":[],"type":"apiDocs"},{"uri":"/reference/referenceproject-tuples-userrank.html#Item2","title":"UserRank.Item2","content":"UserRank.Item2 \nItem2 \n","headings":[],"type":"apiDocs"},{"uri":"/index.html","title":"This project is used to test the generation of API documentation for F# projects.\n","content":"This project is used to test the generation of API documentation for F# projects.\nIt is both used for testing the generation but also visual inspection of the generated documentation.\n","headings":["This project is used to test the generation of API documentation for F# projects."],"type":"content"}] \ No newline at end of file diff --git a/rework-prototype/reference/index.html b/rework-prototype/reference/index.html new file mode 100644 index 000000000..d4f8206f6 --- /dev/null +++ b/rework-prototype/reference/index.html @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + ReferenceProject (API Reference) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
      +
      + + + Header menu logo + ReferenceProject + +
      +
      + + + + + +
      +
      + +
      +
      +
      +

      + API Reference +

      +

      + Available Namespaces: +

      + + + + + + + + + + + + + + + + + +
      + Namespace + + Description +
      + + NamespaceA + +
      + + ReferenceProject + +
      +
      + +
      +
      + + + +
      +
        +

        Type something to start searching.

        +
        +
        + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/namespacea-modulea.html b/rework-prototype/reference/namespacea-modulea.html new file mode 100644 index 000000000..b7c839124 --- /dev/null +++ b/rework-prototype/reference/namespacea-modulea.html @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + ModuleA (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
        +
        + + + Header menu logo + ReferenceProject + +
        +
        + + + + + +
        +
        + +
        +
        +
        +

        + ModuleA +

        +
        + + Namespace: + + + NamespaceA + +
        + + Functions and values + +
        +
        +
        +
        + + val + +   + answer +   + + : + + int +
        +
        +
        +
        + +
        +
        + + + +
        +
          +

          Type something to start searching.

          +
          +
          + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/namespacea.html b/rework-prototype/reference/namespacea.html new file mode 100644 index 000000000..23d2990f1 --- /dev/null +++ b/rework-prototype/reference/namespacea.html @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + NamespaceA | ReferenceProject + + + + + + + + + + + + + + + + + + + +
          +
          + + + Header menu logo + ReferenceProject + +
          +
          + + + + + +
          +
          + +
          +
          +
          +

          + NamespaceA Namespace +

          +
          + + + + + + + + + + + + + +
          + Modules + + Description +
          +

          + + + ModuleA + + +

          +
          +
          +
          + +
          +
          + + + + + +
          +
          +
          +
          + +
          +
          + + + +
          +
            +

            Type something to start searching.

            +
            +
            + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-abstractmethods.html b/rework-prototype/reference/referenceproject-classes-abstractmethods.html new file mode 100644 index 000000000..8f48efc19 --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-abstractmethods.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + AbstractMethods (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
            +
            + + + Header menu logo + ReferenceProject + +
            +
            + + + + + +
            +
            + +
            +
            +
            +

            + AbstractMethods +

            +
            + + Namespace: + + + ReferenceProject + +
            +
            + + Parent: + + + Classes + +
            + TODO +
            + +
            +
            + + + +
            +
              +

              Type something to start searching.

              +
              +
              + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-empty.html b/rework-prototype/reference/referenceproject-classes-empty.html new file mode 100644 index 000000000..dae14ef77 --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-empty.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + Empty (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
              +
              + + + Header menu logo + ReferenceProject + +
              +
              + + + + + +
              +
              + +
              +
              +
              +

              + Empty +

              +
              + + Namespace: + + + ReferenceProject + +
              +
              + + Parent: + + + Classes + +
              + TODO +
              + +
              +
              + + + +
              +
                +

                Type something to start searching.

                +
                +
                + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-emptyconstructor.html b/rework-prototype/reference/referenceproject-classes-emptyconstructor.html new file mode 100644 index 000000000..29fed0c41 --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-emptyconstructor.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + EmptyConstructor (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                +
                + + + Header menu logo + ReferenceProject + +
                +
                + + + + + +
                +
                + +
                +
                +
                +

                + EmptyConstructor +

                +
                + + Namespace: + + + ReferenceProject + +
                +
                + + Parent: + + + Classes + +
                + TODO +
                + +
                +
                + + + +
                +
                  +

                  Type something to start searching.

                  +
                  +
                  + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-explicitfields.html b/rework-prototype/reference/referenceproject-classes-explicitfields.html new file mode 100644 index 000000000..f24a80a2d --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-explicitfields.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + ExplicitFields (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                  +
                  + + + Header menu logo + ReferenceProject + +
                  +
                  + + + + + +
                  +
                  + +
                  +
                  +
                  +

                  + ExplicitFields +

                  +
                  + + Namespace: + + + ReferenceProject + +
                  +
                  + + Parent: + + + Classes + +
                  + TODO +
                  + +
                  +
                  + + + +
                  +
                    +

                    Type something to start searching.

                    +
                    +
                    + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-instancemethods.html b/rework-prototype/reference/referenceproject-classes-instancemethods.html new file mode 100644 index 000000000..2638861c0 --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-instancemethods.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + InstanceMethods (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                    +
                    + + + Header menu logo + ReferenceProject + +
                    +
                    + + + + + +
                    +
                    + +
                    +
                    +
                    +

                    + InstanceMethods +

                    +
                    + + Namespace: + + + ReferenceProject + +
                    +
                    + + Parent: + + + Classes + +
                    + TODO +
                    + +
                    +
                    + + + +
                    +
                      +

                      Type something to start searching.

                      +
                      +
                      + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-interfaceimplementation.html b/rework-prototype/reference/referenceproject-classes-interfaceimplementation.html new file mode 100644 index 000000000..59ff8c729 --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-interfaceimplementation.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + InterfaceImplementation (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                      +
                      + + + Header menu logo + ReferenceProject + +
                      +
                      + + + + + +
                      +
                      + +
                      +
                      +
                      +

                      + InterfaceImplementation +

                      +
                      + + Namespace: + + + ReferenceProject + +
                      +
                      + + Parent: + + + Classes + +
                      + TODO +
                      + +
                      +
                      + + + +
                      +
                        +

                        Type something to start searching.

                        +
                        +
                        + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-optionalinterop.html b/rework-prototype/reference/referenceproject-classes-optionalinterop.html new file mode 100644 index 000000000..a74fdd8fb --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-optionalinterop.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + OptionalInterop (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                        +
                        + + + Header menu logo + ReferenceProject + +
                        +
                        + + + + + +
                        +
                        + +
                        +
                        +
                        +

                        + OptionalInterop +

                        +
                        + + Namespace: + + + ReferenceProject + +
                        +
                        + + Parent: + + + Classes + +
                        + TODO +
                        + +
                        +
                        + + + +
                        +
                          +

                          Type something to start searching.

                          +
                          +
                          + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-properties.html b/rework-prototype/reference/referenceproject-classes-properties.html new file mode 100644 index 000000000..97d0822fb --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-properties.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + Properties (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                          +
                          + + + Header menu logo + ReferenceProject + +
                          +
                          + + + + + +
                          +
                          + +
                          +
                          +
                          +

                          + Properties +

                          +
                          + + Namespace: + + + ReferenceProject + +
                          +
                          + + Parent: + + + Classes + +
                          + TODO +
                          + +
                          +
                          + + + +
                          +
                            +

                            Type something to start searching.

                            +
                            +
                            + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-severalconstructors.html b/rework-prototype/reference/referenceproject-classes-severalconstructors.html new file mode 100644 index 000000000..df12f817e --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-severalconstructors.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + SeveralConstructors (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                            +
                            + + + Header menu logo + ReferenceProject + +
                            +
                            + + + + + +
                            +
                            + +
                            +
                            +
                            +

                            + SeveralConstructors +

                            +
                            + + Namespace: + + + ReferenceProject + +
                            +
                            + + Parent: + + + Classes + +
                            + TODO +
                            + +
                            +
                            + + + +
                            +
                              +

                              Type something to start searching.

                              +
                              +
                              + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes-staticmethods.html b/rework-prototype/reference/referenceproject-classes-staticmethods.html new file mode 100644 index 000000000..0a9bc76a5 --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes-staticmethods.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + StaticMethods (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                              +
                              + + + Header menu logo + ReferenceProject + +
                              +
                              + + + + + +
                              +
                              + +
                              +
                              +
                              +

                              + StaticMethods +

                              +
                              + + Namespace: + + + ReferenceProject + +
                              +
                              + + Parent: + + + Classes + +
                              + TODO +
                              + +
                              +
                              + + + +
                              +
                                +

                                Type something to start searching.

                                +
                                +
                                + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-classes.html b/rework-prototype/reference/referenceproject-classes.html new file mode 100644 index 000000000..dbbca1590 --- /dev/null +++ b/rework-prototype/reference/referenceproject-classes.html @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + Classes (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                +
                                + + + Header menu logo + ReferenceProject + +
                                +
                                + + + + + +
                                +
                                + +
                                +
                                +
                                +

                                + Classes +

                                +
                                + + Namespace: + + + ReferenceProject + +
                                + + Declared types + +

                                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                + Type + + Description +
                                + + AbstractMethods + + + +
                                + + Empty + + + +
                                + + EmptyConstructor + + + +
                                + + ExplicitFields + + + +
                                + + InstanceMethods + + + +
                                + + InterfaceImplementation + + + +
                                + + OptionalInterop + + + +
                                + + Properties + + + +
                                + + SeveralConstructors + + + +
                                + + StaticMethods + + + +
                                +

                                +
                                + +
                                +
                                + + + +
                                +
                                  +

                                  Type something to start searching.

                                  +
                                  +
                                  + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-discriminatedunions-multiplecases.html b/rework-prototype/reference/referenceproject-discriminatedunions-multiplecases.html new file mode 100644 index 000000000..0fba9b480 --- /dev/null +++ b/rework-prototype/reference/referenceproject-discriminatedunions-multiplecases.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + MultipleCases (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                  +
                                  + + + Header menu logo + ReferenceProject + +
                                  +
                                  + + + + + +
                                  +
                                  + +
                                  +
                                  +
                                  +

                                  + MultipleCases +

                                  +
                                  + + Namespace: + + + ReferenceProject + +
                                  +
                                  + + Parent: + + + DiscriminatedUnions + +
                                  + TODO +
                                  + +
                                  +
                                  + + + +
                                  +
                                    +

                                    Type something to start searching.

                                    +
                                    +
                                    + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-discriminatedunions-namedarguments.html b/rework-prototype/reference/referenceproject-discriminatedunions-namedarguments.html new file mode 100644 index 000000000..fe9eba758 --- /dev/null +++ b/rework-prototype/reference/referenceproject-discriminatedunions-namedarguments.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + NamedArguments (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                    +
                                    + + + Header menu logo + ReferenceProject + +
                                    +
                                    + + + + + +
                                    +
                                    + +
                                    +
                                    +
                                    +

                                    + NamedArguments +

                                    +
                                    + + Namespace: + + + ReferenceProject + +
                                    +
                                    + + Parent: + + + DiscriminatedUnions + +
                                    + TODO +
                                    + +
                                    +
                                    + + + +
                                    +
                                      +

                                      Type something to start searching.

                                      +
                                      +
                                      + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-discriminatedunions-singlecase.html b/rework-prototype/reference/referenceproject-discriminatedunions-singlecase.html new file mode 100644 index 000000000..7487dc9c1 --- /dev/null +++ b/rework-prototype/reference/referenceproject-discriminatedunions-singlecase.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + SingleCase (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                      +
                                      + + + Header menu logo + ReferenceProject + +
                                      +
                                      + + + + + +
                                      +
                                      + +
                                      +
                                      +
                                      +

                                      + SingleCase +

                                      +
                                      + + Namespace: + + + ReferenceProject + +
                                      +
                                      + + Parent: + + + DiscriminatedUnions + +
                                      + TODO +
                                      + +
                                      +
                                      + + + +
                                      +
                                        +

                                        Type something to start searching.

                                        +
                                        +
                                        + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-discriminatedunions.html b/rework-prototype/reference/referenceproject-discriminatedunions.html new file mode 100644 index 000000000..43bdc289c --- /dev/null +++ b/rework-prototype/reference/referenceproject-discriminatedunions.html @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + DiscriminatedUnions (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                        +
                                        + + + Header menu logo + ReferenceProject + +
                                        +
                                        + + + + + +
                                        +
                                        + +
                                        +
                                        +
                                        +

                                        + DiscriminatedUnions +

                                        +
                                        + + Namespace: + + + ReferenceProject + +
                                        + + Declared types + +

                                        + + + + + + + + + + + + + + + + + + + + + +
                                        + Type + + Description +
                                        + + MultipleCases + + + +
                                        + + NamedArguments + + + +
                                        + + SingleCase + + + +
                                        +

                                        +
                                        + +
                                        +
                                        + + + +
                                        +
                                          +

                                          Type something to start searching.

                                          +
                                          +
                                          + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-functions.html b/rework-prototype/reference/referenceproject-functions.html new file mode 100644 index 000000000..3952191ee --- /dev/null +++ b/rework-prototype/reference/referenceproject-functions.html @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + Functions (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                          +
                                          + + + Header menu logo + ReferenceProject + +
                                          +
                                          + + + + + +
                                          +
                                          + +
                                          +
                                          +
                                          +

                                          + Functions +

                                          +
                                          + + Namespace: + + + ReferenceProject + +
                                          + + Functions and values + +
                                          +
                                          +
                                          +
                                          val add :
                                          +
                                              a   : int ->
                                          +
                                              b   : int 
                                          +
                                                  -> int
                                          +
                                          +

                                          This function calculates the sum of two numbers.

                                          + +

                                          + + Parameters + +

                                          +
                                          +
                                          a : int
                                          +

                                          The first number.

                                          + +
                                          +
                                          +
                                          b : int
                                          +

                                          The second number.

                                          + +
                                          +

                                          + + Returns + +

                                          +

                                          The sum of the two numbers.

                                          + +
                                          +
                                          +
                                          +
                                          + +
                                              ()            : unit 
                                          +
                                                            -> unit
                                          +
                                          +
                                          +
                                          +
                                          +
                                          + +
                                              a              : int ->
                                          +
                                              b              : int 
                                          +
                                                             -> int
                                          +
                                          +
                                          +
                                          + +
                                          +
                                          + + + +
                                          +
                                            +

                                            Type something to start searching.

                                            +
                                            +
                                            + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-globalreferences-callback.html b/rework-prototype/reference/referenceproject-globalreferences-callback.html new file mode 100644 index 000000000..4db2b899a --- /dev/null +++ b/rework-prototype/reference/referenceproject-globalreferences-callback.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + CallBack (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                            +
                                            + + + Header menu logo + ReferenceProject + +
                                            +
                                            + + + + + +
                                            +
                                            + +
                                            +
                                            +
                                            +

                                            + CallBack +

                                            +
                                            + + Namespace: + + + ReferenceProject + +
                                            +
                                            + + Parent: + + + GlobalReferences + +
                                            + TODO +
                                            + +
                                            +
                                            + + + +
                                            +
                                              +

                                              Type something to start searching.

                                              +
                                              +
                                              + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-globalreferences-userclass.html b/rework-prototype/reference/referenceproject-globalreferences-userclass.html new file mode 100644 index 000000000..0293eb4d6 --- /dev/null +++ b/rework-prototype/reference/referenceproject-globalreferences-userclass.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + UserClass (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                              +
                                              + + + Header menu logo + ReferenceProject + +
                                              +
                                              + + + + + +
                                              +
                                              + +
                                              +
                                              +
                                              +

                                              + UserClass +

                                              +
                                              + + Namespace: + + + ReferenceProject + +
                                              +
                                              + + Parent: + + + GlobalReferences + +
                                              + TODO +
                                              + +
                                              +
                                              + + + +
                                              +
                                                +

                                                Type something to start searching.

                                                +
                                                +
                                                + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-globalreferences-userrecord.html b/rework-prototype/reference/referenceproject-globalreferences-userrecord.html new file mode 100644 index 000000000..4c9b29e60 --- /dev/null +++ b/rework-prototype/reference/referenceproject-globalreferences-userrecord.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + UserRecord (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                +
                                                + + + Header menu logo + ReferenceProject + +
                                                +
                                                + + + + + +
                                                +
                                                + +
                                                +
                                                +
                                                +

                                                + UserRecord +

                                                +
                                                + + Namespace: + + + ReferenceProject + +
                                                +
                                                + + Parent: + + + GlobalReferences + +
                                                +
                                                type UserRecord =
                                                    {
                                                        FirstName : string
                                                        LastName : string
                                                    }
                                                +
                                                +
                                                +
                                                + + UserRecord + +
                                                + Fields +
                                                +
                                                +
                                                + +
                                                +
                                                + + + +
                                                +
                                                  +

                                                  Type something to start searching.

                                                  +
                                                  +
                                                  + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-globalreferences.html b/rework-prototype/reference/referenceproject-globalreferences.html new file mode 100644 index 000000000..da5f9d93d --- /dev/null +++ b/rework-prototype/reference/referenceproject-globalreferences.html @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + GlobalReferences (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                  +
                                                  + + + Header menu logo + ReferenceProject + +
                                                  +
                                                  + + + + + +
                                                  +
                                                  + +
                                                  +
                                                  +
                                                  +

                                                  + GlobalReferences +

                                                  +
                                                  + + Namespace: + + + ReferenceProject + +
                                                  + + Declared types + +

                                                  + + + + + + + + + + + + + + + + + + + + + +
                                                  + Type + + Description +
                                                  + + CallBack + + + +
                                                  + + UserClass + + + +
                                                  + + UserRecord + + + +
                                                  +

                                                  +
                                                  + +
                                                  +
                                                  + + + +
                                                  +
                                                    +

                                                    Type something to start searching.

                                                    +
                                                    +
                                                    + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-interfaces-empty.html b/rework-prototype/reference/referenceproject-interfaces-empty.html new file mode 100644 index 000000000..bae17b920 --- /dev/null +++ b/rework-prototype/reference/referenceproject-interfaces-empty.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + Empty (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                    +
                                                    + + + Header menu logo + ReferenceProject + +
                                                    +
                                                    + + + + + +
                                                    +
                                                    + +
                                                    +
                                                    +
                                                    +

                                                    + Empty +

                                                    +
                                                    + + Namespace: + + + ReferenceProject + +
                                                    +
                                                    + + Parent: + + + Interfaces + +
                                                    + TODO +
                                                    + +
                                                    +
                                                    + + + +
                                                    +
                                                      +

                                                      Type something to start searching.

                                                      +
                                                      +
                                                      + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-interfaces-instancemethods.html b/rework-prototype/reference/referenceproject-interfaces-instancemethods.html new file mode 100644 index 000000000..c3ade72bf --- /dev/null +++ b/rework-prototype/reference/referenceproject-interfaces-instancemethods.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + InstanceMethods (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                      +
                                                      + + + Header menu logo + ReferenceProject + +
                                                      +
                                                      + + + + + +
                                                      +
                                                      + +
                                                      +
                                                      +
                                                      +

                                                      + InstanceMethods +

                                                      +
                                                      + + Namespace: + + + ReferenceProject + +
                                                      +
                                                      + + Parent: + + + Interfaces + +
                                                      + TODO +
                                                      + +
                                                      +
                                                      + + + +
                                                      +
                                                        +

                                                        Type something to start searching.

                                                        +
                                                        +
                                                        + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-interfaces-interfacea.html b/rework-prototype/reference/referenceproject-interfaces-interfacea.html new file mode 100644 index 000000000..e817171b0 --- /dev/null +++ b/rework-prototype/reference/referenceproject-interfaces-interfacea.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + InterfaceA (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                        +
                                                        + + + Header menu logo + ReferenceProject + +
                                                        +
                                                        + + + + + +
                                                        +
                                                        + +
                                                        +
                                                        +
                                                        +

                                                        + InterfaceA +

                                                        +
                                                        + + Namespace: + + + ReferenceProject + +
                                                        +
                                                        + + Parent: + + + Interfaces + +
                                                        + TODO +
                                                        + +
                                                        +
                                                        + + + +
                                                        +
                                                          +

                                                          Type something to start searching.

                                                          +
                                                          +
                                                          + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-interfaces-interfaceb.html b/rework-prototype/reference/referenceproject-interfaces-interfaceb.html new file mode 100644 index 000000000..afaba6ae7 --- /dev/null +++ b/rework-prototype/reference/referenceproject-interfaces-interfaceb.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + InterfaceB (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                          +
                                                          + + + Header menu logo + ReferenceProject + +
                                                          +
                                                          + + + + + +
                                                          +
                                                          + +
                                                          +
                                                          +
                                                          +

                                                          + InterfaceB +

                                                          +
                                                          + + Namespace: + + + ReferenceProject + +
                                                          +
                                                          + + Parent: + + + Interfaces + +
                                                          + TODO +
                                                          + +
                                                          +
                                                          + + + +
                                                          +
                                                            +

                                                            Type something to start searching.

                                                            +
                                                            +
                                                            + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-interfaces-interfacec.html b/rework-prototype/reference/referenceproject-interfaces-interfacec.html new file mode 100644 index 000000000..08705d4f4 --- /dev/null +++ b/rework-prototype/reference/referenceproject-interfaces-interfacec.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + InterfaceC (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                            +
                                                            + + + Header menu logo + ReferenceProject + +
                                                            +
                                                            + + + + + +
                                                            +
                                                            + +
                                                            +
                                                            +
                                                            +

                                                            + InterfaceC +

                                                            +
                                                            + + Namespace: + + + ReferenceProject + +
                                                            +
                                                            + + Parent: + + + Interfaces + +
                                                            + TODO +
                                                            + +
                                                            +
                                                            + + + +
                                                            +
                                                              +

                                                              Type something to start searching.

                                                              +
                                                              +
                                                              + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-interfaces-staticmethods.html b/rework-prototype/reference/referenceproject-interfaces-staticmethods.html new file mode 100644 index 000000000..78feac85e --- /dev/null +++ b/rework-prototype/reference/referenceproject-interfaces-staticmethods.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + StaticMethods (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                              +
                                                              + + + Header menu logo + ReferenceProject + +
                                                              +
                                                              + + + + + +
                                                              +
                                                              + +
                                                              +
                                                              +
                                                              +

                                                              + StaticMethods +

                                                              +
                                                              + + Namespace: + + + ReferenceProject + +
                                                              +
                                                              + + Parent: + + + Interfaces + +
                                                              + TODO +
                                                              + +
                                                              +
                                                              + + + +
                                                              +
                                                                +

                                                                Type something to start searching.

                                                                +
                                                                +
                                                                + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-interfaces.html b/rework-prototype/reference/referenceproject-interfaces.html new file mode 100644 index 000000000..735030acd --- /dev/null +++ b/rework-prototype/reference/referenceproject-interfaces.html @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + Interfaces (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                +
                                                                + + + Header menu logo + ReferenceProject + +
                                                                +
                                                                + + + + + +
                                                                +
                                                                + +
                                                                +
                                                                +
                                                                +

                                                                + Interfaces +

                                                                +
                                                                + + Namespace: + + + ReferenceProject + +
                                                                + + Declared types + +

                                                                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                                + Type + + Description +
                                                                + + Empty + + + +
                                                                + + InstanceMethods + + + +
                                                                + + InterfaceA + + + +
                                                                + + InterfaceB + + + +
                                                                + + InterfaceC + + + +
                                                                + + StaticMethods + + + +
                                                                +

                                                                +
                                                                + +
                                                                +
                                                                + + + +
                                                                +
                                                                  +

                                                                  Type something to start searching.

                                                                  +
                                                                  +
                                                                  + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-modules-modulea-modulea_a.html b/rework-prototype/reference/referenceproject-modules-modulea-modulea_a.html new file mode 100644 index 000000000..2b745bbd2 --- /dev/null +++ b/rework-prototype/reference/referenceproject-modules-modulea-modulea_a.html @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + ModuleA_A (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                  +
                                                                  + + + Header menu logo + ReferenceProject + +
                                                                  +
                                                                  + + + + + +
                                                                  +
                                                                  + +
                                                                  +
                                                                  +
                                                                  +

                                                                  + ModuleA_A +

                                                                  +
                                                                  + + Namespace: + + + ReferenceProject + +
                                                                  +
                                                                  + + Parent: + + + ModuleA + +
                                                                  + + Functions and values + +
                                                                  +
                                                                  +
                                                                  +
                                                                  + + val + +   + answer +   + + : + + int +
                                                                  +
                                                                  +
                                                                  +
                                                                  + +
                                                                  +
                                                                  + + + +
                                                                  +
                                                                    +

                                                                    Type something to start searching.

                                                                    +
                                                                    +
                                                                    + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-modules-modulea-modulea_b.html b/rework-prototype/reference/referenceproject-modules-modulea-modulea_b.html new file mode 100644 index 000000000..979a072ea --- /dev/null +++ b/rework-prototype/reference/referenceproject-modules-modulea-modulea_b.html @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + ModuleA_B (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                    +
                                                                    + + + Header menu logo + ReferenceProject + +
                                                                    +
                                                                    + + + + + +
                                                                    +
                                                                    + +
                                                                    +
                                                                    +
                                                                    +

                                                                    + ModuleA_B +

                                                                    +
                                                                    + + Namespace: + + + ReferenceProject + +
                                                                    +
                                                                    + + Parent: + + + ModuleA + +
                                                                    + + Functions and values + +
                                                                    +
                                                                    +
                                                                    +
                                                                    + + val + +   + answer +   + + : + + int +
                                                                    +
                                                                    +
                                                                    +
                                                                    + +
                                                                    +
                                                                    + + + +
                                                                    +
                                                                      +

                                                                      Type something to start searching.

                                                                      +
                                                                      +
                                                                      + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-modules-modulea.html b/rework-prototype/reference/referenceproject-modules-modulea.html new file mode 100644 index 000000000..82ec4ca13 --- /dev/null +++ b/rework-prototype/reference/referenceproject-modules-modulea.html @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + ModuleA (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                      +
                                                                      + + + Header menu logo + ReferenceProject + +
                                                                      +
                                                                      + + + + + +
                                                                      +
                                                                      + +
                                                                      +
                                                                      +
                                                                      +

                                                                      + ModuleA +

                                                                      +
                                                                      + + Namespace: + + + ReferenceProject + +
                                                                      +
                                                                      + + Parent: + + + Modules + +
                                                                      + + Declared modules + +

                                                                      + + + + + + + + + + + + + + + + + +
                                                                      + Type + + Description +
                                                                      + + ModuleA_A + + + +
                                                                      + + ModuleA_B + + + +
                                                                      +

                                                                      +
                                                                      + +
                                                                      +
                                                                      + + + +
                                                                      +
                                                                        +

                                                                        Type something to start searching.

                                                                        +
                                                                        +
                                                                        + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-modules.html b/rework-prototype/reference/referenceproject-modules.html new file mode 100644 index 000000000..50e3dfedc --- /dev/null +++ b/rework-prototype/reference/referenceproject-modules.html @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + Modules (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                        +
                                                                        + + + Header menu logo + ReferenceProject + +
                                                                        +
                                                                        + + + + + +
                                                                        +
                                                                        + +
                                                                        +
                                                                        +
                                                                        +

                                                                        + Modules +

                                                                        +
                                                                        + + Namespace: + + + ReferenceProject + +
                                                                        + + Declared modules + +

                                                                        + + + + + + + + + + + + + +
                                                                        + Type + + Description +
                                                                        + + ModuleA + + + +
                                                                        +

                                                                        +
                                                                        + +
                                                                        +
                                                                        + + + +
                                                                        +
                                                                          +

                                                                          Type something to start searching.

                                                                          +
                                                                          +
                                                                          + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-records-onefield.html b/rework-prototype/reference/referenceproject-records-onefield.html new file mode 100644 index 000000000..ccf56204e --- /dev/null +++ b/rework-prototype/reference/referenceproject-records-onefield.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + OneField (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                          +
                                                                          + + + Header menu logo + ReferenceProject + +
                                                                          +
                                                                          + + + + + +
                                                                          +
                                                                          + +
                                                                          +
                                                                          +
                                                                          +

                                                                          + OneField +

                                                                          +
                                                                          + + Namespace: + + + ReferenceProject + +
                                                                          +
                                                                          + + Parent: + + + Records + +
                                                                          +
                                                                          type OneField =
                                                                              {
                                                                                  Field : int
                                                                              }
                                                                          +
                                                                          +
                                                                          +
                                                                          + + OneField + +
                                                                          + Fields +
                                                                          +
                                                                          +
                                                                          + +
                                                                          +
                                                                          + + + +
                                                                          +
                                                                            +

                                                                            Type something to start searching.

                                                                            +
                                                                            +
                                                                            + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-records-severalfields.html b/rework-prototype/reference/referenceproject-records-severalfields.html new file mode 100644 index 000000000..c4218e527 --- /dev/null +++ b/rework-prototype/reference/referenceproject-records-severalfields.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + SeveralFields (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                            +
                                                                            + + + Header menu logo + ReferenceProject + +
                                                                            +
                                                                            + + + + + +
                                                                            +
                                                                            + +
                                                                            +
                                                                            +
                                                                            +

                                                                            + SeveralFields +

                                                                            +
                                                                            + + Namespace: + + + ReferenceProject + +
                                                                            +
                                                                            + + Parent: + + + Records + +
                                                                            +
                                                                            type SeveralFields =
                                                                                {
                                                                                    FirstName : string
                                                                                    LastName : string
                                                                                    Age : int
                                                                                }
                                                                            +
                                                                            +
                                                                            +
                                                                            + + SeveralFields + +
                                                                            + Fields +
                                                                            +
                                                                            +
                                                                            + +
                                                                            +
                                                                            + + + +
                                                                            +
                                                                              +

                                                                              Type something to start searching.

                                                                              +
                                                                              +
                                                                              + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-records-withanonymousrecord.html b/rework-prototype/reference/referenceproject-records-withanonymousrecord.html new file mode 100644 index 000000000..faf140469 --- /dev/null +++ b/rework-prototype/reference/referenceproject-records-withanonymousrecord.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + WithAnonymousRecord (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                              +
                                                                              + + + Header menu logo + ReferenceProject + +
                                                                              +
                                                                              + + + + + +
                                                                              +
                                                                              + +
                                                                              +
                                                                              +
                                                                              +

                                                                              + WithAnonymousRecord +

                                                                              +
                                                                              + + Namespace: + + + ReferenceProject + +
                                                                              +
                                                                              + + Parent: + + + Records + +
                                                                              +
                                                                              type WithAnonymousRecord =
                                                                                  {
                                                                                      IndentationLevel : int
                                                                                      Data : (type)
                                                                                  }
                                                                              +
                                                                              +
                                                                              +
                                                                              + + WithAnonymousRecord + +
                                                                              + Fields +
                                                                              +
                                                                              +
                                                                              + +
                                                                              +
                                                                              + + + +
                                                                              +
                                                                                +

                                                                                Type something to start searching.

                                                                                +
                                                                                +
                                                                                + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-records-withattributes.html b/rework-prototype/reference/referenceproject-records-withattributes.html new file mode 100644 index 000000000..fcd04e51a --- /dev/null +++ b/rework-prototype/reference/referenceproject-records-withattributes.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + WithAttributes (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                                +
                                                                                + + + Header menu logo + ReferenceProject + +
                                                                                +
                                                                                + + + + + +
                                                                                +
                                                                                + +
                                                                                +
                                                                                +
                                                                                +

                                                                                + WithAttributes +

                                                                                +
                                                                                + + Namespace: + + + ReferenceProject + +
                                                                                +
                                                                                + + Parent: + + + Records + +
                                                                                +
                                                                                type WithAttributes =
                                                                                    {
                                                                                        Field : string
                                                                                    }
                                                                                +
                                                                                +
                                                                                +
                                                                                + + WithAttributes + +
                                                                                + Fields +
                                                                                +
                                                                                +
                                                                                + +
                                                                                +
                                                                                + + + +
                                                                                +
                                                                                  +

                                                                                  Type something to start searching.

                                                                                  +
                                                                                  +
                                                                                  + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-records-withfunction.html b/rework-prototype/reference/referenceproject-records-withfunction.html new file mode 100644 index 000000000..ecd63168a --- /dev/null +++ b/rework-prototype/reference/referenceproject-records-withfunction.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + WithFunction (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                                  +
                                                                                  + + + Header menu logo + ReferenceProject + +
                                                                                  +
                                                                                  + + + + + +
                                                                                  +
                                                                                  + +
                                                                                  +
                                                                                  +
                                                                                  +

                                                                                  + WithFunction +

                                                                                  +
                                                                                  + + Namespace: + + + ReferenceProject + +
                                                                                  +
                                                                                  + + Parent: + + + Records + +
                                                                                  +
                                                                                  type WithFunction =
                                                                                      {
                                                                                          Function : int -> int
                                                                                      }
                                                                                  +
                                                                                  +
                                                                                  +
                                                                                  + + WithFunction + +
                                                                                  + Fields +
                                                                                  +
                                                                                  +
                                                                                  + +
                                                                                  +
                                                                                  + + + +
                                                                                  +
                                                                                    +

                                                                                    Type something to start searching.

                                                                                    +
                                                                                    +
                                                                                    + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-records-withinstancemethod.html b/rework-prototype/reference/referenceproject-records-withinstancemethod.html new file mode 100644 index 000000000..ecf3ca53c --- /dev/null +++ b/rework-prototype/reference/referenceproject-records-withinstancemethod.html @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + WithInstanceMethod (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                                    +
                                                                                    + + + Header menu logo + ReferenceProject + +
                                                                                    +
                                                                                    + + + + + +
                                                                                    +
                                                                                    + +
                                                                                    +
                                                                                    +
                                                                                    +

                                                                                    + WithInstanceMethod +

                                                                                    +
                                                                                    + + Namespace: + + + ReferenceProject + +
                                                                                    +
                                                                                    + + Parent: + + + Records + +
                                                                                    +
                                                                                    type WithInstanceMethod =
                                                                                        {
                                                                                            FieldA : string
                                                                                        }
                                                                                        member this.MyAddMethodCurry a * b : int
                                                                                        member this.MyAddMethodUncurry adwdwd ->  bdwdwd ->  : int
                                                                                        member this.MyVoidMethod
                                                                                        member this.MyPropertyWithGetter : int with get
                                                                                        member this.MyPropertyWithGetterWorksWithUnit with get
                                                                                        member this.MyPropertyWithGetterAndSetter with get, set
                                                                                        member this.MyPropertyWithSetter with set
                                                                                    +
                                                                                    +
                                                                                    +
                                                                                    + + WithInstanceMethod + +
                                                                                    + Fields +
                                                                                    +
                                                                                    + Members +
                                                                                    +
                                                                                    +
                                                                                    + +
                                                                                    +
                                                                                    + + + +
                                                                                    +
                                                                                      +

                                                                                      Type something to start searching.

                                                                                      +
                                                                                      +
                                                                                      + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-records-withstaticmethod.html b/rework-prototype/reference/referenceproject-records-withstaticmethod.html new file mode 100644 index 000000000..8b4e07c98 --- /dev/null +++ b/rework-prototype/reference/referenceproject-records-withstaticmethod.html @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + WithStaticMethod (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                                      +
                                                                                      + + + Header menu logo + ReferenceProject + +
                                                                                      +
                                                                                      + + + + + +
                                                                                      +
                                                                                      + +
                                                                                      +
                                                                                      +
                                                                                      +

                                                                                      + WithStaticMethod +

                                                                                      +
                                                                                      + + Namespace: + + + ReferenceProject + +
                                                                                      +
                                                                                      + + Parent: + + + Records + +
                                                                                      +
                                                                                      type WithStaticMethod =
                                                                                          {
                                                                                              FieldA : string
                                                                                          }
                                                                                      +
                                                                                      +
                                                                                      +
                                                                                      + + WithStaticMethod + +
                                                                                      + Fields +
                                                                                      +
                                                                                      + Static Members +
                                                                                      +
                                                                                      +
                                                                                      + +
                                                                                      +
                                                                                      + + + +
                                                                                      +
                                                                                        +

                                                                                        Type something to start searching.

                                                                                        +
                                                                                        +
                                                                                        + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-records.html b/rework-prototype/reference/referenceproject-records.html new file mode 100644 index 000000000..b7c08d71c --- /dev/null +++ b/rework-prototype/reference/referenceproject-records.html @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + Records (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                                        +
                                                                                        + + + Header menu logo + ReferenceProject + +
                                                                                        +
                                                                                        + + + + + +
                                                                                        +
                                                                                        + +
                                                                                        +
                                                                                        +
                                                                                        +

                                                                                        + Records +

                                                                                        +
                                                                                        + + Namespace: + + + ReferenceProject + +
                                                                                        + + Declared types + +

                                                                                        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                                                        + Type + + Description +
                                                                                        + + OneField + + + +
                                                                                        + + SeveralFields + + + +
                                                                                        + + WithAnonymousRecord + + + +
                                                                                        + + WithAttributes + + + +
                                                                                        + + WithFunction + + + +
                                                                                        + + WithInstanceMethod + + + +
                                                                                        + + WithStaticMethod + + + +
                                                                                        +

                                                                                        +
                                                                                        + +
                                                                                        +
                                                                                        + + + +
                                                                                        +
                                                                                          +

                                                                                          Type something to start searching.

                                                                                          +
                                                                                          +
                                                                                          + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-tuples-tuple2.html b/rework-prototype/reference/referenceproject-tuples-tuple2.html new file mode 100644 index 000000000..3b6e2f8e3 --- /dev/null +++ b/rework-prototype/reference/referenceproject-tuples-tuple2.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + Tuple2 (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                                          +
                                                                                          + + + Header menu logo + ReferenceProject + +
                                                                                          +
                                                                                          + + + + + +
                                                                                          +
                                                                                          + +
                                                                                          +
                                                                                          +
                                                                                          +

                                                                                          + Tuple2 +

                                                                                          +
                                                                                          + + Namespace: + + + ReferenceProject + +
                                                                                          +
                                                                                          + + Parent: + + + Tuples + +
                                                                                          + TODO +
                                                                                          + +
                                                                                          +
                                                                                          + + + +
                                                                                          +
                                                                                            +

                                                                                            Type something to start searching.

                                                                                            +
                                                                                            +
                                                                                            + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-tuples-userrank.html b/rework-prototype/reference/referenceproject-tuples-userrank.html new file mode 100644 index 000000000..e94c4c87b --- /dev/null +++ b/rework-prototype/reference/referenceproject-tuples-userrank.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + UserRank (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                                            +
                                                                                            + + + Header menu logo + ReferenceProject + +
                                                                                            +
                                                                                            + + + + + +
                                                                                            +
                                                                                            + +
                                                                                            +
                                                                                            +
                                                                                            +

                                                                                            + UserRank +

                                                                                            +
                                                                                            + + Namespace: + + + ReferenceProject + +
                                                                                            +
                                                                                            + + Parent: + + + Tuples + +
                                                                                            + TODO +
                                                                                            + +
                                                                                            +
                                                                                            + + + +
                                                                                            +
                                                                                              +

                                                                                              Type something to start searching.

                                                                                              +
                                                                                              +
                                                                                              + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject-tuples.html b/rework-prototype/reference/referenceproject-tuples.html new file mode 100644 index 000000000..f610ec7c7 --- /dev/null +++ b/rework-prototype/reference/referenceproject-tuples.html @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + Tuples (ReferenceProject) | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                                              +
                                                                                              + + + Header menu logo + ReferenceProject + +
                                                                                              +
                                                                                              + + + + + +
                                                                                              +
                                                                                              + +
                                                                                              +
                                                                                              +
                                                                                              +

                                                                                              + Tuples +

                                                                                              +
                                                                                              + + Namespace: + + + ReferenceProject + +
                                                                                              + + Declared types + +

                                                                                              + + + + + + + + + + + + + + + + + +
                                                                                              + Type + + Description +
                                                                                              + + Tuple2 + + + +
                                                                                              + + UserRank + + + +
                                                                                              +

                                                                                              +
                                                                                              + +
                                                                                              +
                                                                                              + + + +
                                                                                              +
                                                                                                +

                                                                                                Type something to start searching.

                                                                                                +
                                                                                                +
                                                                                                + + + + + + + + \ No newline at end of file diff --git a/rework-prototype/reference/referenceproject.html b/rework-prototype/reference/referenceproject.html new file mode 100644 index 000000000..c33dc087e --- /dev/null +++ b/rework-prototype/reference/referenceproject.html @@ -0,0 +1,404 @@ + + + + + + + + + + + + + + + + + + ReferenceProject | ReferenceProject + + + + + + + + + + + + + + + + + + + +
                                                                                                +
                                                                                                + + + Header menu logo + ReferenceProject + +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                + ReferenceProject Namespace +

                                                                                                +
                                                                                                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                                                                                + Modules + + Description +
                                                                                                +

                                                                                                + + + Classes + + +

                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                + + + DiscriminatedUnions + + +

                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                + + + Functions + + +

                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                + + + GlobalReferences + + +

                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                + + + Interfaces + + +

                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                + + + Modules + + +

                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                + + + Records + + +

                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +

                                                                                                + + + Tuples + + +

                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + + + +
                                                                                                +
                                                                                                +
                                                                                                +
                                                                                                + +
                                                                                                +
                                                                                                + + + +
                                                                                                +
                                                                                                  +

                                                                                                  Type something to start searching.

                                                                                                  +
                                                                                                  +
                                                                                                  + + + + + + + + \ No newline at end of file diff --git a/src/FSharp.Formatting.ApiDocs/Generate/Record.fs b/src/FSharp.Formatting.ApiDocs/Generate/Record.fs index f9bd402e5..2d6188809 100644 --- a/src/FSharp.Formatting.ApiDocs/Generate/Record.fs +++ b/src/FSharp.Formatting.ApiDocs/Generate/Record.fs @@ -153,3 +153,31 @@ let renderRecordType (entityInfo: ApiDocEntityInfo) = ] ] |> Html.minify + + +let subSectionTitle (title: string) = + div [ Class "sub-section-title" ] [ + !!title + ] + +let renderRecordVSCodeLike (entityInfo: ApiDocEntityInfo) = + let entity = entityInfo.Entity + + div [] [ + strong [] [ + !!entity.Name + ] + + if not entity.RecordFields.IsEmpty then + subSectionTitle "Fields" + + if not entity.InstanceMembers.IsEmpty then + subSectionTitle "Members" + + if not entity.StaticMembers.IsEmpty then + subSectionTitle "Static Members" + + // TODO: what are entity.StaticParameters for a record ? + // Are they generics? + + ] \ No newline at end of file diff --git a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs index 62fef2d2b..fba1add02 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs @@ -592,6 +592,9 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = if symbol.IsFSharpRecord then Generate.Record.renderRecordType entityInfo + hr [] + hr [] + Generate.Record.renderRecordVSCodeLike entityInfo else if symbol.IsFSharpModule then let linkGenerator (entity : ApiDocEntity) = entity.Url(root, collectionName, qualify, model.FileExtensions.InUrl) From 7218bc9590b64fbd9bb2037dd0fe70757045992b Mon Sep 17 00:00:00 2001 From: Maxime Mangel Date: Mon, 30 Dec 2024 00:21:56 +0100 Subject: [PATCH 6/7] WIP: save prototype for VSCode like display --- .editorconfig | 4 + rework-prototype/content/fsdocs-default.css | 336 +++++++++++++----- .../reference/referenceproject-functions.html | 93 +++-- .../Generate/Module.fs | 2 + 4 files changed, 301 insertions(+), 134 deletions(-) diff --git a/.editorconfig b/.editorconfig index 24835aeba..897cc0d89 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,6 +3,10 @@ root = true [*] end_of_line = lf +charset = utf-8 +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true [*.{fs,fsi,fsx}] charset = utf-8 diff --git a/rework-prototype/content/fsdocs-default.css b/rework-prototype/content/fsdocs-default.css index aacd189d2..0d2e1354f 100644 --- a/rework-prototype/content/fsdocs-default.css +++ b/rework-prototype/content/fsdocs-default.css @@ -1,6 +1,8 @@ :root { --monospace-font: "Fira Code", monospace; - --system-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + --system-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", + Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", + sans-serif; --heading-font-family: var(--system-font); --spacing-50: 4px; @@ -41,7 +43,8 @@ --page-menu-width: var(--main-menu-width); --header-height: 60px; --body-grid-template-columns: var(--main-menu-width) minmax(0, 1fr); - --body-grid-template-columns-xl: var(--main-menu-width) minmax(0, 1fr) var(--page-menu-width); + --body-grid-template-columns-xl: var(--main-menu-width) minmax(0, 1fr) + var(--page-menu-width); --main-menu-grid-row: 2; --main-menu-grid-column: 1; --main-grid-row: 2; @@ -65,16 +68,16 @@ --menu-color: var(--text-color); --menu-item-hover-background: #eff0f1; --menu-item-hover-color: var(--menu-color); - --doc-tip-background: #F7F7F7; + --doc-tip-background: #f7f7f7; --link-color: #4871f7; --link-hover: #91aafa; --search-background: rgb(229, 231, 235); --nav-category: rgb(156, 163, 175); --scrollbar-track-background: #424242; - --scrollbar-track-border: #4A4A4A; + --scrollbar-track-border: #4a4a4a; --scrollbar-thumb-background: #686868; - --shadow-color: hsla(0, 0%, 0%, .1); - --main-shadow-color: hsla(0, 0%, 0%, .025); + --shadow-color: hsla(0, 0%, 0%, 0.1); + --main-shadow-color: hsla(0, 0%, 0%, 0.025); --aside-background: var(--header-background); --blockquote-bacground-color: var(--header-background); --blockquote-color: var(--text-color); @@ -94,27 +97,27 @@ --header-brand-text-transform: none; - --code-strings-color: #0093A1; - --code-printf-color: #6B2FBA; - --code-escaped-color: #EA8675; - --code-identifiers-color: #6B2FBA; + --code-strings-color: #0093a1; + --code-printf-color: #6b2fba; + --code-escaped-color: #ea8675; + --code-identifiers-color: #6b2fba; --code-module-color: #009999; - --code-reference-color: #4974D1; - --code-value-color: #1B6600; - --code-interface-color: #43AEC6; - --code-typearg-color: #43AEC6; - --code-disposable-color: #43AEC6; - --code-property-color: #43AEC6; - --code-punctuation-color: #43AEC6; + --code-reference-color: #4974d1; + --code-value-color: #1b6600; + --code-interface-color: #43aec6; + --code-typearg-color: #43aec6; + --code-disposable-color: #43aec6; + --code-property-color: #43aec6; + --code-punctuation-color: #43aec6; --code-punctuation2-color: var(--text-color); - --code-function-color: #6B2FBA; - --code-function2-color: #6B2FBA; + --code-function-color: #6b2fba; + --code-function2-color: #6b2fba; --code-activepattern-color: #4ec9b0; --code-unioncase-color: #4ec9b0; - --code-enumeration-color: #8C6C41; - --code-keywords-color: #0F54D6; + --code-enumeration-color: #8c6c41; + --code-keywords-color: #0f54d6; --code-comment-color: #707070; - --code-operators-color: #0F54D6; + --code-operators-color: #0f54d6; --code-numbers-color: #009999; --code-linenumbers-color: #80b0b0; --code-mutable-color: #1b6600; @@ -122,18 +125,17 @@ --code-preprocessor-color: #af75c1; --code-fsioutput-color: #808080; --code-tooltip-color: #d1d1d1; - } /* dark theme */ -[data-theme=dark] { +[data-theme="dark"] { --primary: #81cfe0; --background: rgb(20, 21, 26); - --text-color: #F7F7F7; - --text-hover: #FFF; + --text-color: #f7f7f7; + --text-hover: #fff; --heading-color: rgb(229, 231, 235); - --code-background: #28282D; + --code-background: #28282d; --code-color: #f5f5f6; --header-background: #0c1318; --header-border: #9b9b9b; @@ -143,23 +145,23 @@ --search-background: #020202; --nav-category: rgb(207, 211, 215); --code-strings-color: #86b4b9; - --code-printf-color: #6B2FBA; - --code-escaped-color: #EA8675; + --code-printf-color: #6b2fba; + --code-escaped-color: #ea8675; --code-identifiers-color: #d1b3f5; --code-module-color: #15e1e1; --code-reference-color: #40fddd; --code-value-color: #ffb4e9; - --code-interface-color: #43AEC6; - --code-typearg-color: #43AEC6; + --code-interface-color: #43aec6; + --code-typearg-color: #43aec6; --code-disposable-color: #6dd6f1; --code-property-color: #6acfe7; - --code-punctuation-color: #43AEC6; + --code-punctuation-color: #43aec6; --code-punctuation2-color: var(--text-color); - --code-function-color: #6B2FBA; + --code-function-color: #6b2fba; --code-function2-color: #cbda9d; --code-activepattern-color: #4ec9b0; --code-unioncase-color: #4ec9b0; - --code-enumeration-color: #8C6C41; + --code-enumeration-color: #8c6c41; --code-keywords-color: #a7c2f8; --code-comment-color: #84d16e; --code-operators-color: #b4c6ee; @@ -173,7 +175,9 @@ } /* CSS Reset, source: https://www.joshwcomeau.com/css/custom-css-reset/ */ -*, *::before, *::after { +*, +*::before, +*::after { box-sizing: border-box; } @@ -190,16 +194,28 @@ body { -webkit-font-smoothing: antialiased; } -picture, video, canvas, svg { +picture, +video, +canvas, +svg { display: block; max-width: 100%; } -input, button, textarea, select { +input, +button, +textarea, +select { font: inherit; } -p, h1, h2, h3, h4, h5, h6 { +p, +h1, +h2, +h3, +h4, +h5, +h6 { overflow-wrap: break-word; } @@ -250,7 +266,7 @@ header { } } - & input[type=checkbox] { + & input[type="checkbox"] { position: absolute; width: 100%; height: 100%; @@ -324,7 +340,8 @@ header { color: var(--header-link-color); } - & > .themeToggle, & > .search { + & > .themeToggle, + & > .search { cursor: pointer; height: var(--spacing-500); align-items: center; @@ -381,7 +398,8 @@ main { border-left: 1px solid var(--header-border); margin: 0; - &:hover, &:focus { + &:hover, + &:focus { border-color: var(--page-menu-background-hover-border-color); } @@ -445,7 +463,8 @@ main { } } - &:hover, &.active { + &:hover, + &.active { border-color: var(--nav-item-active-border-color); } @@ -462,7 +481,7 @@ main { body { display: grid; grid-template-rows: var(--header-height) minmax(0, 1fr); - grid-template-columns:var(--body-grid-template-columns); + grid-template-columns: var(--body-grid-template-columns); gap: 0; } @@ -485,7 +504,8 @@ main { } } - aside, main { + aside, + main { height: calc(100vh - var(--header-height)); } @@ -520,20 +540,29 @@ main { @media screen and (min-width: 768px) { #content { - max-width: calc(100vw - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + max-width: calc( + 100vw - var(--main-menu-width) - var(--spacing-300) - + var(--spacing-300) + ); margin: 0 auto; } } @media screen and (min-width: 960px) { #content { - max-width: calc(var(--container-md) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + max-width: calc( + var(--container-md) - var(--main-menu-width) - var(--spacing-300) - + var(--spacing-300) + ); } } @media screen and (min-width: 1024px) { #content { - max-width: calc(var(--container-lg) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + max-width: calc( + var(--container-lg) - var(--main-menu-width) - var(--spacing-300) - + var(--spacing-300) + ); } } @@ -545,7 +574,10 @@ main { grid-template-columns: var(--body-grid-template-columns); #content { - max-width: calc(var(--container-xl) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + max-width: calc( + var(--container-xl) - var(--main-menu-width) - + var(--spacing-300) - var(--spacing-300) + ); } #fsdocs-page-menu { @@ -564,44 +596,71 @@ main { } #content { - max-width: calc(var(--container-xl) - var(--main-menu-width) - var(--page-menu-width) - var(--spacing-300) - var(--spacing-300)); + max-width: calc( + var(--container-xl) - var(--main-menu-width) - + var(--page-menu-width) - var(--spacing-300) - var(--spacing-300) + ); } } @media screen and (min-width: 1400px) { body { - &.api-docs, &:has(#fsdocs-page-menu .empty) { + &.api-docs, + &:has(#fsdocs-page-menu .empty) { #content { - max-width: calc(var(--container-xxl) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + max-width: calc( + var(--container-xxl) - var(--main-menu-width) - + var(--spacing-300) - var(--spacing-300) + ); } } } #content { - max-width: calc(var(--container-xxl) - var(--main-menu-width) - var(--page-menu-width) - var(--spacing-300) - var(--spacing-300)); + max-width: calc( + var(--container-xxl) - var(--main-menu-width) - + var(--page-menu-width) - var(--spacing-300) - var(--spacing-300) + ); } } @media screen and (min-width: 1800px) { body { - &.api-docs, &:has(#fsdocs-page-menu .empty) { + &.api-docs, + &:has(#fsdocs-page-menu .empty) { #content { - max-width: calc(var(--container-xxxl) - var(--main-menu-width) - var(--spacing-300) - var(--spacing-300)); + max-width: calc( + var(--container-xxxl) - var(--main-menu-width) - + var(--spacing-300) - var(--spacing-300) + ); } } } #content { - max-width: calc(var(--container-xxxl) - var(--main-menu-width) - var(--page-menu-width) - var(--spacing-300) - var(--spacing-300)); + max-width: calc( + var(--container-xxxl) - var(--main-menu-width) - + var(--page-menu-width) - var(--spacing-300) - var(--spacing-300) + ); } } /* Headings */ -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { font-family: var(--heading-font-family); } -h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { +h1 a, +h2 a, +h3 a, +h4 a, +h5 a, +h6 a { color: var(--heading-color); text-decoration: none; } @@ -631,7 +690,9 @@ h4 { font-weight: bold; } -h4, h5, h6 { +h4, +h5, +h6 { font-size: var(--font-300); margin-top: var(--spacing-200); margin-bottom: var(--spacing-200); @@ -660,7 +721,9 @@ h4, h5, h6 { font-size: var(--font-500); } - h4, h5, h6 { + h4, + h5, + h6 { margin-top: var(--spacing-300); } } @@ -672,17 +735,19 @@ a { p { line-height: 1.8; - + &:not(:last-child) { margin-bottom: var(--spacing-300); } } -ol, ul { +ol, +ul { padding-left: var(--spacing-400); } -ol li, ul li { +ol li, +ul li { margin: var(--spacing-100) 0; } @@ -718,25 +783,33 @@ blockquote { /* reset browser style */ - -code, table.pre, pre { +code, +table.pre, +pre { background-color: var(--code-background); color: var(--code-color); - font-family: var(--monospace-font); + font-family: var(--monospace-font); font-variant-ligatures: none; font-size: var(--font-200); -webkit-text-size-adjust: 100%; } -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { +h1 code, +h2 code, +h3 code, +h4 code, +h5 code, +h6 code { font-size: inherit; -} +} -table.pre, #content > pre.fssnip { +table.pre, +#content > pre.fssnip { border: 1px solid var(--code-fence-border-color); } -table.pre, pre.fssnip.highlighted { +table.pre, +pre.fssnip.highlighted { margin: var(--spacing-300) 0; padding: var(--spacing-200); } @@ -746,11 +819,13 @@ table.pre .snippet pre.fssnip { margin: 0; } -p > code, li > code { +p > code, +li > code { padding: 2px var(--spacing-50); } -table.pre, pre > code { +table.pre, +pre > code { display: block; } @@ -760,14 +835,23 @@ pre.fssnip > code { } /* avoid problems with transparent background colors */ -pre.fssnip.highlighted > code, table.pre .fssnip, table.pre .fssnip code { +pre.fssnip.highlighted > code, +table.pre .fssnip, +table.pre .fssnip code { background-color: transparent; } /* Custom scrollbar styling */ -body, aside, #menu-toggle .menu, table.pre, code, -.fsdocs-entity-xmldoc > div > pre, div.fsdocs-summary > pre, -dialog ul, div.fsdocs-tip, .fsdocs-xmldoc > pre { +body, +aside, +#menu-toggle .menu, +table.pre, +code, +.fsdocs-entity-xmldoc > div > pre, +div.fsdocs-summary > pre, +dialog ul, +div.fsdocs-tip, +.fsdocs-xmldoc > pre { overflow-x: auto; max-width: 100%; @@ -786,9 +870,16 @@ dialog ul, div.fsdocs-tip, .fsdocs-xmldoc > pre { } } -body, aside, #menu-toggle .menu, table.pre, code, -.fsdocs-entity-xmldoc > div > pre, div.fsdocs-summary > pre, -dialog ul, div.fsdocs-tip, .fsdocs-xmldoc > pre { +body, +aside, +#menu-toggle .menu, +table.pre, +code, +.fsdocs-entity-xmldoc > div > pre, +div.fsdocs-summary > pre, +dialog ul, +div.fsdocs-tip, +.fsdocs-xmldoc > pre { @media screen and (min-width: 768px) { &::-webkit-scrollbar { height: var(--spacing-200); @@ -797,7 +888,9 @@ dialog ul, div.fsdocs-tip, .fsdocs-xmldoc > pre { } } -table.pre, code, pre.fssnip { +table.pre, +code, +pre.fssnip { border-radius: var(--radius); } @@ -833,7 +926,7 @@ table.pre, code, pre.fssnip { /* identifiers --- and styles for more specific identifier types */ & span.id { - color: var(--code-identifiers-color);; + color: var(--code-identifiers-color); } /* module */ @@ -1062,7 +1155,6 @@ span[onmouseout] { margin: 0; flex-grow: 1; } - } } @@ -1149,7 +1241,8 @@ span[onmouseout] { } } - .fsdocs-return-name, .fsdocs-param-name { + .fsdocs-return-name, + .fsdocs-param-name { font-weight: 500; } @@ -1166,7 +1259,7 @@ span[onmouseout] { flex-direction: row; justify-content: space-between; align-items: flex-start; - margin: 0 0 0 var(--spacing-300); + margin: 0 0 0 var(--spacing-300); & p { margin: 0; @@ -1217,7 +1310,7 @@ dialog { visibility: visible; } - & input[type=search] { + & input[type="search"] { margin: 0; display: block; width: 100%; @@ -1250,7 +1343,8 @@ dialog { border-bottom: 1px solid var(--header-border); &:hover { - & a, & a iconify-icon { + & a, + & a iconify-icon { background-color: var(--dialog-link-hover-background-color); color: var(--dialog-link-hover-color); } @@ -1273,16 +1367,12 @@ dialog { } /* Variables don't seem to work on ::backdrop */ -[data-theme=dark] { +[data-theme="dark"] { ::backdrop { opacity: 0.75; } } - - - - /* Code */ .fsdocs-api-code { @@ -1317,16 +1407,15 @@ dialog { &.keyword { color: var(--code-keywords-color); } - + &.type { color: var(--code-reference-color); } } - } -/* - Animations for blinking the target of a link +/* + Animations for blinking the target of a link It makes it easier to see where the link is pointing to */ @@ -1345,7 +1434,7 @@ dialog { margin-bottom: var(--spacing-300); } -/* +/* If there is parameter right after this one, add some margin. We don't want to do it for all of them, because the last one is followed by a `hr` which already adds spacing around it. @@ -1354,7 +1443,7 @@ dialog { margin-bottom: var(--spacing-300); } -/* +/* .button { padding: .5rem .75rem; color: var(--text-color); @@ -1388,10 +1477,61 @@ dialog { /* Should be extract as an independant .buttons class when reworking the CSS */ display: flex; - gap: .25rem; + gap: 0.25rem; flex-wrap: wrap; justify-content: flex-start; align-items: center; } +} + +summary { + list-style: none; + cursor: pointer; + display: flex; + border-radius: 5px 5px 0 0; + + .fsdocs-api-code { + width: 100%; + padding: 0.5rem; + margin-bottom: 0; + } +} + +details { + &::before { + position: relative; + border-width: 7.8px 7.8px 7.8px 10px; + top: 25px; + left: -20px; + border-color: hsla(0, 0%, 0%, 0) hsla(0, 0%, 0%, 0) hsla(0, 0%, 0%, 0) hsla(0, 0%, 65%, 1); + border-left-color: hsla(0, 0%, 83%, 1); + display: block; + content: ""; + width: 0; + height: 0; + border-style: solid; + } +} -} \ No newline at end of file +details[open] { + summary { + background-color: rgba(55,50,119,.12); + } + + &::before { + border-color: hsla(0, 0%, 0%, 0) hsla(240, 0%, 39%, 1) hsla(0, 0%, 0%, 0) hsla(0, 0%, 0%, 0); + border-width: 11.7px 11.7px 0 14.3px; + left: -39px; + } +} + +details { + /* background-color: #a2bceb; */ + + margin-bottom: 4rem; +} + +details > article { + background-color: #92c5c9; + padding: 1rem; +} diff --git a/rework-prototype/reference/referenceproject-functions.html b/rework-prototype/reference/referenceproject-functions.html index 3952191ee..17e77627a 100644 --- a/rework-prototype/reference/referenceproject-functions.html +++ b/rework-prototype/reference/referenceproject-functions.html @@ -14,7 +14,7 @@ - + Functions (ReferenceProject) | ReferenceProject @@ -26,7 +26,7 @@ - - - + +