├── .config └── dotnet-tools.json ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── workflows │ ├── ci.yml │ └── publish.yml ├── .gitignore ├── .npmrc ├── .paket └── Paket.Restore.targets ├── .vscode └── settings.json ├── Directory.Build.props ├── LICENSE.md ├── NuGet.Config ├── README.md ├── babel.config.json ├── docs ├── _partials │ └── footer.jsx ├── index.md ├── release_notes.md ├── scss │ └── fable-font.scss ├── static │ ├── fonts │ │ └── fable-font │ │ │ ├── fable-font.eot │ │ │ ├── fable-font.svg │ │ │ ├── fable-font.ttf │ │ │ └── fable-font.woff │ └── img │ │ ├── hmr_demo.gif │ │ └── logo.png ├── style.scss └── v1_and_v2.md ├── global.json ├── hmr.sln ├── nacara.config.json ├── package-lock.json ├── package.json ├── paket.dependencies ├── paket.lock ├── paket.references ├── scripts ├── release-core.js └── release-nuget.js ├── src ├── Bundler.fs ├── CHANGELOG.md ├── Fable.Elmish.HMR.fsproj ├── HMR.Parcel.fs ├── HMR.Vite.fs ├── HMR.Webpack.fs ├── common.fs ├── hmr.fs └── paket.references └── tests ├── App.fs ├── Router.fs ├── Tests.fsproj ├── index.html ├── paket.references ├── parcel └── index.html └── webpack ├── index.html └── webpack.config.js /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "paket": { 6 | "version": "5.257.0", 7 | "commands": [ 8 | "paket" 9 | ] 10 | }, 11 | "fable": { 12 | "version": "3.4.9", 13 | "commands": [ 14 | "fable" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ### Contributor guidelines 2 | 3 | First of all - thanks for taking the time to contribute! 4 | 5 | With that in mind, elmish is a young project and as such while we welcome the contributions from non-member there are certain things we'd like to get more right than fast. To make everyone's experience as enjoyable as possible please keep the following things in mind: 6 | 7 | * Unless it's a trivial fix, consider opening an issue first to discuss it with the team. 8 | * If you are just looking for something to take on, check the *help wanted" labeled items 9 | 10 | 11 | ### Opening an Issue 12 | 13 | * Before you do, please check if there's a known work around, existing issue or already a work in progress to address it. 14 | * If you just don't know how to do something consider asking in the gitter, there are always helpful people around. 15 | * Provide as much info as possible - follow the template if it makes sense, attach screenshots or logs if applicable. 16 | 17 | 18 | ### Pull requests 19 | 20 | To make it easier to review the changes and get you code into the repo keep the commit history clean: 21 | 22 | * [rebase your pulls](https://coderwall.com/p/tnoiug/rebase-by-default-when-doing-git-pull) on the latest from repo 23 | * only push the commits relevant to the PR 24 | 25 | If adding a feature, also consider adding a sample (or link to one). 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | Please provide a succinct description of your issue. 4 | 5 | ### Repro code 6 | 7 | Please provide the F# code to reproduce the problem. 8 | Ideally, it should be possibe to easily turn this code into a unit test. 9 | 10 | ### Expected and actual results 11 | 12 | Please provide the expected and actual results. 13 | 14 | ### Related information 15 | 16 | * elmish version: 17 | * fable-compiler version: 18 | * fable-core version: 19 | * Operating system: 20 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | branches: [ master ] 5 | workflow_dispatch: 6 | jobs: 7 | build: 8 | runs-on: ${{ matrix.os }} 9 | matrix: 10 | os: [ ubuntu-latest, macOS-latest, windows-latest ] 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: actions/setup-dotnet@v1 14 | with: 15 | dotnet-version: '6.0.x' 16 | - name: Setup workspace 17 | run: dotnet tool restore 18 | - name: Build package 19 | run: dotnet build src 20 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | on: 3 | push: 4 | branches: 5 | - master 6 | workflow_dispatch: 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-dotnet@v1 13 | with: 14 | dotnet-version: '6.0.x' 15 | - uses: actions/setup-node@v2 16 | with: 17 | node-version: '16' 18 | - name: Install and use custom npm version 19 | run: npm i -g npm@7 20 | - name: Setup workspace 21 | run: npm install 22 | - name: Build site 23 | run: npm run docs:build 24 | - name: Deploy site 25 | uses: peaceiris/actions-gh-pages@v3 26 | with: 27 | personal_token: ${{ secrets.GITHUB_TOKEN }} 28 | publish_dir: ./docs_deploy 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # node.js 6 | # 7 | **/node_modules/ 8 | **/npm/ 9 | npm-debug.log 10 | 11 | # F# 12 | .fake/ 13 | packages/ 14 | build/ 15 | obj 16 | bin 17 | out 18 | 19 | # git 20 | *.orig 21 | 22 | .vs 23 | 24 | temp 25 | paket-files 26 | 27 | .ionide/ 28 | 29 | .nacara/ 30 | doc_deploy/ 31 | fableBuild/ 32 | tests/parcel/dist/ 33 | .parcel-cache/ 34 | dist/ 35 | docs_deploy/ 36 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.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 | 241 | 242 | %(PaketReferencesFileLinesInfo.PackageVersion) 243 | All 244 | runtime 245 | runtime 246 | true 247 | true 248 | 249 | 250 | 251 | 252 | $(PaketIntermediateOutputPath)/$(MSBuildProjectFile).paket.clitools 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[0]) 262 | $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[1]) 263 | 264 | 265 | %(PaketCliToolFileLinesInfo.PackageVersion) 266 | 267 | 268 | 269 | 273 | 274 | 275 | 276 | 277 | 278 | false 279 | 280 | 281 | 282 | 283 | 284 | <_NuspecFilesNewLocation Include="$(PaketIntermediateOutputPath)\$(Configuration)\*.nuspec"/> 285 | 286 | 287 | 288 | 289 | 290 | $(MSBuildProjectDirectory)/$(MSBuildProjectFile) 291 | true 292 | false 293 | true 294 | false 295 | true 296 | false 297 | true 298 | false 299 | true 300 | $(PaketIntermediateOutputPath)\$(Configuration) 301 | $(PaketIntermediateOutputPath) 302 | 303 | 304 | 305 | <_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.$(PackageVersion.Split(`+`)[0]).nuspec"/> 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 363 | 364 | 407 | 408 | 450 | 451 | 492 | 493 | 494 | 495 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "search.exclude": { 3 | "**/node_modules": true, 4 | "**/bower_components": true, 5 | "**/packages": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 5 | 6 | 7 | 8 | true 9 | https://github.com/elmish/hmr.git 10 | https://github.com/elmish/hmr 11 | README.md 12 | LICENSE.md 13 | Hot Module Replacement for Elmish apps 14 | fable;elmish;fsharp;hmr 15 | Maxime Mangel 16 | 17 | 18 | 19 | true 20 | true 21 | true 22 | true 23 | snupkg 24 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2016 elmish contributors 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Elmish-HMR: [Hot Module Replacement](https://webpack.js.org/concepts/hot-module-replacement/) integration for [elmish](https://github.com/fable-compiler/elmish) applications. 2 | ======= 3 | 4 | [![NuGet version](https://badge.fury.io/nu/Fable.Elmish.HMR.svg)](https://badge.fury.io/nu/Fable.Elmish.HMR) 5 | 6 | For more information see [the docs](https://elmish.github.io/hmr). 7 | 8 | ## Installation 9 | 10 | ```sh 11 | paket add nuget Fable.Elmish.HMR 12 | ``` 13 | 14 | ## Demo 15 | 16 | ![hmr demo](https://raw.githubusercontent.com/elmish/hmr/master/docs/static/img/hmr_demo.gif) 17 | 18 | ## Development 19 | 20 | This repository use NPM scripts to control the build system here is a list of the main scripts available: 21 | 22 | | Script | Description | 23 | |---|---| 24 | | `npm run tests:watch` | To use when working on the tests suits | 25 | | `npm run docs:watch` | To use when working on the documentation, hosted on [http://localhost:8080](http://localhost:8080) | 26 | | `npm run docs:publish` | Build a new version of the documentation and publish it to Github Pages | 27 | | `npm run release` | Build a new version of the packages if needed and release it | 28 | -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-react" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /docs/_partials/footer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const SitemapSection = ({ title, children }) => ( 4 |
5 |
6 | {title} 7 |
8 | 11 |
12 | ) 13 | 14 | const SitemapSectionItem = ({ text, icon, url }) => ( 15 |
  • 16 | 17 | 18 | 19 | 20 | 21 | {text} 22 | 23 | 24 |
  • 25 | ) 26 | 27 | const CopyrightScript = () => ( 28 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/paket.references: -------------------------------------------------------------------------------- 1 | group Tests 2 | Fable.Core 3 | Fable.Elmish 4 | Fable.Elmish.Browser 5 | Fable.Elmish.React 6 | Fable.Promise 7 | Feliz -------------------------------------------------------------------------------- /tests/parcel/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Elmish HMR - demo 5 | 6 | 7 | 8 | 9 | 10 |
    11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/webpack/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Elmish HMR - demo 5 | 6 | 7 | 8 | 9 | 10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | import HtmlWebpackPlugin from 'html-webpack-plugin'; 2 | import {fileURLToPath} from 'node:url'; 3 | import path from 'node:path'; 4 | 5 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 6 | 7 | function resolve(filePath) { 8 | return path.join(__dirname, filePath) 9 | } 10 | 11 | export default (_env, options) => { 12 | 13 | var isDevelopment = options.mode === "development"; 14 | 15 | return { 16 | // In development, bundle styles together with the code so they can also 17 | // trigger hot reloads. In production, put them in a separate CSS file. 18 | entry: 19 | { 20 | app: "./../fableBuild/App.js" 21 | }, 22 | // Add a hash to the output file name in production 23 | // to prevent browser caching if code changes 24 | output: { 25 | path: resolve("./temp"), 26 | filename: "app.js" 27 | }, 28 | devtool: isDevelopment ? 'eval-source-map' : false, 29 | watchOptions: { 30 | ignored: /node_modules/, 31 | }, 32 | plugins: 33 | [ 34 | // In production, we only need the bundle file 35 | isDevelopment && new HtmlWebpackPlugin({ 36 | filename: "./index.html", 37 | template: "./index.html" 38 | }) 39 | ].filter(Boolean), 40 | // Configuration for webpack-dev-server 41 | devServer: { 42 | hot: true 43 | } 44 | } 45 | } 46 | --------------------------------------------------------------------------------