├── .config └── dotnet-tools.json ├── .gitignore ├── .paket └── Paket.Restore.targets ├── LICENSE.md ├── README.md ├── WebSharper.Forms.Tests ├── Forms.fs ├── Main.fs ├── RenderUtils.fs ├── RenderWithTemplate.fs ├── RenderWithoutTemplate.fs ├── Web.config ├── WebSharper.Forms.Tests.fsproj ├── index.html └── paket.references ├── WebSharper.Forms.sln ├── WebSharper.Forms ├── Forms.fs ├── Forms.fsi ├── WebSharper.Forms.fsproj └── paket.references ├── build.cmd ├── build.fsx ├── build.sh ├── docs └── Introduction.md ├── global.json ├── ivy.xml ├── nuget └── WebSharper.Forms.paket.template ├── paket.dependencies ├── paket.lock └── tools └── WebSharper.snk /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "paket": { 6 | "version": "8.0.3", 7 | "commands": [ 8 | "paket" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.user 3 | .vs/ 4 | build/ 5 | packages/ 6 | tools/packages/ 7 | build/ 8 | *.Tests/Content/ 9 | **/bin/ 10 | **/obj/ 11 | 12 | bin/ 13 | obj/ 14 | /.fake/ 15 | /paket-files/ 16 | /.vscode/ 17 | websharper.log 18 | -------------------------------------------------------------------------------- /.paket/Paket.Restore.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 8 | 9 | $(MSBuildVersion) 10 | 15.0.0 11 | false 12 | true 13 | 14 | true 15 | $(MSBuildThisFileDirectory) 16 | $(MSBuildThisFileDirectory)..\ 17 | $(PaketRootPath)paket-files\paket.restore.cached 18 | $(PaketRootPath)paket.lock 19 | classic 20 | proj 21 | assembly 22 | native 23 | /Library/Frameworks/Mono.framework/Commands/mono 24 | mono 25 | 26 | 27 | $(PaketRootPath)paket.bootstrapper.exe 28 | $(PaketToolsPath)paket.bootstrapper.exe 29 | $([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\ 30 | 31 | "$(PaketBootStrapperExePath)" 32 | $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)" 33 | 34 | 35 | 36 | 37 | true 38 | true 39 | 40 | 41 | True 42 | 43 | 44 | False 45 | 46 | $(BaseIntermediateOutputPath.TrimEnd('\').TrimEnd('\/')) 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | $(PaketRootPath)paket 56 | $(PaketToolsPath)paket 57 | 58 | 59 | 60 | 61 | 62 | $(PaketRootPath)paket.exe 63 | $(PaketToolsPath)paket.exe 64 | 65 | 66 | 67 | 68 | 69 | <_DotnetToolsJson Condition="Exists('$(PaketRootPath)/.config/dotnet-tools.json')">$([System.IO.File]::ReadAllText("$(PaketRootPath)/.config/dotnet-tools.json")) 70 | <_ConfigContainsPaket Condition=" '$(_DotnetToolsJson)' != ''">$(_DotnetToolsJson.Contains('"paket"')) 71 | <_ConfigContainsPaket Condition=" '$(_ConfigContainsPaket)' == ''">false 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | <_PaketCommand>dotnet paket 83 | 84 | 85 | 86 | 87 | 88 | $(PaketToolsPath)paket 89 | $(PaketBootStrapperExeDir)paket 90 | 91 | 92 | paket 93 | 94 | 95 | 96 | 97 | <_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)")) 98 | <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(_PaketExeExtension)' == '.dll' ">dotnet "$(PaketExePath)" 99 | <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(OS)' != 'Windows_NT' AND '$(_PaketExeExtension)' == '.exe' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" 100 | <_PaketCommand Condition=" '$(_PaketCommand)' == '' ">"$(PaketExePath)" 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | true 122 | $(NoWarn);NU1603;NU1604;NU1605;NU1608 123 | false 124 | true 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)')) 134 | 135 | 136 | 137 | 138 | 139 | 141 | $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[0].Replace(`"`, ``).Replace(` `, ``)) 142 | $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[1].Replace(`"`, ``).Replace(` `, ``)) 143 | 144 | 145 | 146 | 147 | %(PaketRestoreCachedKeyValue.Value) 148 | %(PaketRestoreCachedKeyValue.Value) 149 | 150 | 151 | 152 | 153 | true 154 | false 155 | true 156 | 157 | 158 | 162 | 163 | true 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | $(PaketIntermediateOutputPath)\$(MSBuildProjectFile).paket.references.cached 183 | 184 | $(MSBuildProjectFullPath).paket.references 185 | 186 | $(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references 187 | 188 | $(MSBuildProjectDirectory)\paket.references 189 | 190 | false 191 | true 192 | true 193 | references-file-or-cache-not-found 194 | 195 | 196 | 197 | 198 | $([System.IO.File]::ReadAllText('$(PaketReferencesCachedFilePath)')) 199 | $([System.IO.File]::ReadAllText('$(PaketOriginalReferencesFilePath)')) 200 | references-file 201 | false 202 | 203 | 204 | 205 | 206 | false 207 | 208 | 209 | 210 | 211 | true 212 | target-framework '$(TargetFramework)' or '$(TargetFrameworks)' files @(PaketResolvedFilePaths) 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | false 224 | true 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length) 236 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0]) 237 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1]) 238 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4]) 239 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5]) 240 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[6]) 241 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[7]) 242 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[8]) 243 | 244 | 245 | %(PaketReferencesFileLinesInfo.PackageVersion) 246 | All 247 | runtime 248 | $(ExcludeAssets);contentFiles 249 | $(ExcludeAssets);build;buildMultitargeting;buildTransitive 250 | %(PaketReferencesFileLinesInfo.Aliases) 251 | true 252 | true 253 | 254 | 255 | 256 | 257 | 258 | $(PaketIntermediateOutputPath)/$(MSBuildProjectFile).paket.clitools 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[0]) 268 | $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[1]) 269 | 270 | 271 | %(PaketCliToolFileLinesInfo.PackageVersion) 272 | 273 | 274 | 275 | 279 | 280 | 281 | 282 | 283 | 284 | false 285 | 286 | 287 | 288 | 289 | 290 | <_NuspecFilesNewLocation Include="$(PaketIntermediateOutputPath)\$(Configuration)\*.nuspec"/> 291 | 292 | 293 | 294 | 295 | 296 | $(MSBuildProjectDirectory)/$(MSBuildProjectFile) 297 | true 298 | false 299 | true 300 | false 301 | true 302 | false 303 | true 304 | false 305 | true 306 | false 307 | true 308 | $(PaketIntermediateOutputPath)\$(Configuration) 309 | $(PaketIntermediateOutputPath) 310 | 311 | 312 | 313 | <_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.$(PackageVersion.Split(`+`)[0]).nuspec"/> 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 373 | 374 | 423 | 424 | 469 | 470 | 514 | 515 | 558 | 559 | 560 | 561 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Apache License 2 | 3 | Version 2.0, January 2004 4 | 5 | http://www.apache.org/licenses/ 6 | 7 | ## TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | ## END OF TERMS AND CONDITIONS 179 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebSharper.Forms 2 | 3 | Forms are a functional, composable, and type-safe form abstraction for building reactive user interfaces in WebSharper, 4 | similar to Formlets but with fine control over the structure of the output. 5 | 6 | A sample Form: 7 | 8 | ```fsharp 9 | let LoginForm () = 10 | Form.Return (fun user pass -> user, pass) 11 | <*> (Form.Yield "" 12 | |> Validation.IsNotEmpty "Must enter a username") 13 | <*> (Form.Yield "" 14 | |> Validation.IsNotEmpty "Must enter a password") 15 | |> Form.WithSubmit 16 | |> Form.Run (fun (u, p) -> 17 | JS.Alert("Welcome, " + u + "!") 18 | ) 19 | |> Form.Render (fun user pass submit -> 20 | div [] [ 21 | div [] [label [] [text "Username: "]; Doc.Input [] user] 22 | div [] [label [] [text "Password: "]; Doc.PasswordBox [] pass] 23 | Doc.Button "Log in" [] submit.Trigger 24 | div [] [ 25 | Doc.ShowErrors submit.View (fun errors -> 26 | errors 27 | |> Seq.map (fun m -> p [] [text m.Text]) 28 | |> Doc.Concat) 29 | ] 30 | ] 31 | ) 32 | ``` 33 | 34 | * [Tutorial][intro] - check here first to learn about Forms 35 | * Demos 36 | * The [Pets example](http://try.websharper.com/snippet/Dark_Clark/0000Cy) from the tutorial on [Try WebSharper](https://try.websharper.com) 37 | * The main [test project](https://github.com/dotnet-websharper/forms/tree/master/WebSharper.Forms.Tests) in this repository - check here for inline HTML and *templated* forms 38 | * [License][license] (Apache v2) 39 | * GitHub - [sources][gh], [tracker][issues] 40 | * Community 41 | * [WebSharper on Gitter][gitter] - technical chat 42 | * [WebSharper Forums][wsforums] - Got a question? 43 | * [#websharper on freenode][chat] 44 | * [Need support?][contact] - IntelliFactory 45 | 46 | ## Wait, formlets and piglets? - I am confused 47 | 48 | `WebSharper.Forms` (this project, aka. **reactive** piglets or `WebSharper.UI.Piglets`) is a reactive implementation of the original [WebSharper.Piglets](https://github.com/dotnet-websharper/piglets) library, using [WebSharper.UI](https://github.com/dotnet-websharper/ui), [WebSharper](https://websharper.com)'s main reactive library. 49 | 50 | Piglets are a novel UI abstraction pioneered by WebSharper, and are first documented in this IntelliFactory research paper: 51 | 52 | > Loic Denuziere, Ernesto Rodriguez, Adam Granicz. **Piglets to the Rescue: Declarative User Interface Specification with Pluggable View Models**. In Symposium on Implementation and Application of Functional Languages (IFL), Nijmegen, The Netherlands, 2013. [ACM](https://dl.acm.org/citation.cfm?id=2620689), **[PDF](http://www.cs.ru.nl/P.Achten/IFL2013/symposium_proceedings_IFL2013/ifl2013_submission_29.pdf)**. 53 | 54 | Formlets have similarly been published in academia, among others in [this 2007 draft paper](https://www.cl.cam.ac.uk/~jdy22/papers/idioms-guide.pdf) by Ezra Cooper, Sam Lindley, Philip Wadler, and Jeremy Yallop at the University of Edinburgh. 55 | 56 | Formlets have first been ported to F# for WebSharper in 2009, enhanced for dependent flowlets and published in this IntelliFactory research paper: 57 | 58 | > Joel Bjornson, Anton Tayanovskyy, Adam Granicz. **Composing Reactive GUIs in F# Using WebSharper**. In Symposium on Implementation and Application of Functional Languages (IFL), Alphen aan den Rijn, The Netherlands, 2010. pp. 203-216. [Springer](https://link.springer.com/chapter/10.1007/978-3-642-24276-2_13) 59 | 60 | This early formlet library is available as [WebSharper.Formlets](https://github.com/dotnet-websharper/formlets), and a `WebSharper.UI`-based re-implementation is available as [WebSharper.UI.Formlets](https://github.com/dotnet-websharper/ui.formlets). 61 | 62 | Given that reactive forms/piglets are more flexible than formlets, we recommend that you use `WebSharper.Forms` (this project) in your applications. 63 | 64 | 65 | [chat]: http://webchat.freenode.net/?channels=#websharper 66 | [contact]: http://intellifactory.com/contact 67 | [wsforums]: https://forums.websharper.com/ 68 | [fsharp]: http://fsharp.org 69 | [gh]: http://github.com/intellifactory/websharper.forms 70 | [gitter]: https://gitter.im/intellifactory/websharper 71 | [intro]: http://github.com/intellifactory/websharper.forms/blob/master/docs/Introduction.md 72 | [issues]: http://github.com/intellifactory/websharper.forms/issues 73 | [license]: http://github.com/intellifactory/websharper.forms/blob/master/LICENSE.md 74 | [nuget]: http://nuget.org 75 | -------------------------------------------------------------------------------- /WebSharper.Forms.Tests/Forms.fs: -------------------------------------------------------------------------------- 1 | // $begin{copyright} 2 | // 3 | // This file is part of WebSharper 4 | // 5 | // Copyright (c) 2008-2018 IntelliFactory 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you 8 | // may not use this file except in compliance with the License. You may 9 | // obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 16 | // implied. See the License for the specific language governing 17 | // permissions and limitations under the License. 18 | // 19 | // $end{copyright} 20 | namespace WebSharper.Forms.Tests 21 | 22 | open WebSharper 23 | open WebSharper.JavaScript 24 | open WebSharper.UI 25 | open WebSharper.Forms 26 | 27 | [] 28 | module Forms = 29 | 30 | type Contact = Email of string | PhoneNumber of string 31 | 32 | let AddItemForm() = 33 | Form.Return (fun x y -> (x, y)) 34 | <*> (Form.Yield "John Doe" 35 | |> Validation.IsNotEmpty "Please enter a name.") 36 | <*> Form.Do { 37 | let! isEmail = Form.Yield true 38 | if isEmail then 39 | return! Form.Yield "john@doe.com" 40 | |> Validation.IsMatch @"^.+@.+\..+$" "Please enter a valid email address." 41 | |> Form.Map Email 42 | else 43 | return! Form.Yield "01 234 5678" 44 | |> Validation.Is (fun s -> s.Length >= 6) "Please enter a valid phone number." 45 | |> Form.Map PhoneNumber 46 | } 47 | |> Form.WithSubmit 48 | 49 | let FullForm() = 50 | Form.ManyForm Seq.empty (AddItemForm()) Form.Yield 51 | |> Validation.Is (not << Seq.isEmpty) "Please enter at least one contact." 52 | |> Form.WithSubmit 53 | -------------------------------------------------------------------------------- /WebSharper.Forms.Tests/Main.fs: -------------------------------------------------------------------------------- 1 | // $begin{copyright} 2 | // 3 | // This file is part of WebSharper 4 | // 5 | // Copyright (c) 2008-2018 IntelliFactory 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you 8 | // may not use this file except in compliance with the License. You may 9 | // obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 16 | // implied. See the License for the specific language governing 17 | // permissions and limitations under the License. 18 | // 19 | // $end{copyright} 20 | namespace WebSharper.Forms.Tests 21 | 22 | open WebSharper 23 | open WebSharper.JavaScript 24 | open WebSharper.UI 25 | open WebSharper.UI.Html 26 | open WebSharper.UI.Client 27 | open WebSharper.Forms 28 | 29 | [] 30 | module Main = 31 | 32 | [] 33 | let Main() = 34 | Doc.Concat [ 35 | h1 [] [text "Rendered with a template:"] 36 | RenderWithTemplate.Render() 37 | hr [] [] 38 | h1 [] [text "Rendered with HTML combinators:"] 39 | RenderWithoutTemplate.Render() 40 | ] 41 | |> Doc.RunAppend JS.Document.Body 42 | -------------------------------------------------------------------------------- /WebSharper.Forms.Tests/RenderUtils.fs: -------------------------------------------------------------------------------- 1 | // $begin{copyright} 2 | // 3 | // This file is part of WebSharper 4 | // 5 | // Copyright (c) 2008-2018 IntelliFactory 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you 8 | // may not use this file except in compliance with the License. You may 9 | // obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 16 | // implied. See the License for the specific language governing 17 | // permissions and limitations under the License. 18 | // 19 | // $end{copyright} 20 | namespace WebSharper.Forms.Tests 21 | 22 | open WebSharper 23 | open WebSharper.JavaScript 24 | open WebSharper.UI 25 | open WebSharper.UI.Html 26 | open WebSharper.UI.Client 27 | open WebSharper.Forms 28 | 29 | [] 30 | module RenderUtils = 31 | 32 | let ShowErrorMessage v = 33 | v |> Doc.BindView (function 34 | | Success _ -> Doc.Empty 35 | | Failure msgs -> 36 | Doc.Concat [ 37 | for msg in msgs do 38 | yield text msg.Text 39 | yield br [] [] :> _ 40 | ] 41 | ) 42 | -------------------------------------------------------------------------------- /WebSharper.Forms.Tests/RenderWithTemplate.fs: -------------------------------------------------------------------------------- 1 | // $begin{copyright} 2 | // 3 | // This file is part of WebSharper 4 | // 5 | // Copyright (c) 2008-2018 IntelliFactory 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you 8 | // may not use this file except in compliance with the License. You may 9 | // obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 16 | // implied. See the License for the specific language governing 17 | // permissions and limitations under the License. 18 | // 19 | // $end{copyright} 20 | namespace WebSharper.Forms.Tests 21 | 22 | open WebSharper 23 | open WebSharper.JavaScript 24 | open WebSharper.UI 25 | open WebSharper.UI.Html 26 | open WebSharper.UI.Client 27 | open WebSharper.Forms 28 | open WebSharper.Forms.Tests.Forms 29 | 30 | #nowarn "58" // indentation 31 | 32 | [] 33 | module RenderWithTemplate = 34 | 35 | type Template = Templating.Template<"index.html"> 36 | 37 | let Render() = 38 | Forms.FullForm() 39 | |> Form.Render (fun items submit -> 40 | Template.Form() 41 | .Items( 42 | items.Render (fun ops rvContact -> 43 | Template.Item() 44 | .Name(rvContact.View |> View.Map fst) 45 | .Contact(rvContact.View |> View.Map (function 46 | | _, Email x -> "email: " + x 47 | | _, PhoneNumber x -> "phone: " + x) 48 | ) 49 | .MoveUp(Attr.SubmitterValidate ops.MoveUp) 50 | .MoveDown(Attr.SubmitterValidate ops.MoveDown) 51 | .Delete(on.click (fun _ _ -> ops.Delete())) 52 | .Doc() 53 | ) 54 | ) 55 | .Adder( 56 | items.RenderAdder(fun rvName depContact submit -> 57 | Template.Adder() 58 | .Name(rvName) 59 | .NameErrors(ShowErrorMessage (submit.View.Through rvName)) 60 | .ContactType( 61 | depContact.RenderPrimary (fun rvContactType -> 62 | Doc.Concat [ 63 | label [] [Doc.Radio [] true rvContactType; text "Email"] 64 | label [] [Doc.Radio [] false rvContactType; text "Phone number"] 65 | ] 66 | ) 67 | ) 68 | .Contact( 69 | depContact.RenderDependent (fun rvContact -> 70 | Template.Contact() 71 | .ContactText(rvContact) 72 | .ContactErrors(ShowErrorMessage (submit.View.Through rvContact)) 73 | .Doc() 74 | ) 75 | ) 76 | .Add(fun _ -> submit.Trigger()) 77 | .Doc() 78 | ) 79 | ) 80 | .Submit(fun _ -> submit.Trigger()) 81 | .SubmitResults([ 82 | submit.View |> View.Map (function 83 | | Success xs -> 84 | Doc.Concat [ 85 | for name, contact in xs -> 86 | let contact = 87 | match contact with 88 | | PhoneNumber n -> "phone: " + n 89 | | Email e -> "email: " + e 90 | Template.SubmitSuccess().Name(name).Contact(contact).Doc() 91 | ] 92 | | Failure msgs -> 93 | Doc.Concat [ 94 | for msg in msgs -> 95 | Template.SubmitError().Message(msg.Text).Doc() 96 | ] 97 | ) 98 | |> Doc.EmbedView 99 | ]) 100 | .Doc() 101 | ) 102 | 103 | -------------------------------------------------------------------------------- /WebSharper.Forms.Tests/RenderWithoutTemplate.fs: -------------------------------------------------------------------------------- 1 | // $begin{copyright} 2 | // 3 | // This file is part of WebSharper 4 | // 5 | // Copyright (c) 2008-2018 IntelliFactory 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you 8 | // may not use this file except in compliance with the License. You may 9 | // obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 16 | // implied. See the License for the specific language governing 17 | // permissions and limitations under the License. 18 | // 19 | // $end{copyright} 20 | namespace WebSharper.Forms.Tests 21 | 22 | open WebSharper 23 | open WebSharper.JavaScript 24 | open WebSharper.UI 25 | open WebSharper.UI.Html 26 | open WebSharper.UI.Client 27 | open WebSharper.Forms 28 | open WebSharper.Forms.Tests.Forms 29 | 30 | [] 31 | module RenderWithoutTemplate = 32 | 33 | let Render() = 34 | Forms.FullForm() 35 | |> Form.Render (fun items submit -> 36 | div [] [ 37 | h2 [] [text "Contacts:"] 38 | table [] [ 39 | thead [] [ 40 | tr [] [ 41 | th [] [text "Name"] 42 | th [] [text "Contact"] 43 | ] 44 | ] 45 | tbody [] [ 46 | items.Render (fun ops x -> 47 | tr [] [ 48 | td [] [textView (x.View |> View.Map fst)] 49 | td [] [textView (x.View |> View.Map (function 50 | | _, Email x -> "email: " + x 51 | | _, PhoneNumber x -> "phone: " + x 52 | ))] 53 | td [] [Doc.ButtonValidate "Move up" [] ops.MoveUp] 54 | td [] [Doc.ButtonValidate "Move down" [] ops.MoveDown] 55 | td [] [button [on.click (fun _ _ -> ops.Delete())] [text "Delete"]] 56 | ] 57 | ) 58 | ] 59 | ] 60 | div [attr.style "border: solid 1px #888; padding: 10px; margin: 20px"] [ 61 | h3 [] [text "Add a new item"] 62 | items.RenderAdder (fun rvName depContact submit -> 63 | div [] [ 64 | p [] [ 65 | Doc.Input [] rvName 66 | ShowErrorMessage (submit.View.Through rvName) 67 | ] 68 | p [] [ 69 | depContact.RenderPrimary (fun rvContactType -> 70 | div [] [ 71 | label [] [Doc.Radio [] true rvContactType; text "Email"] 72 | label [] [Doc.Radio [] false rvContactType; text "Phone number"] 73 | ] 74 | ) 75 | depContact.RenderDependent (fun rvContact -> 76 | Doc.Concat [ 77 | Doc.Input [] rvContact 78 | ShowErrorMessage (submit.View.Through rvContact) 79 | ] 80 | ) 81 | ] 82 | p [] [Doc.Button "Add" [] submit.Trigger] 83 | ] 84 | ) 85 | ] 86 | Doc.Button "Submit" [] submit.Trigger 87 | submit.View |> View.Map (function 88 | | Success contacts -> 89 | div [] ( 90 | contacts |> Seq.map (fun (x, contact) -> 91 | let contact = 92 | match contact with 93 | | Email e -> " (email: " + e + ")" 94 | | PhoneNumber n -> " (phone: " + n + ")" 95 | p [] [text ("You registered a contact: " + string x + contact)] :> Doc 96 | ) 97 | ) 98 | | Failure msgs -> div [attr.style "color:red"] [for msg in msgs -> p [] [text msg.Text] :> _] 99 | ) 100 | |> Doc.EmbedView 101 | ] 102 | ) 103 | -------------------------------------------------------------------------------- /WebSharper.Forms.Tests/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | True 13 | 14 | 15 | 16 | 17 | True 18 | 19 | 20 | 21 | 22 | True 23 | 24 | 25 | 26 | 27 | True 28 | 29 | 30 | 31 | 32 | True 33 | 34 | 35 | 36 | 37 | True 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /WebSharper.Forms.Tests/WebSharper.Forms.Tests.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net50 5 | Bundle 6 | true 7 | true 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /WebSharper.Forms.Tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WebSharper.Forms.Tests 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 |
17 | 18 |
19 |

Contacts:

20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
NameContact
${Name}${Contact}
37 |
38 |

Add a new contact

39 |
40 |

41 | 42 | 43 |

44 |
45 |
46 |
47 | 48 | 49 |
50 |
51 |

52 | 53 |

54 |
55 |
56 |
57 | 58 |
59 |
60 |

61 | You registered a contact: ${Name} (${Contact}) 62 |

63 |

64 | ${Message} 65 |

66 |
67 |
68 | 69 | 70 | -------------------------------------------------------------------------------- /WebSharper.Forms.Tests/paket.references: -------------------------------------------------------------------------------- 1 | group testing 2 | WebSharper 3 | WebSharper.FSharp 4 | WebSharper.UI 5 | WebSharper.AspNetCore 6 | FSharp.Core 7 | -------------------------------------------------------------------------------- /WebSharper.Forms.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7CA7EED6-C0D3-4C7B-A84F-5B07976AE62F}" 7 | ProjectSection(SolutionItems) = preProject 8 | build.fsx = build.fsx 9 | ivy.xml = ivy.xml 10 | LICENSE.md = LICENSE.md 11 | README.md = README.md 12 | EndProjectSection 13 | EndProject 14 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WebSharper.Forms", "WebSharper.Forms\WebSharper.Forms.fsproj", "{AB53BB7F-FBE4-4F4D-A817-7A7F20F2B06F}" 15 | EndProject 16 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "WebSharper.Forms.Tests", "WebSharper.Forms.Tests\WebSharper.Forms.Tests.fsproj", "{87297620-C340-470F-A347-21DFA030C502}" 17 | ProjectSection(ProjectDependencies) = postProject 18 | {AB53BB7F-FBE4-4F4D-A817-7A7F20F2B06F} = {AB53BB7F-FBE4-4F4D-A817-7A7F20F2B06F} 19 | EndProjectSection 20 | EndProject 21 | Global 22 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 23 | Debug|Any CPU = Debug|Any CPU 24 | Release|Any CPU = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {AB53BB7F-FBE4-4F4D-A817-7A7F20F2B06F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {AB53BB7F-FBE4-4F4D-A817-7A7F20F2B06F}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {AB53BB7F-FBE4-4F4D-A817-7A7F20F2B06F}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {AB53BB7F-FBE4-4F4D-A817-7A7F20F2B06F}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {87297620-C340-470F-A347-21DFA030C502}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {87297620-C340-470F-A347-21DFA030C502}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {87297620-C340-470F-A347-21DFA030C502}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {87297620-C340-470F-A347-21DFA030C502}.Release|Any CPU.Build.0 = Release|Any CPU 35 | EndGlobalSection 36 | GlobalSection(SolutionProperties) = preSolution 37 | HideSolutionNode = FALSE 38 | EndGlobalSection 39 | EndGlobal 40 | -------------------------------------------------------------------------------- /WebSharper.Forms/Forms.fs: -------------------------------------------------------------------------------- 1 | // $begin{copyright} 2 | // 3 | // This file is part of WebSharper 4 | // 5 | // Copyright (c) 2008-2018 IntelliFactory 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you 8 | // may not use this file except in compliance with the License. You may 9 | // obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 16 | // implied. See the License for the specific language governing 17 | // permissions and limitations under the License. 18 | // 19 | // $end{copyright} 20 | namespace WebSharper.Forms 21 | 22 | open System.Runtime.CompilerServices 23 | open WebSharper 24 | open WebSharper.JavaScript 25 | open WebSharper.UI 26 | open WebSharper.UI.Client 27 | open WebSharper.UI.Notation 28 | 29 | [] 30 | type ErrorMessage (id: string, message: string) = 31 | 32 | [] 33 | member this.Id = id 34 | 35 | [] 36 | member this.Text = message 37 | 38 | [] 39 | module Fresh = 40 | 41 | let lastId = ref 0 42 | 43 | let Id() = 44 | incr lastId 45 | "Form" + string !lastId 46 | 47 | [] 48 | type Result<'T> = 49 | | Success of 'T 50 | | Failure of list 51 | 52 | [] 53 | type Result = 54 | 55 | static member IsSuccess (r: Result<'T>) = 56 | match r with 57 | | Success _ -> true 58 | | Failure _ -> false 59 | 60 | static member IsFailure (r: Result<'T>) = 61 | match r with 62 | | Success _ -> false 63 | | Failure _ -> true 64 | 65 | static member Map (f: 'T -> 'U) (r: Result<'T>) = 66 | match r with 67 | | Success x -> Success (f x) 68 | | Failure m -> Failure m 69 | 70 | static member Apply (rf: Result<'T -> 'U>) (rx: Result<'T>) = 71 | match rf with 72 | | Failure mf -> 73 | match rx with 74 | | Failure mx -> Failure (mf @ mx) 75 | | Success _ -> Failure mf 76 | | Success f -> 77 | match rx with 78 | | Failure mx -> Failure mx 79 | | Success x -> Success (f x) 80 | 81 | static member ApJoin (rf: Result<'T -> 'U>) (rx: Result>) = 82 | match rf with 83 | | Failure mf -> 84 | match rx with 85 | | Failure mx -> Failure (mf @ mx) 86 | | Success _ -> Failure mf 87 | | Success f -> 88 | match rx with 89 | | Failure mx 90 | | Success (Failure mx) -> Failure mx 91 | | Success (Success x) -> Success (f x) 92 | 93 | static member Bind (f: 'T -> Result<'U>) (r: Result<'T>) : Result<'U> = 94 | match r with 95 | | Failure m -> Failure m 96 | | Success x -> f x 97 | 98 | static member Append (app: 'T -> 'T -> 'T) (r1: Result<'T>) (r2: Result<'T>) : Result<'T> = 99 | match r1 with 100 | | Failure m1 -> 101 | match r2 with 102 | | Failure m2 -> Failure (m1 @ m2) 103 | | Success _ -> r1 104 | | Success x1 -> 105 | match r2 with 106 | | Failure _ -> r2 107 | | Success x2 -> Success (app x1 x2) 108 | 109 | static member FailWith (errorMessage, ?id) = 110 | let id = match id with Some id -> id | None -> Fresh.Id() 111 | Failure [ErrorMessage(id, errorMessage)] 112 | 113 | [] 114 | type Form<'T, 'R> = 115 | { 116 | id : string 117 | view : View> 118 | render : 'R 119 | } 120 | 121 | [] 122 | member this.Id = this.id 123 | [] 124 | member this.View = this.view 125 | [] 126 | member this.Render = this.render 127 | 128 | type ErrorMessage with 129 | 130 | [] 131 | static member Create (id: string, text) = 132 | new ErrorMessage(id, text) 133 | 134 | [] 135 | static member Create (p: Form<_, _>, text) = 136 | new ErrorMessage(p.id, text) 137 | 138 | [] 139 | module Utils = 140 | 141 | let memoize f = 142 | let d = System.Collections.Generic.Dictionary() 143 | fun x -> 144 | if d.ContainsKey x then 145 | d.[x] 146 | else 147 | let y = f x 148 | d.[x] <- y 149 | y 150 | 151 | 152 | [] 153 | module Form = 154 | 155 | [] 156 | type Dependent<'TResult, 'U, 'W> 157 | ( 158 | renderPrimary: 'U -> Doc, 159 | pOut: View Doc>>> 160 | ) = 161 | 162 | let out = 163 | pOut.Bind (function 164 | | Success p -> p.view 165 | | Failure m -> View.Const (Failure m)) 166 | 167 | [] 168 | member this.View : View> = out 169 | 170 | [] 171 | member this.RenderPrimary (f: 'U) : Doc = 172 | renderPrimary f 173 | 174 | member this.RenderDependent (f: 'W) : Doc = 175 | pOut |> Doc.BindView (function 176 | | Success p -> p.render f 177 | | Failure _ -> Doc.Empty) 178 | 179 | module Dependent = 180 | let Make primary dependent = 181 | let dependent = memoize (fun x -> 182 | let p = dependent x 183 | { view = p.view; id = p.id; render = fun x -> p.render x :> Doc }) 184 | let pOut = primary.view.Map (Result.Map dependent) 185 | Dependent((fun x -> primary.render x :> Doc), pOut) 186 | 187 | 188 | [] 189 | module Many = 190 | 191 | type ItemOperations(delete: unit -> unit, moveUp: Submitter>, moveDown: Submitter>) = 192 | [] 193 | member this.Delete() = delete() 194 | [] 195 | member this.MoveUp = moveUp 196 | [] 197 | member this.MoveDown = moveDown 198 | 199 | type System.Collections.Generic.List<'T> with 200 | member this.Swap(i, j) = 201 | let tmp = this.[i] 202 | this.[i] <- this.[j] 203 | this.[j] <- tmp 204 | 205 | module Fresh = 206 | 207 | let Int = 208 | let x = ref 0 209 | fun () -> 210 | incr x 211 | !x 212 | 213 | type Collection<'T, 'V, 'W, 'Y, 'Z when 'W :> Doc and 'Z :> Doc> (p : 'T -> Form<'T, 'V -> 'W>, inits: seq<'T>, adder : Form<'T, 'Y -> 'Z>) = 214 | let arr = ResizeArray() 215 | let var = Var.Create arr 216 | let mk (x: 'T) = 217 | let ident = Fresh.Int() 218 | let getThisIndexIn = Seq.findIndex (fun (_, _, j) -> ident = j) 219 | let vIndex = var.View |> View.Map getThisIndexIn 220 | let delete() = 221 | let k = getThisIndexIn arr 222 | arr.RemoveAt k 223 | Var.Update var id 224 | let sMoveUp = 225 | let inp = vIndex |> View.Map (fun i -> 226 | if i = 0 then Failure [] else Success true 227 | ) 228 | Submitter.Create inp (if arr.Count = 0 then Failure [] else Success false) 229 | let vMoveUp = 230 | sMoveUp.View |> View.Map (function 231 | | Success true -> 232 | let i = getThisIndexIn arr 233 | arr.Swap(i, i - 1) 234 | Var.Update var id 235 | | _ -> () 236 | ) 237 | let sMoveDown = 238 | let inp = vIndex |> View.Map (fun i -> 239 | if i = arr.Count - 1 then Failure [] else Success true 240 | ) 241 | Submitter.Create inp (Failure []) 242 | let vMoveDown = 243 | sMoveDown.View |> View.Map (function 244 | | Success true -> 245 | let i = getThisIndexIn arr 246 | arr.Swap(i, i + 1) 247 | Var.Update var id 248 | | _ -> () 249 | ) 250 | let p = p x 251 | let v = View.Map2 (fun x () -> x) p.view (View.Map2 (fun () () -> ()) vMoveUp vMoveDown) 252 | let p = { p with view = v } 253 | p, ItemOperations(delete, sMoveUp, sMoveDown), ident 254 | do Seq.iter (mk >> arr.Add) inits 255 | 256 | let fst3 (x, _, _) = x 257 | let changesView = 258 | var.View 259 | |> View.Bind (fun arr -> 260 | arr.ToArray() 261 | |> Array.MapTreeReduce 262 | (fun x -> 263 | (fst3 x).view |> View.Map (fun _ -> Seq.singleton x)) 264 | (View.Const Seq.empty) 265 | (View.Map2 Seq.append) 266 | ) 267 | 268 | let add x = 269 | arr.Add(mk x) 270 | Var.Update var id 271 | 272 | let adderView x = 273 | match x with 274 | | Failure _ -> () 275 | | Success x -> add x 276 | Doc.Empty 277 | 278 | let out = 279 | var.View 280 | |> View.Bind (fun s -> 281 | s.ToArray() 282 | |> Array.MapTreeReduce 283 | (fun (p, _, _) -> p.view |> View.Map (Result.Map Seq.singleton)) 284 | (View.Const (Success Seq.empty)) 285 | (View.Map2 (Result.Append Seq.append)) 286 | ) 287 | 288 | [] 289 | member this.View = out 290 | 291 | member this.Render (f: ItemOperations -> 'V) : Doc = 292 | changesView 293 | |> Doc.BindSeqCachedBy (fun (_, _, ident) -> ident) (fun (p, ops, _) -> 294 | p.render (f ops) :> Doc 295 | ) 296 | 297 | [] 298 | member this.Add (x: 'T) = 299 | add x 300 | 301 | member this.RenderAdder f = 302 | adder.render f 303 | |> Doc.Append (adder.view |> View.Map adderView |> Doc.EmbedView) 304 | 305 | [] 306 | type CollectionWithDefault<'T, 'V, 'W when 'W :> Doc> (p, inits, pInit, ``default``) = 307 | inherit Collection<'T, 'V, 'W, 'V, 'W> (p, inits, pInit) 308 | 309 | member this.Add() = this.Add ``default`` 310 | 311 | [] 312 | let (>>^) v f = fun g -> g (v f) 313 | 314 | let Create view (renderBuilder: _ -> _) = 315 | { 316 | id = Fresh.Id() 317 | view = view 318 | render = renderBuilder 319 | } 320 | 321 | let Render renderFunction p = 322 | p.render renderFunction 323 | |> Doc.Append ( 324 | p.view 325 | |> View.Map (fun _ -> Doc.Empty) 326 | |> Doc.EmbedView 327 | ) 328 | 329 | [] 330 | let RenderMany (c: Many.Collection<_,_,_,_,_>) f = 331 | c.Render f 332 | 333 | [] 334 | let RenderManyAdder (c: Many.Collection<_,_,_,_,_>) f = 335 | c.RenderAdder f 336 | 337 | [] 338 | let RenderPrimary (d: Dependent<_,_,_>) f = 339 | d.RenderPrimary f 340 | 341 | [] 342 | let RenderDependent (d: Dependent<_,_,_>) f = 343 | d.RenderDependent f 344 | 345 | [] 346 | let GetView (p: Form<_, _ -> _>) = 347 | p.view 348 | 349 | let Return value = 350 | { 351 | id = Fresh.Id() 352 | view = View.Const (Success value) 353 | render = id 354 | } 355 | 356 | let ReturnFailure () = 357 | { 358 | id = Fresh.Id() 359 | view = View.Const (Failure []) 360 | render = id 361 | } 362 | 363 | let YieldVar (var: Var<_>) = 364 | { 365 | id = var.Id 366 | view = var.View |> View.Map Success 367 | render = fun r -> r var 368 | } 369 | 370 | let Yield init = 371 | YieldVar (Var.Create init) 372 | 373 | let YieldFailure () = 374 | let var = Var.Create JS.Undefined<_> :> Var<_> 375 | let view = var.View 376 | { 377 | id = var.Id 378 | view = View.SnapshotOn (Failure []) view (view |> View.Map Success) 379 | render = fun r -> r var 380 | } 381 | 382 | let YieldOption init noneValue = 383 | let var = Var.Create (defaultArg init noneValue) :> Var<_> 384 | { 385 | id = var.Id 386 | view = var.View |> View.Map (fun x -> 387 | Success (if x = noneValue then None else Some x)) 388 | render = fun r -> r var 389 | } 390 | 391 | let Apply pf px = 392 | { 393 | id = Fresh.Id() 394 | view = View.Map2 Result.Apply pf.view px.view 395 | render = pf.render >> px.render 396 | } 397 | 398 | let ApJoin pf px = 399 | { 400 | id = Fresh.Id() 401 | view = View.Map2 Result.ApJoin pf.view px.view 402 | render = pf.render >> px.render 403 | } 404 | 405 | let WithSubmit p = 406 | let submitter = Submitter.Create p.view (Failure []) 407 | { 408 | id = Fresh.Id() 409 | view = submitter.View 410 | render = fun r -> p.render r submitter 411 | } 412 | 413 | let TransmitView p = 414 | { 415 | id = p.id 416 | view = p.view 417 | render = fun x -> p.render x p.view 418 | } 419 | 420 | let TransmitViewMapResult f p = 421 | { 422 | id = p.id 423 | view = p.view 424 | render = fun x -> p.render x (View.Map f p.view) 425 | } 426 | 427 | let TransmitViewMap f p = 428 | TransmitViewMapResult (Result.Map f) p 429 | 430 | let MapResult f p : Form<_, _ -> _> = 431 | { 432 | id = p.id 433 | view = View.Map f p.view 434 | render = p.render 435 | } 436 | 437 | let MapToResult f p = 438 | MapResult (Result.Bind f) p 439 | 440 | let Map f p = 441 | MapResult (Result.Map f) p 442 | 443 | let MapAsyncResult f p : Form<_, _ -> _> = 444 | { 445 | id = p.id 446 | view = View.MapAsync f p.view 447 | render = p.render 448 | } 449 | 450 | let MapToAsyncResult f p = 451 | let f x = 452 | match x with 453 | | Success x -> async { return! f x } 454 | | Failure m -> async { return Failure m } 455 | MapAsyncResult f p 456 | 457 | let MapAsync f p = 458 | let f x = 459 | match x with 460 | | Success x -> async { let! y = f x in return Success y } 461 | | Failure m -> async { return Failure m } 462 | MapAsyncResult f p 463 | 464 | let MapRenderArgs f p = 465 | { 466 | id = p.id 467 | view = p.view 468 | render = fun g -> g (p.render f) 469 | } 470 | 471 | let FlushErrors p = 472 | MapResult (function Failure _ -> Failure [] | x -> x) p 473 | 474 | let Run f p = 475 | Map (fun x -> f x; x) p 476 | 477 | let RunResult f p = 478 | MapResult (fun x -> f x; x) p 479 | 480 | [] 481 | let ManyForm init addForm itemForm = 482 | let m = Many.Collection(itemForm, init, addForm) 483 | { 484 | id = Fresh.Id() 485 | view = m.View 486 | render = fun f -> f m 487 | } 488 | 489 | [] 490 | let Many init addValue itemForm = 491 | let pInit = itemForm addValue 492 | let m = Many.CollectionWithDefault(itemForm, init, pInit, addValue) 493 | { 494 | id = Fresh.Id() 495 | view = m.View 496 | render = fun f -> f m 497 | } 498 | 499 | let Dependent primary dependent = 500 | let d = Dependent.Make primary dependent 501 | { 502 | id = Fresh.Id() 503 | view = d.View 504 | render = fun f -> f d 505 | } 506 | 507 | type Builder = 508 | | Do 509 | 510 | [] 511 | member this.Bind(input, output) = Dependent input output 512 | 513 | [] 514 | member this.Return x = Return x 515 | 516 | [] 517 | member this.ReturnFrom (p: Form<_, _ -> _>) = p 518 | 519 | [] 520 | member this.Yield init = Yield init 521 | 522 | [] 523 | member this.YieldFrom (p: Form<_, _ -> _>) = p 524 | 525 | [] 526 | member this.Zero() = ReturnFailure() 527 | 528 | [] 529 | module Validation = 530 | 531 | let Is pred msg p = 532 | p |> Form.MapResult (fun res -> 533 | match res with 534 | | Success x -> if pred x then res else Failure [ErrorMessage(p.id, msg)] 535 | | Failure _ -> res 536 | ) 537 | 538 | let IsNotEmpty msg p = 539 | Is (fun x -> x <> "") msg p 540 | 541 | let IsMatch (regexp: string) msg p = 542 | Is (RegExp(regexp).Test) msg p 543 | 544 | let MapValidCheckedInput msg p = 545 | p |> Form.MapResult (fun res -> 546 | match res with 547 | | Success (CheckedInput.Valid (x, _)) -> Success x 548 | | Success _ -> Failure [ErrorMessage.Create(p, msg)] 549 | | Failure msgs -> Failure msgs 550 | ) 551 | 552 | [] 553 | [] 554 | module Pervasives = 555 | 556 | let (<*>) pf px = 557 | Form.Apply pf px 558 | 559 | let (<*?>) pf px = 560 | Form.ApJoin pf px 561 | 562 | [] 563 | module Attr = 564 | 565 | open WebSharper.UI.Html 566 | open WebSharper.UI.Client 567 | 568 | let SubmitterValidate (submitter: Submitter<_>) = 569 | Attr.Append 570 | (on.click (fun _ _ -> submitter.Trigger())) 571 | (attr.disabledDynPred (View.Const "disabled") 572 | (submitter.Input |> View.Map Result.IsFailure)) 573 | 574 | [] 575 | module Doc = 576 | 577 | open WebSharper.UI.Html 578 | open WebSharper.UI.Client 579 | 580 | let ButtonValidate caption attrs (submitter: Submitter<_>) = 581 | Elt.button (Seq.append [|Attr.SubmitterValidate submitter|] attrs) [text caption] 582 | 583 | let ShowErrors (v: View>) (f: list -> Doc) = 584 | v.Doc(function 585 | | Success _ -> Doc.Empty 586 | | Failure msgs -> f msgs 587 | ) 588 | 589 | let ShowSuccess (v: View>) (f: 'T -> Doc) = 590 | v.Doc(function 591 | | Success x -> f x 592 | | Failure msgs -> Doc.Empty 593 | ) 594 | 595 | [] 596 | type View = 597 | 598 | [] 599 | static member Through (input: View>, v: Var<'U>) : View> = 600 | input |> View.Map (fun x -> 601 | match x with 602 | | Success _ -> x 603 | | Failure msgs -> Failure (msgs |> List.filter (fun m -> m.Id = v.Id)) 604 | ) 605 | 606 | [] 607 | static member Through (input: View>, p: Form<'U, 'R>) : View> = 608 | input |> View.Map (fun x -> 609 | match x with 610 | | Success _ -> x 611 | | Failure msgs -> Failure (msgs |> List.filter (fun m -> m.Id = p.id)) 612 | ) 613 | 614 | [] 615 | static member ShowErrors (this: View>, f: list -> Doc) : Doc = 616 | Doc.ShowErrors this f 617 | 618 | [] 619 | static member ShowSuccess (this: View>, f: 'T -> Doc) : Doc = 620 | Doc.ShowSuccess this f 621 | -------------------------------------------------------------------------------- /WebSharper.Forms/Forms.fsi: -------------------------------------------------------------------------------- 1 | // $begin{copyright} 2 | // 3 | // This file is part of WebSharper 4 | // 5 | // Copyright (c) 2008-2018 IntelliFactory 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); you 8 | // may not use this file except in compliance with the License. You may 9 | // obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 16 | // implied. See the License for the specific language governing 17 | // permissions and limitations under the License. 18 | // 19 | // $end{copyright} 20 | namespace WebSharper.Forms 21 | 22 | open System.Runtime.CompilerServices 23 | open WebSharper 24 | open WebSharper.UI 25 | open WebSharper.UI.Client 26 | 27 | [] 28 | type ErrorMessage = 29 | member Id: string 30 | member Text: string 31 | static member Create : id: string * text: string -> ErrorMessage 32 | static member Create : Form<'T, 'R> * text: string -> ErrorMessage 33 | 34 | and Result<'T> = 35 | | Success of 'T 36 | | Failure of list 37 | 38 | and [] Form<'T, 'R> = 39 | member Id : string 40 | member View : View> 41 | member Render : 'R 42 | 43 | [] 44 | type Result = 45 | 46 | /// Check whether a result is successful. 47 | static member IsSuccess 48 | : Result<'T> 49 | -> bool 50 | 51 | /// Check whether a result is failing. 52 | static member IsFailure 53 | : Result<'T> 54 | -> bool 55 | 56 | /// Pass a result through a function if it is successful. 57 | static member Map 58 | : f: ('T -> 'U) 59 | -> r: Result<'T> 60 | -> Result<'U> 61 | 62 | /// Apply a function result to a value result if both are successful. 63 | static member Apply 64 | : rf: Result<'T -> 'U> 65 | -> rx: Result<'T> 66 | -> Result<'U> 67 | 68 | /// Pass a result through a function if it is successful. 69 | static member Bind 70 | : f: ('T -> Result<'U>) 71 | -> r: Result<'T> 72 | -> Result<'U> 73 | 74 | /// Create a failing result with a single error message. 75 | static member FailWith 76 | : errorMessage: string 77 | * ?id: string 78 | -> Result<'T> 79 | 80 | 81 | /// Form constructors and combinators. 82 | module Form = 83 | 84 | /// Operations related to Forms of collections. 85 | module Many = 86 | 87 | /// Operations applicable to an item in a Form of collections. 88 | [] 89 | type ItemOperations = 90 | 91 | /// Delete the current item from the collection. 92 | member Delete : unit -> unit 93 | 94 | /// Move the current item up one step in the collection. 95 | member MoveUp : Submitter> 96 | 97 | /// Move the current item down one step in the collection. 98 | member MoveDown : Submitter> 99 | 100 | /// Operations applicable to a Form of collections. 101 | [] 102 | type Collection<'T, 'V, 'W, 'Y, 'Z when 'W :> Doc and 'Z :> Doc> = 103 | 104 | /// A view on the resulting collection. 105 | member View : View>> 106 | 107 | /// Render the item collection inside this Form 108 | /// with the provided rendering function. 109 | member Render : (ItemOperations -> 'V) -> Doc 110 | 111 | /// Stream where new items for the collection are written. 112 | member Add : 'T -> unit 113 | 114 | /// Render the Form that inserts new items into the collection. 115 | member RenderAdder : 'Y -> Doc 116 | 117 | /// Operations applicable to a Form of collections 118 | /// with a provided default new value to insert. 119 | [] 120 | type CollectionWithDefault<'T, 'V, 'W when 'W :> Doc> = 121 | inherit Collection<'T,'V,'W,'V,'W> 122 | 123 | /// Add an item to the collection set to the default value. 124 | [] 125 | member Add : unit -> unit 126 | 127 | /// Operations applicable to a dependent Form. 128 | [] 129 | type Dependent<'TResult, 'U, 'W> = 130 | 131 | /// A view on the result of the dependent Form. 132 | member View : View> 133 | 134 | /// Render the primary part of a dependent Form. 135 | member RenderPrimary : 'U -> Doc 136 | 137 | /// Render the dependent part of a dependent Form. 138 | member RenderDependent : 'W -> Doc 139 | 140 | /// Create a Form from a view and a render builder. 141 | val Create 142 | : view: View> 143 | -> renderBuilder: ('R -> 'D) 144 | -> Form<'T, 'R -> 'D> 145 | 146 | /// Render a Form with a render function. 147 | val Render 148 | : renderFunction: 'R 149 | -> Form<'T, 'R -> #Doc> 150 | -> Doc 151 | 152 | /// Render the items of a Collection with the provided rendering function. 153 | val RenderMany 154 | : Many.Collection<'T, 'V, 'W, 'Y, 'Z> 155 | -> (Many.ItemOperations -> 'V) 156 | -> Doc 157 | when 'W :> Doc and 'Z :> Doc 158 | 159 | /// Render the Form that inserts new items into a Collection. 160 | val RenderManyAdder 161 | : Many.Collection<'T, 'V, 'W, 'Y, 'Z> 162 | -> 'Y 163 | -> Doc 164 | when 'W :> Doc and 'Z :> Doc 165 | 166 | /// Render the primary part of a dependent Form. 167 | val RenderPrimary 168 | : Dependent<'TResult, 'U, 'W> 169 | -> 'U 170 | -> Doc 171 | 172 | /// Render the dependent part of a dependent Form. 173 | val RenderDependent 174 | : Dependent<'TResult, 'U, 'W> 175 | -> 'W 176 | -> Doc 177 | 178 | /// Get the view of a Form. 179 | val GetView 180 | : Form<'T, 'R -> 'D> 181 | -> View> 182 | 183 | /// Create a Form that always returns the same successful value. 184 | val Return 185 | : value: 'T 186 | -> Form<'T, 'D -> 'D> 187 | 188 | /// Create a Form that always fails. 189 | val ReturnFailure 190 | : unit 191 | -> Form<'T, 'D -> 'D> 192 | 193 | /// Create a Form that returns a reactive value, 194 | /// initialized to a successful value `init`. 195 | val Yield 196 | : init: 'T 197 | -> Form<'T, (Var<'T> -> 'D) -> 'D> 198 | 199 | /// Create a Form that returns a reactive value. 200 | val YieldVar 201 | : Var<'T> 202 | -> Form<'T, (Var<'T> -> 'D) -> 'D> 203 | 204 | /// Create a Form that returns a reactive value, initialized to failure. 205 | val YieldFailure 206 | : unit 207 | -> Form<'T, (Var<'T> -> 'D) -> 'D> 208 | 209 | /// Create a Form that returns a reactive optional value, 210 | /// initialized to a successful value `init`. 211 | /// 212 | /// When the associated Var is `noneValue`, the result value is `None`; 213 | /// when it is any other value `x`, the result value is `Some x`. 214 | val YieldOption 215 | : init: option<'T> 216 | -> noneValue: 'T 217 | -> Form, (Var<'T> -> 'D) -> 'D> 218 | when 'T : equality 219 | 220 | /// Apply a Form that returns a function to a Form that returns a value. 221 | val Apply 222 | : Form<'T -> 'U, 'R -> 'R1> 223 | -> Form<'T, 'R1 -> 'D> 224 | -> Form<'U, 'R -> 'D> 225 | 226 | /// Add a submitter to a Form: the returned Form gets its value from 227 | /// the input Form whenever the submitter is triggered. 228 | val WithSubmit 229 | : Form<'T, 'R -> Submitter> -> 'D> 230 | -> Form<'T, 'R -> 'D> 231 | 232 | /// Pass a view on the result of a Form to its render function. 233 | val TransmitView 234 | : Form<'T, 'R -> View> -> 'D> 235 | -> Form<'T, 'R -> 'D> 236 | 237 | /// Pass a mapped view on the result of a Form to its render function. 238 | val TransmitViewMap 239 | : ('T -> 'U) 240 | -> Form<'T, 'R -> View> -> 'D> 241 | -> Form<'T, 'R -> 'D> 242 | 243 | /// Pass a mapped view on the result of a Form to its render function. 244 | val TransmitViewMapResult 245 | : (Result<'T> -> 'U) 246 | -> Form<'T, 'R -> View<'U> -> 'D> 247 | -> Form<'T, 'R -> 'D> 248 | 249 | /// Map the result of a Form. 250 | val Map 251 | : ('T -> 'U) 252 | -> Form<'T, 'R -> 'D> 253 | -> Form<'U, 'R -> 'D> 254 | 255 | /// Map the result of a Form. 256 | val MapToResult 257 | : ('T -> Result<'U>) 258 | -> Form<'T, 'R -> 'D> 259 | -> Form<'U, 'R -> 'D> 260 | 261 | /// Map the result of a Form. 262 | val MapResult 263 | : (Result<'T> -> Result<'U>) 264 | -> Form<'T, 'R -> 'D> 265 | -> Form<'U, 'R -> 'D> 266 | 267 | /// Map the result of a Form asynchronously. 268 | val MapAsync 269 | : ('T -> Async<'U>) 270 | -> Form<'T, 'R -> 'D> 271 | -> Form<'U, 'R -> 'D> 272 | 273 | /// Map the result of a Form asynchronously. 274 | val MapToAsyncResult 275 | : ('T -> Async>) 276 | -> Form<'T, 'R -> 'D> 277 | -> Form<'U, 'R -> 'D> 278 | 279 | /// Map the result of a Form asynchronously. 280 | val MapAsyncResult 281 | : (Result<'T> -> Async>) 282 | -> Form<'T, 'R -> 'D> 283 | -> Form<'U, 'R -> 'D> 284 | 285 | /// Map the arguments passed to the render function of a Form. 286 | val MapRenderArgs 287 | : 'R1 288 | -> Form<'T, 'R1 -> 'R2> 289 | -> Form<'T, ('R2 -> 'D) -> 'D> 290 | 291 | /// Map any failing result to a failure with no error messages. 292 | val FlushErrors 293 | : Form<'T, 'R -> 'D> 294 | -> Form<'T, 'R -> 'D> 295 | 296 | /// Run a function on all successful results. 297 | val Run 298 | : ('T -> unit) 299 | -> Form<'T, 'R -> 'D> 300 | -> Form<'T, 'R -> 'D> 301 | 302 | /// Run a function on all results. 303 | val RunResult 304 | : (Result<'T> -> unit) 305 | -> Form<'T, 'R -> 'D> 306 | -> Form<'T, 'R -> 'D> 307 | 308 | /// Create a dependent Form where a `dependent` Form depends on the value of a `primary` Form. 309 | val Dependent 310 | : primary: Form<'TPrimary, 'U -> 'V> 311 | -> dependent: ('TPrimary -> Form<'TResult, 'W -> 'X>) 312 | -> Form<'TResult, (Dependent<'TResult, 'U, 'W> -> 'Y) -> 'Y> 313 | when 'TPrimary : equality and 'V :> Doc and 'X :> Doc 314 | 315 | /// Create a Form that returns a collection of values, 316 | /// with an additional Form used to insert new values in the collection. 317 | val ManyForm 318 | : init: seq<'T> 319 | -> addForm: (Form<'T, 'Y -> 'Z>) 320 | -> itemForm: ('T -> Form<'T, 'V -> 'W>) 321 | -> Form, (Many.Collection<'T, 'V, 'W, 'Y, 'Z> -> 'x) -> 'x> 322 | when 'W :> Doc and 'Z :> Doc 323 | 324 | /// Create a Form that returns a collection of values, each created according to the given Form. 325 | val Many 326 | : init: seq<'T> 327 | -> addValue: 'T 328 | -> itemForm: ('T -> Form<'T, 'V -> 'W>) 329 | -> Form, (Many.CollectionWithDefault<'T, 'V, 'W> -> 'x) -> 'x> 330 | when 'W :> Doc and 'Z :> Doc 331 | 332 | type Builder = 333 | | Do 334 | 335 | /// Create a dependent Form where the `dependent` part depends on an `primary` Form. 336 | member Bind 337 | : input: Form<'TPrimary, 'U -> 'V> 338 | * output: ('TPrimary -> Form<'TResult, 'W -> 'X>) 339 | -> Form<'TResult, (Dependent<'TResult, 'U, 'W> -> 'Y) -> 'Y> 340 | when 'TPrimary : equality and 'V :> Doc and 'X :> Doc 341 | 342 | /// Create a Form that always returns the same successful value. 343 | member Return : 'T -> Form<'T, 'D -> 'D> 344 | 345 | /// Return the given Form. 346 | member ReturnFrom : Form<'T, 'R -> 'D> -> Form<'T, 'R -> 'D> 347 | 348 | /// Create a Form that returns a reactive value, 349 | /// initialized to a successful value `init`. 350 | member Yield : init: 'T -> Form<'T, (Var<'T> -> 'D) -> 'D> 351 | 352 | /// Return the given Form. 353 | member YieldFrom : Form<'T, 'R -> 'D> -> Form<'T, 'R -> 'D> 354 | 355 | /// Create a Form that always fails. 356 | member Zero : unit -> Form<'T, 'D -> 'D> 357 | 358 | /// Functions to validate the value of a Form. 359 | module Validation = 360 | 361 | /// If the Form value passes the predicate, it is passed on; 362 | /// else, `Failwith msg` is passed on. 363 | val Is : pred: ('T -> bool) -> msg: string -> Form<'T, 'R -> 'D> -> Form<'T, 'R -> 'D> 364 | 365 | /// If the Form value is not an empty string, it is passed on; 366 | /// else, `Failwith msg` is passed on. 367 | val IsNotEmpty : msg: string -> Form 'D> -> Form 'D> 368 | 369 | /// If the Form value matches the given regexp, it is passed on; 370 | /// else, `Failwith msg` is passed on. 371 | val IsMatch : regexp: string -> msg: string -> Form 'D> -> Form 'D> 372 | 373 | val MapValidCheckedInput : msg: string -> Form, 'R -> 'D> -> Form<'T, 'R -> 'D> 374 | 375 | [] 376 | module Pervasives = 377 | 378 | /// Apply a Form that returns a function to a Form that returns a value. 379 | val (<*>) 380 | : pf: Form<'T -> 'U, 'R -> 'R1> 381 | -> px: Form<'T, 'R1 -> 'D> 382 | -> Form<'U, 'R -> 'D> 383 | 384 | val (<*?>) 385 | : pf: Form<'T -> 'U, 'R -> 'R1> 386 | -> px: Form, 'R1 -> 'D> 387 | -> Form<'U, 'R -> 'D> 388 | 389 | module Attr = 390 | 391 | /// Add a click handler that triggers a Submitter, 392 | /// and disable the element when the submitter's input is a failure. 393 | val SubmitterValidate 394 | : Submitter> 395 | -> Attr 396 | 397 | module Doc = 398 | 399 | /// Create a button that triggers a Submitter when clicked, 400 | /// and is disabled when the submitter's input is a failure. 401 | val ButtonValidate 402 | : caption: string 403 | -> seq 404 | -> Submitter> 405 | -> Elt 406 | 407 | /// When the input View is a failure, show the given Doc; 408 | /// otherwise, show an empty Doc. 409 | val ShowErrors 410 | : View> 411 | -> (list -> Doc) 412 | -> Doc 413 | 414 | /// When the input View is a success, show the given Doc; 415 | /// otherwise, show an empty Doc. 416 | val ShowSuccess 417 | : View> 418 | -> ('T -> Doc) 419 | -> Doc 420 | 421 | module private Fresh = 422 | 423 | val Id : unit -> string 424 | 425 | [] 426 | type View = 427 | 428 | /// When the input View is a failure, restrict its error messages 429 | /// to those that come directly from the given Var. 430 | [] 431 | static member Through 432 | : input: View> 433 | * Var<'U> 434 | -> View> 435 | 436 | /// When the input View is a failure, restrict its error messages 437 | /// to those that come directly from the given Form. 438 | [] 439 | static member Through 440 | : input: View> 441 | * Form<'U, 'R> 442 | -> View> 443 | 444 | /// When the input View is a failure, show the given Doc; 445 | /// otherwise, show an empty Doc. 446 | [] 447 | static member ShowErrors 448 | : View> 449 | * (list -> Doc) 450 | -> Doc 451 | 452 | /// When the input View is a success, show the given Doc; 453 | /// otherwise, show an empty Doc. 454 | [] 455 | static member ShowSuccess 456 | : View> 457 | * ('T -> Doc) 458 | -> Doc 459 | -------------------------------------------------------------------------------- /WebSharper.Forms/WebSharper.Forms.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netstandard2.0 4 | Library 5 | true 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /WebSharper.Forms/paket.references: -------------------------------------------------------------------------------- 1 | WebSharper 2 | WebSharper.FSharp 3 | WebSharper.UI 4 | FSharp.Core 5 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal 3 | 4 | dotnet tool restore 5 | 6 | dotnet paket update -g wsbuild --no-install 7 | if errorlevel 1 exit /b %errorlevel% 8 | 9 | dotnet fsi ./build.fsx -t %* -------------------------------------------------------------------------------- /build.fsx: -------------------------------------------------------------------------------- 1 | #r "nuget: FAKE.Core" 2 | #r "nuget: Fake.Core.Target" 3 | #r "nuget: Fake.IO.FileSystem" 4 | #r "nuget: Fake.Tools.Git" 5 | #r "nuget: Fake.DotNet.Cli" 6 | #r "nuget: Fake.DotNet.AssemblyInfoFile" 7 | #r "nuget: Fake.DotNet.Paket" 8 | #r "nuget: Paket.Core, 8.1.0-alpha004" 9 | #r "nuget: MSBuild.StructuredLogger" 10 | 11 | open Fake.Core 12 | System.Environment.GetCommandLineArgs() 13 | |> Array.skip 2 // skip fsi.exe; build.fsx 14 | |> Array.toList 15 | |> Fake.Core.Context.FakeExecutionContext.Create false __SOURCE_FILE__ 16 | |> Fake.Core.Context.RuntimeContext.Fake 17 | |> Fake.Core.Context.setExecutionContext 18 | 19 | #load "paket-files/wsbuild/github.com/dotnet-websharper/build-script/WebSharper.Fake.fsx" 20 | #r "System.Xml.Linq" 21 | 22 | open WebSharper.Fake 23 | open Fake.DotNet 24 | 25 | LazyVersionFrom "WebSharper" |> WSTargets.Default 26 | |> fun args -> 27 | { args with 28 | Attributes = 29 | [ 30 | AssemblyInfo.Company "IntelliFactory" 31 | AssemblyInfo.Copyright "(c) IntelliFactory 2023" 32 | AssemblyInfo.Title "https://github.com/dotnet-websharper/forms" 33 | AssemblyInfo.Product "WebSharper Forms" 34 | ] 35 | } 36 | |> MakeTargets 37 | |> RunTargets 38 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | dotnet tool restore 4 | 5 | dotnet paket update -g wsbuild --no-install 6 | 7 | . paket-files/wsbuild/github.com/dotnet-websharper/build-script/build.sh "$@" -------------------------------------------------------------------------------- /docs/Introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction to Forms 2 | 3 | The WebSharper.Forms (aka. UI.Piglets or **reactive** piglets/forms, see also ordinary [piglets](https://github.com/dotnet-websharper/piglets)) library provides a high-level abstraction for working with web forms and constructing interactive user interfaces. It is closely related to [formlets](http://websharper.com/docs/formlets) (see also [UI.Formlets](https://github.com/dotnet-websharper/ui.formlets)) as they both provide the capability to declaratively describe user data input such as forms, including data validation and feedback. The main difference comes from the way actual widgets are rendered: Formlets automatically generate input fields and layout markup, while reactive forms let the developer render the composed form using custom markup. 4 | 5 | You should use Piglets/Forms in one of these cases: 6 | 7 | * You want to have absolute control over the rendering of the form. 8 | 9 | * You are creating an application for different frontends (e.g. a web version using JQueryUI and a mobile version using JQueryMobile) and would like to factor the data definition and validation code, leaving only the actual rendering to be differenciated. 10 | 11 | You should use Formlets in one of these cases: 12 | 13 | * You want your code to be extremely concise and define at the same time how input data is composed and validated, and how input fields are rendered. 14 | 15 | * You are developing a back-office application, prioritizing speed of development over pixel-perfect design. 16 | 17 | In all cases, Piglets/Forms and Formlets have a lot in common: 18 | 19 | * They are type-safe: unlike many "strongly typed" templating engines, in which a field is only identified by an id and there is no way to check that, say, a datepicker is indeed associated with a field of type `Date`, Formlets and Piglets/Forms are able to guarantee such properties. 20 | 21 | * Data composition and validation is done declaratively, and the dynamic aspects of computing and checking a result value are automated. 22 | 23 | * They are composable: you can define a *X*let and use it as part of a bigger *X*let. 24 | 25 | * They can express dependent sub-forms, i.e. the type and appearance of input fields in part of the form dynamically depends on user input in previous fields. 26 | 27 | Using Forms is easy. Users might be frightened by their cryptic type signature so this guide intends to explain what is the meaning of all the elements that compose a Form. In addition, introductory examples will be presented to get the user acquainted with Forms. 28 | 29 | We recommend to read [the Formlets documentation](http://websharper.com/docs/formlets) first, as some concepts, such as the `<*>` operator or validation, will be introduced with less detail here. 30 | 31 | Forms is an implementation of piglets based on [WebSharper UI](http://github.com/intellifactory/ui). Therefore familiarity with concepts such as `Var`, `View` and the `Doc` type for HTML is necessary to work with it. 32 | 33 | 34 | ## A simple Form 35 | 36 | Programming with reactive forms has two distinct steps: 37 | 38 | * Defining your Form, i.e. defining the fields that compose the result, how they are composed, and what validation must be run on them. 39 | 40 | * Rendering your Form, i.e. creating the markup that will be used and connecting the input fields with the reactive values created in the first step. 41 | 42 | ### Defining a Form 43 | 44 | In this step we create a value of type `Form<'T, 'R>` where: 45 | 46 | * `'T` is the type returned by the Form. 47 | 48 | * `'R` is the type of the render builder. It will always have the following shape: 49 | 50 | ``` 51 | (arg1 -> arg2 -> ... -> argn -> 'b) -> 'b 52 | ``` 53 | 54 | which means that the view function from the second step will take arguments `arg1 ... argn` and return whatever type of markup element we want. 55 | 56 | Let's create a reactive form to input data about a pet. We will need the species and the name of the pet. First, let's define the corresponding types: 57 | 58 | ```fsharp 59 | type Species = 60 | | Cat | Dog | Piglet 61 | 62 | [] 63 | override this.ToString() = 64 | match this with 65 | | Cat -> "cat" 66 | | Dog -> "dog" 67 | | Piglet -> "piglet" 68 | 69 | type Pet = { species : Species; name : string } 70 | ``` 71 | 72 | Then, let's define the Form itself: 73 | 74 | ```fsharp 75 | let PetForm (init: Pet) = 76 | Form.Return (fun s n -> { species = s; name = n }) 77 | <*> Form.Yield init.species 78 | <*> (Form.Yield init.name 79 | |> Validation.IsNotEmpty "Please enter the pet's name.") 80 | ``` 81 | 82 | If you learned about Formlets already, this should look familiar. We first define a Form with a function type, and then successively compose it with each field. The main difference is that here, the fields do not declare how they will be rendered. `Form.Yield init.name` only creates a Form whose value has type `string` and which is initialized with `init.name`. Contrast with Formlet's `Controls.Input init.name`, which also declares that it should be rendered as an input field. 83 | 84 | The types of `Form.Return`, `<*>` and `Form.Yield` are more complex than their Formlet counterparts, since they also deal with composing the view builder. 85 | 86 | ```fsharp 87 | val Return : 'T -> Form<'T, ('D -> 'D)> 88 | 89 | val Yield : 'T -> Form<'T, (Var<'T> -> 'D) -> 'D> 90 | 91 | val (<*>) : Form<('T -> 'U), ('R -> 'R1)> -> 92 | Form<'T, ('R1 -> 'D)> -> 93 | Form<'U, ('R -> 'D)> 94 | ``` 95 | 96 | Validation is also very similar to Formlet validation: the Form is passed through a combinator, `Validation.IsNotEmpty`, that defines the condition that must be fulfilled and the error message in case it isn't. 97 | 98 | We have now defined how a species and a name should be composed into a Pet, and how the name should be verified. Time to define how to render the corresponding reactive form. 99 | 100 | ### Rendering a Form 101 | 102 | The Form we defined has the following type: 103 | 104 | ```fsharp 105 | val PetForm : Pet -> 106 | Form -> 108 | Var -> 109 | 'b) -> 'b> 110 | ``` 111 | 112 | The first type argument to our form is `Pet`, as expected, since that's what we want to return. The second type argument has the shape described previously: it takes as argument a function from several arguments (two `Var`s), and calls it with the appropriate `Var`s to obtain the rendered document. 113 | 114 | ```fsharp 115 | let RenderPet species name = 116 | div [ 117 | label [Doc.Radio [] Cat species; text (string Cat)] 118 | label [Doc.Radio [] Dog species; text (string Dog)] 119 | label [Doc.Radio [] Piglet species; text (string Piglet)] 120 | Doc.Input [] name 121 | ] 122 | ``` 123 | 124 | Here, `species` has type `Var`, and `name` has type `Var`. So the type of `RenderPet` corresponds to the argument of the second type parameter of `PetForm`, with `'b` specialized to `Element`. 125 | 126 | The functions `Doc.Radio` and `Doc.Input` come from WebSharper.UI, and create elements whose value is always synchronized with the `Var` they receive. Note that, unlike Formlets which include layout markup, these functions only render the needed input elements, allowing you to lay them out and style them as you want. For example, you can add attributes directly to the input element: 127 | 128 | ```fsharp 129 | Doc.Input [attr.class "pet-name"] name 130 | ``` 131 | 132 | In order to use `RenderPet` to render the pet form, we use `Form.Render`: 133 | 134 | ```fsharp 135 | let PetFormUI = 136 | PetForm { species = Cat; name = "Fluffy" } 137 | |> Form.Render RenderPet 138 | ``` 139 | 140 | We now have a value `PetFormUI : Doc` that we can integrate directly into our HTML markup. It will display a radio list and a text input field, and update the resulting `Pet` value according to user input in these two fields. 141 | 142 | Note that right now, we are not doing anything with this resulting `Pet`. The simplest way to do so is using `Form.Run`, which calls a function every time the value is changed. 143 | 144 | ```fsharp 145 | let PetFormUI = 146 | PetForm { species = Cat; name = "Fluffy" } 147 | |> Form.Run (fun animal -> 148 | JavaScript.Alert ( 149 | "Your " + string animal.species + 150 | " is called " + animal.name)) 151 | |> Form.Render RenderPet 152 | ``` 153 | 154 | ## More complex Forms 155 | 156 | ### Submit button 157 | 158 | The above `PetFormUI` is not very user friendly: it triggers (and shows an alert window) every time the user inputs a character. Let's fix this by adding a submit button to the underlying form. 159 | 160 | ```fsharp 161 | let PetFormWithSubmit (init: Pet) = 162 | Form.Return (fun s n -> { species = s; name = n }) 163 | <*> Form.Yield init.species 164 | <*> (Form.Yield init.name 165 | |> Validation.IsNotEmpty "Please enter the pet's name.") 166 | |> Form.WithSubmit 167 | ``` 168 | 169 | Now `PetFormWithSubmit` only triggers a new return value when the user submits the form. A new value of type `Submitter` is passed to the view function, and rendering it is just as simple: 170 | 171 | ```fsharp 172 | let RenderPet species name submitter = 173 | div [ 174 | label [Doc.Radio [] Cat species; text (string Cat)] 175 | label [Doc.Radio [] Dog species; text (string Dog)] 176 | label [Doc.Radio [] Piglet species; text (string Piglet)] 177 | Doc.Input [] name 178 | Doc.Button [] submitter.Trigger 179 | ] 180 | ``` 181 | 182 | If you want the submit button to be grayed out when the input is invalid (i.e. in our case, when the name field is empty), use `Doc.ButtonValidate` instead. 183 | 184 | ### Displaying values and error messages 185 | 186 | We have already seen `Form.Run`; but another common action to do with the result value is to display it. You can get the result from the `View` property on the submitter. It has a value of the following type: 187 | 188 | ```fsharp 189 | type Result<'T> = 190 | | Success of 'T 191 | | Failure of ErrorMessage list 192 | ``` 193 | 194 | where `ErrorMessage` has a `Text` field containing the text message. Here is an example: 195 | 196 | ```fsharp 197 | let RenderPetWithSubmit species name submit = 198 | div [ 199 | submit.View 200 | |> View.Map (function 201 | | Success pet -> 202 | Doc.Concat [ 203 | span [text ("Your " + string pet.species + " is called ")] 204 | b [text pet.name] 205 | ] 206 | | Failure errors -> 207 | Doc.Concat [ 208 | for error in errors do 209 | yield bAttr [attr.style "color:red"] [text error.Text] :> _ 210 | ]) 211 | |> Doc.EmbedView 212 | ] 213 | ``` 214 | 215 | Note that we've been showing the result after submission. If you want to use the live value as it is input by the user, either to display it or for some other purpose, it is available as `submit.Input`. 216 | 217 | ### Forms for collections 218 | 219 | Let's make this form more complex by asking the user about their own name and a list of their pets. They will be able to add, remove and reorder pets in the form. 220 | 221 | Here is the final data we want to collect: 222 | 223 | ```fsharp 224 | type Person = 225 | { 226 | firstName: string 227 | lastName: string 228 | pets: seq 229 | } 230 | ``` 231 | 232 | Defining a Form for this type is relatively straightforward using a function from the `Form.Many*` family: 233 | 234 | ```fsharp 235 | let PersonForm (init: Person) = 236 | Form.Return (fun first last pets -> 237 | { firstName = first; lastName = last; pets = pets }) 238 | <*> (Form.Yield init.firstName 239 | |> Validation.Is Validation.NotEmpty "Please enter your first name.") 240 | <*> (Form.Yield init.lastName 241 | |> Validation.Is Validation.NotEmpty "Please enter your last name.") 242 | <*> Form.Many init.pets { species = Cat; name = "" } PetForm 243 | |> Form.WithSubmit 244 | ``` 245 | 246 | The function `Form.Many` takes three arguments: 247 | 248 | * The initial collection of values, of type `seq`. 249 | 250 | * The value of type `Pet` with which the new sub-form should be initialized when the user inserts a new pet. 251 | 252 | * A function taking an initial `Pet` value and returning the `Form` that will be shown for each pet. 253 | 254 | It returns a Form whose value is a sequence of `Pet`s, and adds an argument to the render function of type `Form.Many.CollectionWithDefault<'T, 'V, 'W>`. The type `'T` is the type of items in the collection, and `'V -> 'W` is the type of the render builder for a single item. This is how you render such a stream: 255 | 256 | ```fsharp 257 | let RenderPerson (firstName: Var) 258 | (lastName: Var) 259 | (pets: Form.Many.CollectionWithDefault) 260 | (submit: Submitter>) = 261 | div [ 262 | div [Doc.Input [] firstName] 263 | div [Doc.Input [] lastName] 264 | pets.Render (fun ops species name -> 265 | div [ 266 | RenderPet species name 267 | Doc.ButtonValidate "Move up" [] ops.MoveUp 268 | Doc.ButtonValidate "Move down" [] ops.MoveDown 269 | Doc.Button "Delete" [] ops.Delete 270 | ]) 271 | Doc.Button "Add a pet" [] pets.Add 272 | Doc.ButtonValidate "Submit" [] submit 273 | ] 274 | ``` 275 | 276 | The function passed to `pets.Render` is called once for every new item in the collection, and defines how this individual item should be rendered. It takes as arguments: 277 | 278 | * A value of type `Form.Many.ItemOperations`, named `ops` here. This value has members that allow to move the current item up or down in the collection, or to delete it. 279 | 280 | * The arguments of the render function for the item rendering Form, ie. the Form that was passed as the third argument to `Form.Many`. 281 | 282 | `CollectionWithDefault` also contains a callback called `Add` that adds a new pet at the end of the collection. 283 | 284 | ### Localized errors 285 | 286 | We have seen how to show all the errors together from `submit`. But in many cases it is useful to show the error associated with a given field next to that field. For that purpose, the type `View>` has an extension method `Through` that takes a `Var` or a `Form`, and returns a new `View>` whose value is the same as the original one, except on failure, only error messages associated with the given `Var` or `Form` are kept. For example, the following shows the error messages associated with `firstName`: 287 | 288 | ```fsharp 289 | submit.View.Through firstName 290 | |> View.Map (function 291 | | Success _ -> Doc.Empty 292 | | Failure errors -> 293 | Doc.Concat [ 294 | for error in errors do 295 | yield bAttr [attr.style "color:red"] [text error.Text] :> _ 296 | ] 297 | ) 298 | |> Doc.EmbedView 299 | ``` 300 | 301 | ## Complete example 302 | 303 | Here is now the complete example, showcasing all the elements described in this tutorial. 304 | 305 | ```fsharp 306 | type Species = 307 | | Cat | Dog | Piglet 308 | [] 309 | override this.ToString() = 310 | match this with 311 | | Cat -> "cat" 312 | | Dog -> "dog" 313 | | Piglet -> "piglet" 314 | 315 | type Pet = { species: Species; name: string } 316 | type Person = { firstName: string; lastName: string; pets: seq } 317 | 318 | let PetForm (init: Pet) = 319 | Form.Return (fun s n -> { species = s; name = n }) 320 | <*> Form.Yield init.species 321 | <*> (Form.Yield init.name 322 | |> Validation.IsNotEmpty "Please enter your pet's name.") 323 | 324 | let PersonForm (init: Person) = 325 | Form.Return (fun first last pets -> 326 | { firstName = first; lastName = last; pets = pets }) 327 | <*> (Form.Yield init.firstName 328 | |> Validation.IsNotEmpty "Please enter your first name.") 329 | <*> (Form.Yield init.lastName 330 | |> Validation.IsNotEmpty "Please enter your last name.") 331 | <*> Form.Many init.pets { species = Cat; name = "" } PetForm 332 | |> Form.WithSubmit 333 | 334 | let RenderPet species name = 335 | Doc.Concat [ 336 | label [Doc.Radio [] Cat species; text (string Cat)] 337 | label [Doc.Radio [] Dog species; text (string Dog)] 338 | label [Doc.Radio [] Piglet species; text (string Piglet)] 339 | Doc.Input [] name 340 | ] 341 | 342 | let ShowErrorsFor v = 343 | v 344 | |> View.Map (function 345 | | Success _ -> Doc.Empty 346 | | Failure errors -> 347 | Doc.Concat [ 348 | for error in errors do 349 | yield bAttr [attr.style "color:red"] [text error.Text] :> _ 350 | ] 351 | ) 352 | |> Doc.EmbedView 353 | 354 | let RenderPerson (firstName: Var) 355 | (lastName: Var) 356 | (pets: Form.Many.CollectionWithDefault) 357 | (submit: Submitter>) = 358 | div [ 359 | h2 [text "You"] 360 | div [ 361 | label [text "First name: "; Doc.Input [] firstName] 362 | ShowErrorsFor (submit.View.Through firstName) 363 | ] 364 | div [ 365 | label [text "Last name: "; Doc.Input [] lastName] 366 | ShowErrorsFor (submit.View.Through lastName) 367 | ] 368 | h2 [text "Your pets"] 369 | div [ 370 | pets.Render (fun ops species name -> 371 | div [ 372 | RenderPet species name 373 | Doc.ButtonValidate "Move up" [] ops.MoveUp 374 | Doc.ButtonValidate "Move down" [] ops.MoveDown 375 | Doc.Button "Delete" [] ops.Delete 376 | ShowErrorsFor (submit.View.Through name) 377 | ]) 378 | Doc.Button "Add a pet" [] pets.Add 379 | ] 380 | div [ 381 | Doc.Button "Submit" [] submit.Trigger 382 | ] 383 | ] 384 | 385 | let Form = 386 | PersonForm { 387 | firstName = "" 388 | lastName = "" 389 | pets = [||] } 390 | |> Form.Run (fun p -> 391 | let message = 392 | "Welcome to you " + p.firstName + " " + p.lastName + 393 | (p.pets 394 | |> Seq.map (fun pet -> 395 | ", your " + string pet.species + " " + pet.name) 396 | |> String.concat "") + 397 | "!" 398 | JS.Alert message) 399 | |> Form.Render RenderPerson 400 | ``` 401 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "8.0.0", 4 | "rollForward": "latestFeature", 5 | "allowPrerelease": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ivy.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /nuget/WebSharper.Forms.paket.template: -------------------------------------------------------------------------------- 1 | type file 2 | id WebSharper.Forms 3 | authors IntelliFactory 4 | owners IntelliFactory 5 | projectUrl https://websharper.com/ 6 | repositoryType git 7 | repositoryUrl https://github.com/dotnet-websharper/forms 8 | licenseUrl http://github.com/intellifactory/websharper.forms/blob/master/LICENSE.md 9 | iconUrl https://github.com/dotnet-websharper/core/raw/websharper50/tools/WebSharper.png 10 | description 11 | Provides a framework to build reactive interfaces in WebSharper,similar to Formlets but with more control over the structure of the output. 12 | tags 13 | WebSharper Web JavaScript F# C# FSharp CSharp 14 | files 15 | ../WebSharper.Forms/bin/Release/netstandard2.0/WebSharper.Forms.dll ==> lib/netstandard2.0 16 | ../WebSharper.Forms/bin/Release/netstandard2.0/WebSharper.Forms.xml ==> lib/netstandard2.0 17 | dependencies 18 | framework: netstandard2.0 19 | WebSharper ~> LOCKEDVERSION:[3] 20 | WebSharper.UI ~> LOCKEDVERSION:[3] 21 | -------------------------------------------------------------------------------- /paket.dependencies: -------------------------------------------------------------------------------- 1 | source https://api.nuget.org/v3/index.json 2 | source https://nuget.pkg.github.com/dotnet-websharper/index.json 3 | source ../localnuget 4 | 5 | framework: netstandard2.0, netcoreapp2.1, netcoreapp3.1, net8.0 6 | 7 | storage: none 8 | strategy: min 9 | 10 | nuget WebSharper prerelease 11 | nuget WebSharper.FSharp prerelease 12 | nuget WebSharper.UI prerelease 13 | 14 | 15 | group wsbuild 16 | git https://github.com/dotnet-websharper/build-script websharper80 17 | 18 | group testing 19 | source https://api.nuget.org/v3/index.json 20 | source https://nuget.pkg.github.com/dotnet-websharper/index.json 21 | source ../localnuget 22 | 23 | framework: netstandard2.0, netcoreapp2.1, netcoreapp3.1, net8.0 24 | 25 | storage: none 26 | strategy: min 27 | 28 | nuget FSharp.Core 29 | nuget WebSharper prerelease 30 | nuget WebSharper.FSharp prerelease 31 | nuget WebSharper.UI prerelease 32 | nuget WebSharper.AspNetCore prerelease 33 | -------------------------------------------------------------------------------- /paket.lock: -------------------------------------------------------------------------------- 1 | STORAGE: NONE 2 | STRATEGY: MIN 3 | RESTRICTION: || (== net8.0) (== netcoreapp2.1) (== netcoreapp3.1) (== netstandard2.0) 4 | NUGET 5 | remote: https://api.nuget.org/v3/index.json 6 | FSharp.Core (6.0) 7 | HtmlAgilityPack (1.11) 8 | System.Net.Http (>= 4.3.2) 9 | System.Xml.XmlDocument (>= 4.3) 10 | System.Xml.XPath (>= 4.3) 11 | System.Xml.XPath.XmlDocument (>= 4.3) 12 | Microsoft.NETCore.Platforms (1.1) 13 | Microsoft.NETCore.Targets (1.1) 14 | runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 15 | runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 16 | runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 17 | runtime.native.System (4.3) 18 | Microsoft.NETCore.Platforms (>= 1.1) 19 | Microsoft.NETCore.Targets (>= 1.1) 20 | runtime.native.System.Net.Http (4.3) 21 | Microsoft.NETCore.Platforms (>= 1.1) 22 | Microsoft.NETCore.Targets (>= 1.1) 23 | runtime.native.System.Security.Cryptography.Apple (4.3) 24 | runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (>= 4.3) 25 | runtime.native.System.Security.Cryptography.OpenSsl (4.3) 26 | runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 27 | runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 28 | runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 29 | runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 30 | runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 31 | runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 32 | runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 33 | runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 34 | runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 35 | runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 36 | runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 37 | runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 38 | runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (4.3) 39 | runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 40 | runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 41 | runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 42 | runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 43 | runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 44 | System.Collections (4.3) 45 | Microsoft.NETCore.Platforms (>= 1.1) 46 | Microsoft.NETCore.Targets (>= 1.1) 47 | System.Runtime (>= 4.3) 48 | System.Collections.Concurrent (4.3) 49 | System.Collections (>= 4.3) 50 | System.Diagnostics.Debug (>= 4.3) 51 | System.Diagnostics.Tracing (>= 4.3) 52 | System.Globalization (>= 4.3) 53 | System.Reflection (>= 4.3) 54 | System.Resources.ResourceManager (>= 4.3) 55 | System.Runtime (>= 4.3) 56 | System.Runtime.Extensions (>= 4.3) 57 | System.Threading (>= 4.3) 58 | System.Threading.Tasks (>= 4.3) 59 | System.Diagnostics.Debug (4.3) 60 | Microsoft.NETCore.Platforms (>= 1.1) 61 | Microsoft.NETCore.Targets (>= 1.1) 62 | System.Runtime (>= 4.3) 63 | System.Diagnostics.DiagnosticSource (4.3) 64 | System.Collections (>= 4.3) 65 | System.Diagnostics.Tracing (>= 4.3) 66 | System.Reflection (>= 4.3) 67 | System.Runtime (>= 4.3) 68 | System.Threading (>= 4.3) 69 | System.Diagnostics.Tracing (4.3) 70 | Microsoft.NETCore.Platforms (>= 1.1) 71 | Microsoft.NETCore.Targets (>= 1.1) 72 | System.Runtime (>= 4.3) 73 | System.Globalization (4.3) 74 | Microsoft.NETCore.Platforms (>= 1.1) 75 | Microsoft.NETCore.Targets (>= 1.1) 76 | System.Runtime (>= 4.3) 77 | System.Globalization.Calendars (4.3) 78 | Microsoft.NETCore.Platforms (>= 1.1) 79 | Microsoft.NETCore.Targets (>= 1.1) 80 | System.Globalization (>= 4.3) 81 | System.Runtime (>= 4.3) 82 | System.Globalization.Extensions (4.3) 83 | Microsoft.NETCore.Platforms (>= 1.1) 84 | System.Globalization (>= 4.3) 85 | System.Resources.ResourceManager (>= 4.3) 86 | System.Runtime (>= 4.3) 87 | System.Runtime.Extensions (>= 4.3) 88 | System.Runtime.InteropServices (>= 4.3) 89 | System.IO (4.3) 90 | Microsoft.NETCore.Platforms (>= 1.1) 91 | Microsoft.NETCore.Targets (>= 1.1) 92 | System.Runtime (>= 4.3) 93 | System.Text.Encoding (>= 4.3) 94 | System.Threading.Tasks (>= 4.3) 95 | System.IO.FileSystem (4.3) 96 | Microsoft.NETCore.Platforms (>= 1.1) 97 | Microsoft.NETCore.Targets (>= 1.1) 98 | System.IO (>= 4.3) 99 | System.IO.FileSystem.Primitives (>= 4.3) 100 | System.Runtime (>= 4.3) 101 | System.Runtime.Handles (>= 4.3) 102 | System.Text.Encoding (>= 4.3) 103 | System.Threading.Tasks (>= 4.3) 104 | System.IO.FileSystem.Primitives (4.3) 105 | System.Runtime (>= 4.3) 106 | System.Linq (4.3) 107 | System.Collections (>= 4.3) 108 | System.Diagnostics.Debug (>= 4.3) 109 | System.Resources.ResourceManager (>= 4.3) 110 | System.Runtime (>= 4.3) 111 | System.Runtime.Extensions (>= 4.3) 112 | System.Net.Http (4.3.2) 113 | Microsoft.NETCore.Platforms (>= 1.1) 114 | runtime.native.System (>= 4.3) 115 | runtime.native.System.Net.Http (>= 4.3) 116 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 117 | System.Collections (>= 4.3) 118 | System.Diagnostics.Debug (>= 4.3) 119 | System.Diagnostics.DiagnosticSource (>= 4.3) 120 | System.Diagnostics.Tracing (>= 4.3) 121 | System.Globalization (>= 4.3) 122 | System.Globalization.Extensions (>= 4.3) 123 | System.IO (>= 4.3) 124 | System.IO.FileSystem (>= 4.3) 125 | System.Net.Primitives (>= 4.3) 126 | System.Resources.ResourceManager (>= 4.3) 127 | System.Runtime (>= 4.3) 128 | System.Runtime.Extensions (>= 4.3) 129 | System.Runtime.Handles (>= 4.3) 130 | System.Runtime.InteropServices (>= 4.3) 131 | System.Security.Cryptography.Algorithms (>= 4.3) 132 | System.Security.Cryptography.Encoding (>= 4.3) 133 | System.Security.Cryptography.OpenSsl (>= 4.3) 134 | System.Security.Cryptography.Primitives (>= 4.3) 135 | System.Security.Cryptography.X509Certificates (>= 4.3) 136 | System.Text.Encoding (>= 4.3) 137 | System.Threading (>= 4.3) 138 | System.Threading.Tasks (>= 4.3) 139 | System.Net.Primitives (4.3) 140 | Microsoft.NETCore.Platforms (>= 1.1) 141 | Microsoft.NETCore.Targets (>= 1.1) 142 | System.Runtime (>= 4.3) 143 | System.Runtime.Handles (>= 4.3) 144 | System.Reflection (4.3) 145 | Microsoft.NETCore.Platforms (>= 1.1) 146 | Microsoft.NETCore.Targets (>= 1.1) 147 | System.IO (>= 4.3) 148 | System.Reflection.Primitives (>= 4.3) 149 | System.Runtime (>= 4.3) 150 | System.Reflection.Emit.ILGeneration (4.7) - restriction: || (&& (== net8.0) (< netcoreapp2.0) (< netstandard2.1)) (&& (== net8.0) (< netstandard2.0)) (&& (== net8.0) (< portable-net45+wp8)) (&& (== net8.0) (>= uap10.1)) (&& (== netcoreapp2.1) (< netcoreapp2.0)) (&& (== netcoreapp2.1) (< netstandard2.0)) (&& (== netcoreapp2.1) (< portable-net45+wp8)) (&& (== netcoreapp2.1) (>= uap10.1)) (&& (== netcoreapp3.1) (< netcoreapp2.0) (< netstandard2.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (< portable-net45+wp8)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) 151 | System.Reflection.Emit.Lightweight (4.7) 152 | System.Reflection.Emit.ILGeneration (>= 4.7) - restriction: || (&& (== net8.0) (< netcoreapp2.0) (< netstandard2.1)) (&& (== net8.0) (< netstandard2.0)) (&& (== net8.0) (< portable-net45+wp8)) (&& (== net8.0) (>= uap10.1)) (&& (== netcoreapp2.1) (< netcoreapp2.0)) (&& (== netcoreapp2.1) (< netstandard2.0)) (&& (== netcoreapp2.1) (< portable-net45+wp8)) (&& (== netcoreapp2.1) (>= uap10.1)) (&& (== netcoreapp3.1) (< netcoreapp2.0) (< netstandard2.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (< portable-net45+wp8)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) 153 | System.Reflection.Primitives (4.3) 154 | Microsoft.NETCore.Platforms (>= 1.1) 155 | Microsoft.NETCore.Targets (>= 1.1) 156 | System.Runtime (>= 4.3) 157 | System.Resources.ResourceManager (4.3) 158 | Microsoft.NETCore.Platforms (>= 1.1) 159 | Microsoft.NETCore.Targets (>= 1.1) 160 | System.Globalization (>= 4.3) 161 | System.Reflection (>= 4.3) 162 | System.Runtime (>= 4.3) 163 | System.Runtime (4.3) 164 | Microsoft.NETCore.Platforms (>= 1.1) 165 | Microsoft.NETCore.Targets (>= 1.1) 166 | System.Runtime.Extensions (4.3) 167 | Microsoft.NETCore.Platforms (>= 1.1) 168 | Microsoft.NETCore.Targets (>= 1.1) 169 | System.Runtime (>= 4.3) 170 | System.Runtime.Handles (4.3) 171 | Microsoft.NETCore.Platforms (>= 1.1) 172 | Microsoft.NETCore.Targets (>= 1.1) 173 | System.Runtime (>= 4.3) 174 | System.Runtime.InteropServices (4.3) 175 | Microsoft.NETCore.Platforms (>= 1.1) 176 | Microsoft.NETCore.Targets (>= 1.1) 177 | System.Reflection (>= 4.3) 178 | System.Reflection.Primitives (>= 4.3) 179 | System.Runtime (>= 4.3) 180 | System.Runtime.Handles (>= 4.3) 181 | System.Runtime.Numerics (4.3) 182 | System.Globalization (>= 4.3) 183 | System.Resources.ResourceManager (>= 4.3) 184 | System.Runtime (>= 4.3) 185 | System.Runtime.Extensions (>= 4.3) 186 | System.Security.Cryptography.Algorithms (4.3) 187 | Microsoft.NETCore.Platforms (>= 1.1) 188 | runtime.native.System.Security.Cryptography.Apple (>= 4.3) 189 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 190 | System.Collections (>= 4.3) 191 | System.IO (>= 4.3) 192 | System.Resources.ResourceManager (>= 4.3) 193 | System.Runtime (>= 4.3) 194 | System.Runtime.Extensions (>= 4.3) 195 | System.Runtime.Handles (>= 4.3) 196 | System.Runtime.InteropServices (>= 4.3) 197 | System.Runtime.Numerics (>= 4.3) 198 | System.Security.Cryptography.Encoding (>= 4.3) 199 | System.Security.Cryptography.Primitives (>= 4.3) 200 | System.Text.Encoding (>= 4.3) 201 | System.Security.Cryptography.Cng (4.3) 202 | Microsoft.NETCore.Platforms (>= 1.1) 203 | System.IO (>= 4.3) 204 | System.Resources.ResourceManager (>= 4.3) 205 | System.Runtime (>= 4.3) 206 | System.Runtime.Extensions (>= 4.3) 207 | System.Runtime.Handles (>= 4.3) 208 | System.Runtime.InteropServices (>= 4.3) 209 | System.Security.Cryptography.Algorithms (>= 4.3) 210 | System.Security.Cryptography.Encoding (>= 4.3) 211 | System.Security.Cryptography.Primitives (>= 4.3) 212 | System.Text.Encoding (>= 4.3) 213 | System.Security.Cryptography.Csp (4.3) 214 | Microsoft.NETCore.Platforms (>= 1.1) 215 | System.IO (>= 4.3) 216 | System.Reflection (>= 4.3) 217 | System.Resources.ResourceManager (>= 4.3) 218 | System.Runtime (>= 4.3) 219 | System.Runtime.Extensions (>= 4.3) 220 | System.Runtime.Handles (>= 4.3) 221 | System.Runtime.InteropServices (>= 4.3) 222 | System.Security.Cryptography.Algorithms (>= 4.3) 223 | System.Security.Cryptography.Encoding (>= 4.3) 224 | System.Security.Cryptography.Primitives (>= 4.3) 225 | System.Text.Encoding (>= 4.3) 226 | System.Threading (>= 4.3) 227 | System.Security.Cryptography.Encoding (4.3) 228 | Microsoft.NETCore.Platforms (>= 1.1) 229 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 230 | System.Collections (>= 4.3) 231 | System.Collections.Concurrent (>= 4.3) 232 | System.Linq (>= 4.3) 233 | System.Resources.ResourceManager (>= 4.3) 234 | System.Runtime (>= 4.3) 235 | System.Runtime.Extensions (>= 4.3) 236 | System.Runtime.Handles (>= 4.3) 237 | System.Runtime.InteropServices (>= 4.3) 238 | System.Security.Cryptography.Primitives (>= 4.3) 239 | System.Text.Encoding (>= 4.3) 240 | System.Security.Cryptography.OpenSsl (4.3) 241 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 242 | System.Collections (>= 4.3) 243 | System.IO (>= 4.3) 244 | System.Resources.ResourceManager (>= 4.3) 245 | System.Runtime (>= 4.3) 246 | System.Runtime.Extensions (>= 4.3) 247 | System.Runtime.Handles (>= 4.3) 248 | System.Runtime.InteropServices (>= 4.3) 249 | System.Runtime.Numerics (>= 4.3) 250 | System.Security.Cryptography.Algorithms (>= 4.3) 251 | System.Security.Cryptography.Encoding (>= 4.3) 252 | System.Security.Cryptography.Primitives (>= 4.3) 253 | System.Text.Encoding (>= 4.3) 254 | System.Security.Cryptography.Primitives (4.3) 255 | System.Diagnostics.Debug (>= 4.3) 256 | System.Globalization (>= 4.3) 257 | System.IO (>= 4.3) 258 | System.Resources.ResourceManager (>= 4.3) 259 | System.Runtime (>= 4.3) 260 | System.Threading (>= 4.3) 261 | System.Threading.Tasks (>= 4.3) 262 | System.Security.Cryptography.X509Certificates (4.3) 263 | Microsoft.NETCore.Platforms (>= 1.1) 264 | runtime.native.System (>= 4.3) 265 | runtime.native.System.Net.Http (>= 4.3) 266 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 267 | System.Collections (>= 4.3) 268 | System.Diagnostics.Debug (>= 4.3) 269 | System.Globalization (>= 4.3) 270 | System.Globalization.Calendars (>= 4.3) 271 | System.IO (>= 4.3) 272 | System.IO.FileSystem (>= 4.3) 273 | System.IO.FileSystem.Primitives (>= 4.3) 274 | System.Resources.ResourceManager (>= 4.3) 275 | System.Runtime (>= 4.3) 276 | System.Runtime.Extensions (>= 4.3) 277 | System.Runtime.Handles (>= 4.3) 278 | System.Runtime.InteropServices (>= 4.3) 279 | System.Runtime.Numerics (>= 4.3) 280 | System.Security.Cryptography.Algorithms (>= 4.3) 281 | System.Security.Cryptography.Cng (>= 4.3) 282 | System.Security.Cryptography.Csp (>= 4.3) 283 | System.Security.Cryptography.Encoding (>= 4.3) 284 | System.Security.Cryptography.OpenSsl (>= 4.3) 285 | System.Security.Cryptography.Primitives (>= 4.3) 286 | System.Text.Encoding (>= 4.3) 287 | System.Threading (>= 4.3) 288 | System.Text.Encoding (4.3) 289 | Microsoft.NETCore.Platforms (>= 1.1) 290 | Microsoft.NETCore.Targets (>= 1.1) 291 | System.Runtime (>= 4.3) 292 | System.Text.Encoding.Extensions (4.3) 293 | Microsoft.NETCore.Platforms (>= 1.1) 294 | Microsoft.NETCore.Targets (>= 1.1) 295 | System.Runtime (>= 4.3) 296 | System.Text.Encoding (>= 4.3) 297 | System.Text.RegularExpressions (4.3) 298 | System.Collections (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 299 | System.Globalization (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 300 | System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 301 | System.Runtime (>= 4.3) 302 | System.Runtime.Extensions (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 303 | System.Threading (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 304 | System.Threading (4.3) 305 | System.Runtime (>= 4.3) 306 | System.Threading.Tasks (>= 4.3) 307 | System.Threading.Tasks (4.3) 308 | Microsoft.NETCore.Platforms (>= 1.1) 309 | Microsoft.NETCore.Targets (>= 1.1) 310 | System.Runtime (>= 4.3) 311 | System.Threading.Tasks.Extensions (4.3) 312 | System.Collections (>= 4.3) 313 | System.Runtime (>= 4.3) 314 | System.Threading.Tasks (>= 4.3) 315 | System.Xml.ReaderWriter (4.3) 316 | System.Collections (>= 4.3) 317 | System.Diagnostics.Debug (>= 4.3) 318 | System.Globalization (>= 4.3) 319 | System.IO (>= 4.3) 320 | System.IO.FileSystem (>= 4.3) 321 | System.IO.FileSystem.Primitives (>= 4.3) 322 | System.Resources.ResourceManager (>= 4.3) 323 | System.Runtime (>= 4.3) 324 | System.Runtime.Extensions (>= 4.3) 325 | System.Runtime.InteropServices (>= 4.3) 326 | System.Text.Encoding (>= 4.3) 327 | System.Text.Encoding.Extensions (>= 4.3) 328 | System.Text.RegularExpressions (>= 4.3) 329 | System.Threading.Tasks (>= 4.3) 330 | System.Threading.Tasks.Extensions (>= 4.3) 331 | System.Xml.XmlDocument (4.3) 332 | System.Collections (>= 4.3) 333 | System.Diagnostics.Debug (>= 4.3) 334 | System.Globalization (>= 4.3) 335 | System.IO (>= 4.3) 336 | System.Resources.ResourceManager (>= 4.3) 337 | System.Runtime (>= 4.3) 338 | System.Runtime.Extensions (>= 4.3) 339 | System.Text.Encoding (>= 4.3) 340 | System.Threading (>= 4.3) 341 | System.Xml.ReaderWriter (>= 4.3) 342 | System.Xml.XPath (4.3) 343 | System.Collections (>= 4.3) 344 | System.Diagnostics.Debug (>= 4.3) 345 | System.Globalization (>= 4.3) 346 | System.IO (>= 4.3) 347 | System.Resources.ResourceManager (>= 4.3) 348 | System.Runtime (>= 4.3) 349 | System.Runtime.Extensions (>= 4.3) 350 | System.Threading (>= 4.3) 351 | System.Xml.ReaderWriter (>= 4.3) 352 | System.Xml.XPath.XmlDocument (4.3) 353 | System.Collections (>= 4.3) 354 | System.Globalization (>= 4.3) 355 | System.IO (>= 4.3) 356 | System.Resources.ResourceManager (>= 4.3) 357 | System.Runtime (>= 4.3) 358 | System.Runtime.Extensions (>= 4.3) 359 | System.Threading (>= 4.3) 360 | System.Xml.ReaderWriter (>= 4.3) 361 | System.Xml.XmlDocument (>= 4.3) 362 | System.Xml.XPath (>= 4.3) 363 | remote: https://nuget.pkg.github.com/dotnet-websharper/index.json 364 | WebSharper (9.1.1.557) 365 | FSharp.Core (>= 6.0) 366 | System.Reflection.Emit.Lightweight (>= 4.7) 367 | WebSharper.FSharp (9.1.1.557) 368 | WebSharper (9.1.1.557) 369 | WebSharper.UI (9.1.1.557) 370 | HtmlAgilityPack (>= 1.11) 371 | WebSharper (>= 9.1.1 < 9.2) 372 | 373 | GROUP testing 374 | STORAGE: NONE 375 | STRATEGY: MIN 376 | RESTRICTION: || (== net8.0) (== netcoreapp2.1) (== netcoreapp3.1) (== netstandard2.0) 377 | NUGET 378 | remote: https://api.nuget.org/v3/index.json 379 | FSharp.Core (9.0.300) 380 | HtmlAgilityPack (1.11) 381 | System.Net.Http (>= 4.3.2) 382 | System.Xml.XmlDocument (>= 4.3) 383 | System.Xml.XPath (>= 4.3) 384 | System.Xml.XPath.XmlDocument (>= 4.3) 385 | Microsoft.AspNetCore.Authentication.Abstractions (2.0) 386 | Microsoft.AspNetCore.Http.Abstractions (>= 2.0) 387 | Microsoft.Extensions.Logging.Abstractions (>= 2.0) 388 | Microsoft.Extensions.Options (>= 2.0) 389 | Microsoft.AspNetCore.Hosting.Abstractions (2.0) 390 | Microsoft.AspNetCore.Hosting.Server.Abstractions (>= 2.0) 391 | Microsoft.AspNetCore.Http.Abstractions (>= 2.0) 392 | Microsoft.Extensions.Configuration.Abstractions (>= 2.0) 393 | Microsoft.Extensions.DependencyInjection.Abstractions (>= 2.0) 394 | Microsoft.Extensions.FileProviders.Abstractions (>= 2.0) 395 | Microsoft.Extensions.Hosting.Abstractions (>= 2.0) 396 | Microsoft.Extensions.Logging.Abstractions (>= 2.0) 397 | Microsoft.AspNetCore.Hosting.Server.Abstractions (2.0) 398 | Microsoft.AspNetCore.Http.Features (>= 2.0) 399 | Microsoft.Extensions.Configuration.Abstractions (>= 2.0) 400 | Microsoft.AspNetCore.Http.Abstractions (2.0) 401 | Microsoft.AspNetCore.Http.Features (>= 2.0) 402 | System.Text.Encodings.Web (>= 4.4) 403 | Microsoft.AspNetCore.Http.Features (2.0) 404 | Microsoft.Extensions.Primitives (>= 2.0) 405 | Microsoft.AspNetCore.Mvc.Abstractions (2.0) 406 | Microsoft.AspNetCore.Routing.Abstractions (>= 2.0) 407 | Microsoft.Net.Http.Headers (>= 2.0) 408 | Microsoft.AspNetCore.Routing.Abstractions (2.0) 409 | Microsoft.AspNetCore.Http.Abstractions (>= 2.0) 410 | Microsoft.Extensions.Configuration.Abstractions (2.0) 411 | Microsoft.Extensions.Primitives (>= 2.0) 412 | Microsoft.Extensions.DependencyInjection.Abstractions (2.0) 413 | Microsoft.Extensions.FileProviders.Abstractions (2.0) 414 | Microsoft.Extensions.Primitives (>= 2.0) 415 | Microsoft.Extensions.Hosting.Abstractions (2.0) 416 | Microsoft.Extensions.Logging.Abstractions (2.0) 417 | Microsoft.Extensions.Options (2.0) 418 | Microsoft.Extensions.DependencyInjection.Abstractions (>= 2.0) 419 | Microsoft.Extensions.Primitives (>= 2.0) 420 | Microsoft.Extensions.Primitives (2.0) 421 | System.Runtime.CompilerServices.Unsafe (>= 4.4) 422 | Microsoft.Net.Http.Headers (2.0) 423 | Microsoft.Extensions.Primitives (>= 2.0) 424 | System.Buffers (>= 4.4) 425 | Microsoft.NETCore.Platforms (3.1) 426 | Microsoft.NETCore.Targets (1.1) 427 | Microsoft.Win32.SystemEvents (4.7) - restriction: || (== net8.0) (&& (== netcoreapp2.1) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0)) 428 | Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (== net8.0) (== netcoreapp2.1) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) 429 | runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 430 | runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 431 | runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 432 | runtime.native.System (4.3) 433 | Microsoft.NETCore.Platforms (>= 1.1) 434 | Microsoft.NETCore.Targets (>= 1.1) 435 | runtime.native.System.Net.Http (4.3) 436 | Microsoft.NETCore.Platforms (>= 1.1) 437 | Microsoft.NETCore.Targets (>= 1.1) 438 | runtime.native.System.Security.Cryptography.Apple (4.3) 439 | runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (>= 4.3) 440 | runtime.native.System.Security.Cryptography.OpenSsl (4.3) 441 | runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 442 | runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 443 | runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 444 | runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 445 | runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 446 | runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 447 | runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 448 | runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 449 | runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 450 | runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 451 | runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 452 | runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 453 | runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (4.3) 454 | runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 455 | runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 456 | runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 457 | runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 458 | runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3) 459 | System.Buffers (4.4) 460 | System.Collections (4.3) 461 | Microsoft.NETCore.Platforms (>= 1.1) 462 | Microsoft.NETCore.Targets (>= 1.1) 463 | System.Runtime (>= 4.3) 464 | System.Collections.Concurrent (4.3) 465 | System.Collections (>= 4.3) 466 | System.Diagnostics.Debug (>= 4.3) 467 | System.Diagnostics.Tracing (>= 4.3) 468 | System.Globalization (>= 4.3) 469 | System.Reflection (>= 4.3) 470 | System.Resources.ResourceManager (>= 4.3) 471 | System.Runtime (>= 4.3) 472 | System.Runtime.Extensions (>= 4.3) 473 | System.Threading (>= 4.3) 474 | System.Threading.Tasks (>= 4.3) 475 | System.Configuration.ConfigurationManager (4.7) 476 | System.Security.Cryptography.ProtectedData (>= 4.7) 477 | System.Security.Permissions (>= 4.7) 478 | System.Diagnostics.Debug (4.3) 479 | Microsoft.NETCore.Platforms (>= 1.1) 480 | Microsoft.NETCore.Targets (>= 1.1) 481 | System.Runtime (>= 4.3) 482 | System.Diagnostics.DiagnosticSource (4.3) 483 | System.Collections (>= 4.3) 484 | System.Diagnostics.Tracing (>= 4.3) 485 | System.Reflection (>= 4.3) 486 | System.Runtime (>= 4.3) 487 | System.Threading (>= 4.3) 488 | System.Diagnostics.Tracing (4.3) 489 | Microsoft.NETCore.Platforms (>= 1.1) 490 | Microsoft.NETCore.Targets (>= 1.1) 491 | System.Runtime (>= 4.3) 492 | System.Drawing.Common (4.7) - restriction: || (== net8.0) (&& (== netcoreapp2.1) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0)) 493 | Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (== net8.0) (== netcoreapp2.1) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) (&& (== netstandard2.0) (>= netcoreapp3.0)) 494 | Microsoft.Win32.SystemEvents (>= 4.7) - restriction: || (== net8.0) (== netcoreapp2.1) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) (&& (== netstandard2.0) (>= netcoreapp3.0)) 495 | System.Globalization (4.3) 496 | Microsoft.NETCore.Platforms (>= 1.1) 497 | Microsoft.NETCore.Targets (>= 1.1) 498 | System.Runtime (>= 4.3) 499 | System.Globalization.Calendars (4.3) 500 | Microsoft.NETCore.Platforms (>= 1.1) 501 | Microsoft.NETCore.Targets (>= 1.1) 502 | System.Globalization (>= 4.3) 503 | System.Runtime (>= 4.3) 504 | System.Globalization.Extensions (4.3) 505 | Microsoft.NETCore.Platforms (>= 1.1) 506 | System.Globalization (>= 4.3) 507 | System.Resources.ResourceManager (>= 4.3) 508 | System.Runtime (>= 4.3) 509 | System.Runtime.Extensions (>= 4.3) 510 | System.Runtime.InteropServices (>= 4.3) 511 | System.IO (4.3) 512 | Microsoft.NETCore.Platforms (>= 1.1) 513 | Microsoft.NETCore.Targets (>= 1.1) 514 | System.Runtime (>= 4.3) 515 | System.Text.Encoding (>= 4.3) 516 | System.Threading.Tasks (>= 4.3) 517 | System.IO.FileSystem (4.3) 518 | Microsoft.NETCore.Platforms (>= 1.1) 519 | Microsoft.NETCore.Targets (>= 1.1) 520 | System.IO (>= 4.3) 521 | System.IO.FileSystem.Primitives (>= 4.3) 522 | System.Runtime (>= 4.3) 523 | System.Runtime.Handles (>= 4.3) 524 | System.Text.Encoding (>= 4.3) 525 | System.Threading.Tasks (>= 4.3) 526 | System.IO.FileSystem.Primitives (4.3) 527 | System.Runtime (>= 4.3) 528 | System.Linq (4.3) 529 | System.Collections (>= 4.3) 530 | System.Diagnostics.Debug (>= 4.3) 531 | System.Resources.ResourceManager (>= 4.3) 532 | System.Runtime (>= 4.3) 533 | System.Runtime.Extensions (>= 4.3) 534 | System.Memory (4.5.3) - restriction: || (&& (== net8.0) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (== netstandard2.0) 535 | System.Buffers (>= 4.4) - restriction: || (&& (== net8.0) (>= monotouch)) (&& (== net8.0) (>= net461)) (&& (== net8.0) (< netcoreapp2.0)) (&& (== net8.0) (< netstandard1.1)) (&& (== net8.0) (< netstandard2.0)) (&& (== net8.0) (>= xamarinios)) (&& (== net8.0) (>= xamarinmac)) (&& (== net8.0) (>= xamarintvos)) (&& (== net8.0) (>= xamarinwatchos)) (&& (== netcoreapp2.1) (>= monotouch)) (&& (== netcoreapp2.1) (>= net461)) (&& (== netcoreapp2.1) (< netcoreapp2.0)) (&& (== netcoreapp2.1) (< netstandard1.1)) (&& (== netcoreapp2.1) (< netstandard2.0)) (&& (== netcoreapp2.1) (>= xamarinios)) (&& (== netcoreapp2.1) (>= xamarinmac)) (&& (== netcoreapp2.1) (>= xamarintvos)) (&& (== netcoreapp2.1) (>= xamarinwatchos)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0) 536 | System.Numerics.Vectors (>= 4.4) - restriction: || (&& (== net8.0) (>= net461)) (&& (== net8.0) (< netcoreapp2.0)) (&& (== netcoreapp2.1) (>= net461)) (&& (== netcoreapp2.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0) 537 | System.Runtime.CompilerServices.Unsafe (>= 4.5.2) - restriction: || (&& (== net8.0) (>= monotouch)) (&& (== net8.0) (>= net461)) (&& (== net8.0) (< netcoreapp2.0)) (&& (== net8.0) (< netcoreapp2.1)) (&& (== net8.0) (< netstandard1.1)) (&& (== net8.0) (< netstandard2.0)) (&& (== net8.0) (>= uap10.1)) (&& (== net8.0) (>= xamarinios)) (&& (== net8.0) (>= xamarinmac)) (&& (== net8.0) (>= xamarintvos)) (&& (== net8.0) (>= xamarinwatchos)) (&& (== netcoreapp2.1) (>= monotouch)) (&& (== netcoreapp2.1) (>= net461)) (&& (== netcoreapp2.1) (< netcoreapp2.0)) (&& (== netcoreapp2.1) (< netstandard1.1)) (&& (== netcoreapp2.1) (< netstandard2.0)) (&& (== netcoreapp2.1) (>= uap10.1)) (&& (== netcoreapp2.1) (>= xamarinios)) (&& (== netcoreapp2.1) (>= xamarinmac)) (&& (== netcoreapp2.1) (>= xamarintvos)) (&& (== netcoreapp2.1) (>= xamarinwatchos)) (&& (== netcoreapp3.1) (>= monotouch)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netstandard1.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (>= uap10.1)) (&& (== netcoreapp3.1) (>= xamarinios)) (&& (== netcoreapp3.1) (>= xamarinmac)) (&& (== netcoreapp3.1) (>= xamarintvos)) (&& (== netcoreapp3.1) (>= xamarinwatchos)) (== netstandard2.0) 538 | System.Net.Http (4.3.2) 539 | Microsoft.NETCore.Platforms (>= 1.1) 540 | runtime.native.System (>= 4.3) 541 | runtime.native.System.Net.Http (>= 4.3) 542 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 543 | System.Collections (>= 4.3) 544 | System.Diagnostics.Debug (>= 4.3) 545 | System.Diagnostics.DiagnosticSource (>= 4.3) 546 | System.Diagnostics.Tracing (>= 4.3) 547 | System.Globalization (>= 4.3) 548 | System.Globalization.Extensions (>= 4.3) 549 | System.IO (>= 4.3) 550 | System.IO.FileSystem (>= 4.3) 551 | System.Net.Primitives (>= 4.3) 552 | System.Resources.ResourceManager (>= 4.3) 553 | System.Runtime (>= 4.3) 554 | System.Runtime.Extensions (>= 4.3) 555 | System.Runtime.Handles (>= 4.3) 556 | System.Runtime.InteropServices (>= 4.3) 557 | System.Security.Cryptography.Algorithms (>= 4.3) 558 | System.Security.Cryptography.Encoding (>= 4.3) 559 | System.Security.Cryptography.OpenSsl (>= 4.3) 560 | System.Security.Cryptography.Primitives (>= 4.3) 561 | System.Security.Cryptography.X509Certificates (>= 4.3) 562 | System.Text.Encoding (>= 4.3) 563 | System.Threading (>= 4.3) 564 | System.Threading.Tasks (>= 4.3) 565 | System.Net.Primitives (4.3) 566 | Microsoft.NETCore.Platforms (>= 1.1) 567 | Microsoft.NETCore.Targets (>= 1.1) 568 | System.Runtime (>= 4.3) 569 | System.Runtime.Handles (>= 4.3) 570 | System.Numerics.Vectors (4.4) - restriction: || (&& (== net8.0) (>= net461)) (&& (== net8.0) (< netcoreapp2.0)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0) 571 | System.Reflection (4.3) 572 | Microsoft.NETCore.Platforms (>= 1.1) 573 | Microsoft.NETCore.Targets (>= 1.1) 574 | System.IO (>= 4.3) 575 | System.Reflection.Primitives (>= 4.3) 576 | System.Runtime (>= 4.3) 577 | System.Reflection.Emit.ILGeneration (4.7) - restriction: || (&& (== net8.0) (< netcoreapp2.0) (< netstandard2.1)) (&& (== net8.0) (< netstandard2.0)) (&& (== net8.0) (< portable-net45+wp8)) (&& (== net8.0) (>= uap10.1)) (&& (== netcoreapp2.1) (< netcoreapp2.0)) (&& (== netcoreapp2.1) (< netstandard2.0)) (&& (== netcoreapp2.1) (< portable-net45+wp8)) (&& (== netcoreapp2.1) (>= uap10.1)) (&& (== netcoreapp3.1) (< netcoreapp2.0) (< netstandard2.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (< portable-net45+wp8)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) 578 | System.Reflection.Emit.Lightweight (4.7) 579 | System.Reflection.Emit.ILGeneration (>= 4.7) - restriction: || (&& (== net8.0) (< netcoreapp2.0) (< netstandard2.1)) (&& (== net8.0) (< netstandard2.0)) (&& (== net8.0) (< portable-net45+wp8)) (&& (== net8.0) (>= uap10.1)) (&& (== netcoreapp2.1) (< netcoreapp2.0)) (&& (== netcoreapp2.1) (< netstandard2.0)) (&& (== netcoreapp2.1) (< portable-net45+wp8)) (&& (== netcoreapp2.1) (>= uap10.1)) (&& (== netcoreapp3.1) (< netcoreapp2.0) (< netstandard2.1)) (&& (== netcoreapp3.1) (< netstandard2.0)) (&& (== netcoreapp3.1) (< portable-net45+wp8)) (&& (== netcoreapp3.1) (>= uap10.1)) (== netstandard2.0) 580 | System.Reflection.Primitives (4.3) 581 | Microsoft.NETCore.Platforms (>= 1.1) 582 | Microsoft.NETCore.Targets (>= 1.1) 583 | System.Runtime (>= 4.3) 584 | System.Resources.ResourceManager (4.3) 585 | Microsoft.NETCore.Platforms (>= 1.1) 586 | Microsoft.NETCore.Targets (>= 1.1) 587 | System.Globalization (>= 4.3) 588 | System.Reflection (>= 4.3) 589 | System.Runtime (>= 4.3) 590 | System.Runtime (4.3) 591 | Microsoft.NETCore.Platforms (>= 1.1) 592 | Microsoft.NETCore.Targets (>= 1.1) 593 | System.Runtime.CompilerServices.Unsafe (4.5.2) 594 | System.Runtime.Extensions (4.3) 595 | Microsoft.NETCore.Platforms (>= 1.1) 596 | Microsoft.NETCore.Targets (>= 1.1) 597 | System.Runtime (>= 4.3) 598 | System.Runtime.Handles (4.3) 599 | Microsoft.NETCore.Platforms (>= 1.1) 600 | Microsoft.NETCore.Targets (>= 1.1) 601 | System.Runtime (>= 4.3) 602 | System.Runtime.InteropServices (4.3) 603 | Microsoft.NETCore.Platforms (>= 1.1) 604 | Microsoft.NETCore.Targets (>= 1.1) 605 | System.Reflection (>= 4.3) 606 | System.Reflection.Primitives (>= 4.3) 607 | System.Runtime (>= 4.3) 608 | System.Runtime.Handles (>= 4.3) 609 | System.Runtime.Numerics (4.3) 610 | System.Globalization (>= 4.3) 611 | System.Resources.ResourceManager (>= 4.3) 612 | System.Runtime (>= 4.3) 613 | System.Runtime.Extensions (>= 4.3) 614 | System.Security.AccessControl (4.7) 615 | Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (== net8.0) (== netcoreapp2.1) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) 616 | System.Security.Principal.Windows (>= 4.7) 617 | System.Security.Cryptography.Algorithms (4.3) 618 | Microsoft.NETCore.Platforms (>= 1.1) 619 | runtime.native.System.Security.Cryptography.Apple (>= 4.3) 620 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 621 | System.Collections (>= 4.3) 622 | System.IO (>= 4.3) 623 | System.Resources.ResourceManager (>= 4.3) 624 | System.Runtime (>= 4.3) 625 | System.Runtime.Extensions (>= 4.3) 626 | System.Runtime.Handles (>= 4.3) 627 | System.Runtime.InteropServices (>= 4.3) 628 | System.Runtime.Numerics (>= 4.3) 629 | System.Security.Cryptography.Encoding (>= 4.3) 630 | System.Security.Cryptography.Primitives (>= 4.3) 631 | System.Text.Encoding (>= 4.3) 632 | System.Security.Cryptography.Cng (4.3) 633 | Microsoft.NETCore.Platforms (>= 1.1) 634 | System.IO (>= 4.3) 635 | System.Resources.ResourceManager (>= 4.3) 636 | System.Runtime (>= 4.3) 637 | System.Runtime.Extensions (>= 4.3) 638 | System.Runtime.Handles (>= 4.3) 639 | System.Runtime.InteropServices (>= 4.3) 640 | System.Security.Cryptography.Algorithms (>= 4.3) 641 | System.Security.Cryptography.Encoding (>= 4.3) 642 | System.Security.Cryptography.Primitives (>= 4.3) 643 | System.Text.Encoding (>= 4.3) 644 | System.Security.Cryptography.Csp (4.3) 645 | Microsoft.NETCore.Platforms (>= 1.1) 646 | System.IO (>= 4.3) 647 | System.Reflection (>= 4.3) 648 | System.Resources.ResourceManager (>= 4.3) 649 | System.Runtime (>= 4.3) 650 | System.Runtime.Extensions (>= 4.3) 651 | System.Runtime.Handles (>= 4.3) 652 | System.Runtime.InteropServices (>= 4.3) 653 | System.Security.Cryptography.Algorithms (>= 4.3) 654 | System.Security.Cryptography.Encoding (>= 4.3) 655 | System.Security.Cryptography.Primitives (>= 4.3) 656 | System.Text.Encoding (>= 4.3) 657 | System.Threading (>= 4.3) 658 | System.Security.Cryptography.Encoding (4.3) 659 | Microsoft.NETCore.Platforms (>= 1.1) 660 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 661 | System.Collections (>= 4.3) 662 | System.Collections.Concurrent (>= 4.3) 663 | System.Linq (>= 4.3) 664 | System.Resources.ResourceManager (>= 4.3) 665 | System.Runtime (>= 4.3) 666 | System.Runtime.Extensions (>= 4.3) 667 | System.Runtime.Handles (>= 4.3) 668 | System.Runtime.InteropServices (>= 4.3) 669 | System.Security.Cryptography.Primitives (>= 4.3) 670 | System.Text.Encoding (>= 4.3) 671 | System.Security.Cryptography.OpenSsl (4.3) 672 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 673 | System.Collections (>= 4.3) 674 | System.IO (>= 4.3) 675 | System.Resources.ResourceManager (>= 4.3) 676 | System.Runtime (>= 4.3) 677 | System.Runtime.Extensions (>= 4.3) 678 | System.Runtime.Handles (>= 4.3) 679 | System.Runtime.InteropServices (>= 4.3) 680 | System.Runtime.Numerics (>= 4.3) 681 | System.Security.Cryptography.Algorithms (>= 4.3) 682 | System.Security.Cryptography.Encoding (>= 4.3) 683 | System.Security.Cryptography.Primitives (>= 4.3) 684 | System.Text.Encoding (>= 4.3) 685 | System.Security.Cryptography.Primitives (4.3) 686 | System.Diagnostics.Debug (>= 4.3) 687 | System.Globalization (>= 4.3) 688 | System.IO (>= 4.3) 689 | System.Resources.ResourceManager (>= 4.3) 690 | System.Runtime (>= 4.3) 691 | System.Threading (>= 4.3) 692 | System.Threading.Tasks (>= 4.3) 693 | System.Security.Cryptography.ProtectedData (4.7) 694 | System.Memory (>= 4.5.3) - restriction: || (&& (== net8.0) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (== netstandard2.0) 695 | System.Security.Cryptography.X509Certificates (4.3) 696 | Microsoft.NETCore.Platforms (>= 1.1) 697 | runtime.native.System (>= 4.3) 698 | runtime.native.System.Net.Http (>= 4.3) 699 | runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3) 700 | System.Collections (>= 4.3) 701 | System.Diagnostics.Debug (>= 4.3) 702 | System.Globalization (>= 4.3) 703 | System.Globalization.Calendars (>= 4.3) 704 | System.IO (>= 4.3) 705 | System.IO.FileSystem (>= 4.3) 706 | System.IO.FileSystem.Primitives (>= 4.3) 707 | System.Resources.ResourceManager (>= 4.3) 708 | System.Runtime (>= 4.3) 709 | System.Runtime.Extensions (>= 4.3) 710 | System.Runtime.Handles (>= 4.3) 711 | System.Runtime.InteropServices (>= 4.3) 712 | System.Runtime.Numerics (>= 4.3) 713 | System.Security.Cryptography.Algorithms (>= 4.3) 714 | System.Security.Cryptography.Cng (>= 4.3) 715 | System.Security.Cryptography.Csp (>= 4.3) 716 | System.Security.Cryptography.Encoding (>= 4.3) 717 | System.Security.Cryptography.OpenSsl (>= 4.3) 718 | System.Security.Cryptography.Primitives (>= 4.3) 719 | System.Text.Encoding (>= 4.3) 720 | System.Threading (>= 4.3) 721 | System.Security.Permissions (4.7) 722 | System.Security.AccessControl (>= 4.7) 723 | System.Windows.Extensions (>= 4.7) - restriction: || (== net8.0) (&& (== netcoreapp2.1) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0)) 724 | System.Security.Principal.Windows (4.7) 725 | Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (&& (== net8.0) (< netcoreapp2.1)) (&& (== net8.0) (< netcoreapp3.0)) (== netcoreapp2.1) (&& (== netcoreapp3.1) (< netcoreapp2.1)) (&& (== netcoreapp3.1) (< netcoreapp3.0)) (&& (== netstandard2.0) (>= netcoreapp2.0)) (&& (== netstandard2.0) (>= netcoreapp2.1)) 726 | System.Text.Encoding (4.3) 727 | Microsoft.NETCore.Platforms (>= 1.1) 728 | Microsoft.NETCore.Targets (>= 1.1) 729 | System.Runtime (>= 4.3) 730 | System.Text.Encoding.Extensions (4.3) 731 | Microsoft.NETCore.Platforms (>= 1.1) 732 | Microsoft.NETCore.Targets (>= 1.1) 733 | System.Runtime (>= 4.3) 734 | System.Text.Encoding (>= 4.3) 735 | System.Text.Encodings.Web (4.4) 736 | System.Text.RegularExpressions (4.3) 737 | System.Collections (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 738 | System.Globalization (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 739 | System.Resources.ResourceManager (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 740 | System.Runtime (>= 4.3) 741 | System.Runtime.Extensions (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 742 | System.Threading (>= 4.3) - restriction: || (&& (== net8.0) (< netcoreapp1.1)) (&& (== netcoreapp2.1) (< netcoreapp1.1)) (&& (== netcoreapp3.1) (< netcoreapp1.1)) (== netstandard2.0) 743 | System.Threading (4.3) 744 | System.Runtime (>= 4.3) 745 | System.Threading.Tasks (>= 4.3) 746 | System.Threading.Tasks (4.3) 747 | Microsoft.NETCore.Platforms (>= 1.1) 748 | Microsoft.NETCore.Targets (>= 1.1) 749 | System.Runtime (>= 4.3) 750 | System.Threading.Tasks.Extensions (4.3) 751 | System.Collections (>= 4.3) 752 | System.Runtime (>= 4.3) 753 | System.Threading.Tasks (>= 4.3) 754 | System.Windows.Extensions (4.7) - restriction: || (== net8.0) (&& (== netcoreapp2.1) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0)) 755 | System.Drawing.Common (>= 4.7) - restriction: || (== net8.0) (&& (== netcoreapp2.1) (>= netcoreapp3.0)) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp3.0)) 756 | System.Xml.ReaderWriter (4.3) 757 | System.Collections (>= 4.3) 758 | System.Diagnostics.Debug (>= 4.3) 759 | System.Globalization (>= 4.3) 760 | System.IO (>= 4.3) 761 | System.IO.FileSystem (>= 4.3) 762 | System.IO.FileSystem.Primitives (>= 4.3) 763 | System.Resources.ResourceManager (>= 4.3) 764 | System.Runtime (>= 4.3) 765 | System.Runtime.Extensions (>= 4.3) 766 | System.Runtime.InteropServices (>= 4.3) 767 | System.Text.Encoding (>= 4.3) 768 | System.Text.Encoding.Extensions (>= 4.3) 769 | System.Text.RegularExpressions (>= 4.3) 770 | System.Threading.Tasks (>= 4.3) 771 | System.Threading.Tasks.Extensions (>= 4.3) 772 | System.Xml.XmlDocument (4.3) 773 | System.Collections (>= 4.3) 774 | System.Diagnostics.Debug (>= 4.3) 775 | System.Globalization (>= 4.3) 776 | System.IO (>= 4.3) 777 | System.Resources.ResourceManager (>= 4.3) 778 | System.Runtime (>= 4.3) 779 | System.Runtime.Extensions (>= 4.3) 780 | System.Text.Encoding (>= 4.3) 781 | System.Threading (>= 4.3) 782 | System.Xml.ReaderWriter (>= 4.3) 783 | System.Xml.XPath (4.3) 784 | System.Collections (>= 4.3) 785 | System.Diagnostics.Debug (>= 4.3) 786 | System.Globalization (>= 4.3) 787 | System.IO (>= 4.3) 788 | System.Resources.ResourceManager (>= 4.3) 789 | System.Runtime (>= 4.3) 790 | System.Runtime.Extensions (>= 4.3) 791 | System.Threading (>= 4.3) 792 | System.Xml.ReaderWriter (>= 4.3) 793 | System.Xml.XPath.XmlDocument (4.3) 794 | System.Collections (>= 4.3) 795 | System.Globalization (>= 4.3) 796 | System.IO (>= 4.3) 797 | System.Resources.ResourceManager (>= 4.3) 798 | System.Runtime (>= 4.3) 799 | System.Runtime.Extensions (>= 4.3) 800 | System.Threading (>= 4.3) 801 | System.Xml.ReaderWriter (>= 4.3) 802 | System.Xml.XmlDocument (>= 4.3) 803 | System.Xml.XPath (>= 4.3) 804 | remote: https://nuget.pkg.github.com/dotnet-websharper/index.json 805 | WebSharper (9.1.1.557) 806 | FSharp.Core (>= 6.0) 807 | System.Reflection.Emit.Lightweight (>= 4.7) 808 | WebSharper.AspNetCore (9.1.1.557) 809 | Microsoft.AspNetCore.Authentication.Abstractions (>= 2.0) 810 | Microsoft.AspNetCore.Hosting.Abstractions (>= 2.0) 811 | Microsoft.AspNetCore.Mvc.Abstractions (>= 2.0) 812 | System.Configuration.ConfigurationManager (>= 4.7) 813 | WebSharper (9.1.1.557) 814 | WebSharper.FSharp (9.1.1.557) 815 | WebSharper (9.1.1.557) 816 | WebSharper.UI (9.1.1.557) 817 | HtmlAgilityPack (>= 1.11) 818 | WebSharper (>= 9.1.1 < 9.2) 819 | 820 | GROUP wsbuild 821 | 822 | GIT 823 | remote: https://github.com/dotnet-websharper/build-script 824 | (a7b506f18c67bb036a16a9adee507c44aa9e5bbc) -------------------------------------------------------------------------------- /tools/WebSharper.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dotnet-websharper/forms/85cf5c76d5ebf481df8100d67495c0cb9022e147/tools/WebSharper.snk --------------------------------------------------------------------------------