From c5ba43aa3e24804669078a246929858d97172db6 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Thu, 22 Sep 2022 16:57:21 +0200 Subject: [PATCH 1/2] Remove templates --- jscomp/bsb/Docs.md | 23 - jscomp/bsb/bsb_templates.ml | 1883 -------------- jscomp/bsb/bsb_templates.mli | 6 - jscomp/bsb/bsb_theme_init.ml | 136 - jscomp/bsb/bsb_theme_init.mli | 27 - jscomp/bsb/templates/basic-reason/.gitignore | 6 - jscomp/bsb/templates/basic-reason/README.md | 24 - .../bsb/templates/basic-reason/bsconfig.json | 21 - .../bsb/templates/basic-reason/package.json | 17 - .../bsb/templates/basic-reason/src/Demo.res | 1 - jscomp/bsb/templates/basic/.gitignore | 27 - jscomp/bsb/templates/basic/README.md | 13 - jscomp/bsb/templates/basic/bsconfig.json | 13 - jscomp/bsb/templates/basic/package.json | 17 - jscomp/bsb/templates/basic/src/Demo.res | 2 - jscomp/bsb/templates/generator/.gitignore | 27 - jscomp/bsb/templates/generator/README.md | 16 - jscomp/bsb/templates/generator/bsconfig.json | 18 - jscomp/bsb/templates/generator/package.json | 17 - jscomp/bsb/templates/generator/src/demo.ml | 3 - .../bsb/templates/generator/src/test.cpp.ml | 10 - jscomp/bsb/templates/minimal/.gitignore | 6 - jscomp/bsb/templates/minimal/README.md | 2 - jscomp/bsb/templates/minimal/bsconfig.json | 7 - jscomp/bsb/templates/minimal/package.json | 17 - jscomp/bsb/templates/minimal/src/main.ml | 0 jscomp/bsb/templates/node/.gitignore | 27 - jscomp/bsb/templates/node/README.md | 16 - jscomp/bsb/templates/node/bsconfig.json | 15 - jscomp/bsb/templates/node/package.json | 17 - jscomp/bsb/templates/node/src/demo.ml | 3 - jscomp/bsb/templates/react-hooks/.gitignore | 7 - jscomp/bsb/templates/react-hooks/README.md | 61 - .../react-hooks/UNUSED_webpack.config.js | 14 - .../bsb/templates/react-hooks/bsconfig.json | 21 - jscomp/bsb/templates/react-hooks/index.html | 22 - .../react-hooks/indexProduction.html | 10 - jscomp/bsb/templates/react-hooks/package.json | 27 - .../src/BlinkingGreeting/BlinkingGreeting.res | 20 - .../react-hooks/src/ExampleStyles.res | 44 - .../FetchedDogPictures/FetchedDogPictures.res | 70 - .../bsb/templates/react-hooks/src/Index.res | 40 - .../ReasonUsingJSUsingReason/ReactJSCard.js | 31 - .../ReasonReactCard.res | 8 - .../ReasonUsingJSUsingReason.res | 10 - .../ReducerFromReactJSDocs.res | 45 - jscomp/bsb/templates/react-hooks/watcher.js | 46 - jscomp/bsb/templates/react-starter/.gitignore | 7 - jscomp/bsb/templates/react-starter/README.md | 26 - .../bsb/templates/react-starter/bsconfig.json | 21 - .../bsb/templates/react-starter/package.json | 34 - .../bsb/templates/react-starter/src/App.res | 27 - .../bsb/templates/react-starter/src/Index.res | 3 - .../bsb/templates/react-starter/src/index.css | 14 - .../templates/react-starter/src/index.html | 11 - .../templates/react-starter/webpack.config.js | 35 - jscomp/bsb/templates/tea/README.md | 20 - jscomp/bsb/templates/tea/bsconfig.json | 16 - jscomp/bsb/templates/tea/index.html | 20 - jscomp/bsb/templates/tea/loader.js | 484 ---- jscomp/bsb/templates/tea/package.json | 20 - jscomp/bsb/templates/tea/src/demo.ml | 62 - jscomp/bsb/templates/tea/src/main.ml | 9 - jscomp/bsb/templates/tea/watcher.js | 27 - jscomp/main/rescript_main.ml | 21 - lib/4.06.1/rescript.ml | 2178 ----------------- lib/4.06.1/rescript.ml.d | 6 - scripts/dedupe.js | 2 +- scripts/format.js | 2 +- scripts/pack.js | 107 - scripts/release.js | 2 - 71 files changed, 2 insertions(+), 6045 deletions(-) delete mode 100644 jscomp/bsb/Docs.md delete mode 100644 jscomp/bsb/bsb_templates.ml delete mode 100644 jscomp/bsb/bsb_templates.mli delete mode 100644 jscomp/bsb/bsb_theme_init.ml delete mode 100644 jscomp/bsb/bsb_theme_init.mli delete mode 100644 jscomp/bsb/templates/basic-reason/.gitignore delete mode 100644 jscomp/bsb/templates/basic-reason/README.md delete mode 100644 jscomp/bsb/templates/basic-reason/bsconfig.json delete mode 100644 jscomp/bsb/templates/basic-reason/package.json delete mode 100644 jscomp/bsb/templates/basic-reason/src/Demo.res delete mode 100644 jscomp/bsb/templates/basic/.gitignore delete mode 100644 jscomp/bsb/templates/basic/README.md delete mode 100644 jscomp/bsb/templates/basic/bsconfig.json delete mode 100644 jscomp/bsb/templates/basic/package.json delete mode 100644 jscomp/bsb/templates/basic/src/Demo.res delete mode 100644 jscomp/bsb/templates/generator/.gitignore delete mode 100644 jscomp/bsb/templates/generator/README.md delete mode 100644 jscomp/bsb/templates/generator/bsconfig.json delete mode 100644 jscomp/bsb/templates/generator/package.json delete mode 100644 jscomp/bsb/templates/generator/src/demo.ml delete mode 100644 jscomp/bsb/templates/generator/src/test.cpp.ml delete mode 100644 jscomp/bsb/templates/minimal/.gitignore delete mode 100644 jscomp/bsb/templates/minimal/README.md delete mode 100644 jscomp/bsb/templates/minimal/bsconfig.json delete mode 100644 jscomp/bsb/templates/minimal/package.json delete mode 100644 jscomp/bsb/templates/minimal/src/main.ml delete mode 100644 jscomp/bsb/templates/node/.gitignore delete mode 100644 jscomp/bsb/templates/node/README.md delete mode 100644 jscomp/bsb/templates/node/bsconfig.json delete mode 100644 jscomp/bsb/templates/node/package.json delete mode 100644 jscomp/bsb/templates/node/src/demo.ml delete mode 100644 jscomp/bsb/templates/react-hooks/.gitignore delete mode 100644 jscomp/bsb/templates/react-hooks/README.md delete mode 100644 jscomp/bsb/templates/react-hooks/UNUSED_webpack.config.js delete mode 100644 jscomp/bsb/templates/react-hooks/bsconfig.json delete mode 100644 jscomp/bsb/templates/react-hooks/index.html delete mode 100644 jscomp/bsb/templates/react-hooks/indexProduction.html delete mode 100644 jscomp/bsb/templates/react-hooks/package.json delete mode 100644 jscomp/bsb/templates/react-hooks/src/BlinkingGreeting/BlinkingGreeting.res delete mode 100644 jscomp/bsb/templates/react-hooks/src/ExampleStyles.res delete mode 100644 jscomp/bsb/templates/react-hooks/src/FetchedDogPictures/FetchedDogPictures.res delete mode 100644 jscomp/bsb/templates/react-hooks/src/Index.res delete mode 100644 jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReactJSCard.js delete mode 100644 jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReasonReactCard.res delete mode 100644 jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReasonUsingJSUsingReason.res delete mode 100644 jscomp/bsb/templates/react-hooks/src/ReducerFromReactJSDocs/ReducerFromReactJSDocs.res delete mode 100644 jscomp/bsb/templates/react-hooks/watcher.js delete mode 100644 jscomp/bsb/templates/react-starter/.gitignore delete mode 100644 jscomp/bsb/templates/react-starter/README.md delete mode 100644 jscomp/bsb/templates/react-starter/bsconfig.json delete mode 100644 jscomp/bsb/templates/react-starter/package.json delete mode 100644 jscomp/bsb/templates/react-starter/src/App.res delete mode 100644 jscomp/bsb/templates/react-starter/src/Index.res delete mode 100644 jscomp/bsb/templates/react-starter/src/index.css delete mode 100644 jscomp/bsb/templates/react-starter/src/index.html delete mode 100644 jscomp/bsb/templates/react-starter/webpack.config.js delete mode 100644 jscomp/bsb/templates/tea/README.md delete mode 100644 jscomp/bsb/templates/tea/bsconfig.json delete mode 100644 jscomp/bsb/templates/tea/index.html delete mode 100644 jscomp/bsb/templates/tea/loader.js delete mode 100644 jscomp/bsb/templates/tea/package.json delete mode 100644 jscomp/bsb/templates/tea/src/demo.ml delete mode 100644 jscomp/bsb/templates/tea/src/main.ml delete mode 100644 jscomp/bsb/templates/tea/watcher.js delete mode 100644 scripts/pack.js diff --git a/jscomp/bsb/Docs.md b/jscomp/bsb/Docs.md deleted file mode 100644 index abf2188c34..0000000000 --- a/jscomp/bsb/Docs.md +++ /dev/null @@ -1,23 +0,0 @@ -# BSB - -Bsb is ReScript's build system. User-facing documentations are [here](https://rescript-lang.org/docs/manual/latest/build-overview). - -This directory hosts its implementation. It reads into `bsconfig.json`, uses some BS/OCaml/Reason-specific logic, and generates a [ninja](https://ninja-build.org) build file then calls `ninja` on it. So much of the incremental build and perf work is delegated to Ninja. - -There's a `templates/` subdirectory. It's the thing shown when you do `bsb -themes`. To generate a template for the user, it basically picks the chosen template from `templates/` and copy pastes it into the destined user directory while substituting some strings in those templates, like `${rescript:proj-version}` in the `package.json`s. - -## Add/edit a template - -The content of `templates` is packed into `bsb_templates.ml` automatically when running [pack.js](../../scripts/pack.js). - -When adding/editing a template the script needs to be rerun to update the relevant parts in `bsb_templates.ml`. - -## Testing a template locally - -Do the following setup steps to build the compiler: [build ocaml compiler](https://github.com/rescript-lang/rescript-compiler/blob/master/CONTRIBUTING.md#build-the-vendored-ocaml-compiler) and [build everything in dev mode](https://github.com/rescript-lang/rescript-compiler/blob/master/CONTRIBUTING.md#build-everything-in-dev-mode-using-vendored-compiler). - -The built binaries will end up under `lib` where you can run local `bsb`: - -```sh -./bsb -init test-theme -theme new_theme -``` diff --git a/jscomp/bsb/bsb_templates.ml b/jscomp/bsb/bsb_templates.ml deleted file mode 100644 index 2cfbd9791a..0000000000 --- a/jscomp/bsb/bsb_templates.ml +++ /dev/null @@ -1,1883 +0,0 @@ - -type node = - | Dir of string * node list - | File of string * string -let root = ([ - Dir("basic",[ - File(".gitignore", - "*.exe\n\ - *.obj\n\ - *.out\n\ - *.compile\n\ - *.native\n\ - *.byte\n\ - *.cmo\n\ - *.annot\n\ - *.cmi\n\ - *.cmx\n\ - *.cmt\n\ - *.cmti\n\ - *.cma\n\ - *.a\n\ - *.cmxa\n\ - *.obj\n\ - *~\n\ - *.annot\n\ - *.cmj\n\ - *.bak\n\ - lib/bs\n\ - *.mlast\n\ - *.mliast\n\ - .vscode\n\ - .merlin\n\ - .bsb.lock\n\ - /node_modules/\n\ - " - ); - File("README.md", - "\n\ - \n\ - # Build\n\ - ```\n\ - npm run build\n\ - ```\n\ - \n\ - # Watch\n\ - \n\ - ```\n\ - npm run watch\n\ - ```\n\ - \n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"sources\": {\n\ - \ \"dir\" : \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"package-specs\": {\n\ - \ \"module\": \"es6\",\n\ - \ \"in-source\": true\n\ - \ },\n\ - \ \"suffix\": \".bs.js\"\n\ - }\n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"rescript clean\",\n\ - \ \"build\": \"rescript build\",\n\ - \ \"watch\": \"rescript build -w\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }" - ); - Dir("src",[ - File("Demo.res", - "\n\ - Js.log(\"Hello, ReScript\")" - ) - ]) - ]); - Dir("basic-reason",[ - File(".gitignore", - ".DS_Store\n\ - .merlin\n\ - .bsb.lock\n\ - npm-debug.log\n\ - /lib/bs/\n\ - /node_modules/\n\ - " - ); - File("README.md", - "# Basic Reason Template\n\ - \n\ - Hello! This project allows you to quickly get started with ReScript using Reason syntax. If you wanted a more sophisticated version, try the `react` template (`bsb -theme react -init .`).\n\ - \n\ - # Build\n\ - \n\ - ```bash\n\ - # for yarn\n\ - yarn build\n\ - \n\ - # for npm\n\ - npm run build\n\ - ```\n\ - \n\ - # Build + Watch\n\ - \n\ - ```bash\n\ - # for yarn\n\ - yarn start\n\ - \n\ - # for npm\n\ - npm run start\n\ - ```\n\ - \n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"sources\": {\n\ - \ \"dir\" : \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"package-specs\": {\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ },\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"bs-dependencies\": [\n\ - \n\ - \ ],\n\ - \ \"warnings\": {\n\ - \ \"error\" : \"+101\"\n\ - \ },\n\ - \ \"namespace\": true,\n\ - \ \"refmt\": 3\n\ - }\n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"start\": \"bsb -make-world -w\",\n\ - \ \"clean\": \"bsb -clean-world\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("Demo.re", - "Js.log(\"Hello, ReScript!\");\n\ - " - ) - ]) - ]); - Dir("generator",[ - File(".gitignore", - "*.exe\n\ - *.obj\n\ - *.out\n\ - *.compile\n\ - *.native\n\ - *.byte\n\ - *.cmo\n\ - *.annot\n\ - *.cmi\n\ - *.cmx\n\ - *.cmt\n\ - *.cmti\n\ - *.cma\n\ - *.a\n\ - *.cmxa\n\ - *.obj\n\ - *~\n\ - *.annot\n\ - *.cmj\n\ - *.bak\n\ - lib/bs\n\ - *.mlast\n\ - *.mliast\n\ - .vscode\n\ - .merlin\n\ - .bsb.lock\n\ - /node_modules/\n\ - " - ); - File("README.md", - "\n\ - \n\ - # Build\n\ - ```\n\ - npm run build\n\ - ```\n\ - \n\ - # Watch\n\ - \n\ - ```\n\ - npm run watch\n\ - ```\n\ - \n\ - \n\ - # Editor\n\ - If you use `vscode`, Press `Windows + Shift + B` it will build automatically" - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"sources\": {\n\ - \ \"dir\": \"src\",\n\ - \ \"generators\": [{\n\ - \ \"name\": \"cpp\",\n\ - \ \"edge\": [\"test.ml\", \":\", \"test.cpp.ml\"]\n\ - \ }],\n\ - \ \"subdirs\": true \n\ - \ },\n\ - \ \"generators\": [{\n\ - \ \"name\" : \"cpp\",\n\ - \ \"command\": \"sed 's/OCAML/3/' $in > $out\"\n\ - \ }],\n\ - \ \"bs-dependencies\" : [\n\ - \ ]\n\ - }" - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"watch\": \"bsb -make-world -w\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("demo.ml", - "\n\ - \n\ - let () = Js.log \"Hello, ReScript\"" - ); - File("test.cpp.ml", - "\n\ - (* \n\ - #define FS_VAL(name,ty) external name : ty = \"\" [@@bs.module \"fs\"]\n\ - \n\ - \n\ - FS_VAL(readdirSync, string -> string array)\n\ - \ *)\n\ - \n\ - \n\ - \ let ocaml = OCAML" - ) - ]) - ]); - Dir("minimal",[ - File(".gitignore", - ".DS_Store\n\ - .merlin\n\ - .bsb.lock\n\ - npm-debug.log\n\ - /lib/bs/\n\ - /node_modules/" - ); - File("README.md", - "\n\ - \ # ${rescript:name}" - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"sources\": {\n\ - \ \"dir\": \"src\",\n\ - \ \"subdirs\": true\n\ - \ }\n\ - }" - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"start\": \"bsb -make-world -w\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("main.ml", - "" - ) - ]) - ]); - Dir("node",[ - File(".gitignore", - "*.exe\n\ - *.obj\n\ - *.out\n\ - *.compile\n\ - *.native\n\ - *.byte\n\ - *.cmo\n\ - *.annot\n\ - *.cmi\n\ - *.cmx\n\ - *.cmt\n\ - *.cmti\n\ - *.cma\n\ - *.a\n\ - *.cmxa\n\ - *.obj\n\ - *~\n\ - *.annot\n\ - *.cmj\n\ - *.bak\n\ - lib/bs\n\ - *.mlast\n\ - *.mliast\n\ - .vscode\n\ - .merlin\n\ - .bsb.lock\n\ - /node_modules/\n\ - " - ); - File("README.md", - "\n\ - \n\ - # Build\n\ - ```\n\ - npm run build\n\ - ```\n\ - \n\ - # Watch\n\ - \n\ - ```\n\ - npm run watch\n\ - ```\n\ - \n\ - \n\ - # Editor\n\ - If you use `vscode`, Press `Windows + Shift + B` it will build automatically\n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"sources\": {\n\ - \ \"dir\": \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"package-specs\": {\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ },\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"bs-dependencies\": [\n\ - \ ]\n\ - }" - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"watch\": \"bsb -make-world -w\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("demo.ml", - "\n\ - \n\ - let () = Js.log \"Hello, ReScript\"" - ) - ]) - ]); - Dir("react-hooks",[ - File(".gitignore", - ".DS_Store\n\ - .merlin\n\ - .bsb.lock\n\ - npm-debug.log\n\ - /lib/bs/\n\ - /node_modules/\n\ - /bundleOutput/" - ); - File("README.md", - "# ReasonReact Template & Examples\n\ - \n\ - This is:\n\ - - A template for your new ReasonReact project.\n\ - - A collection of thin examples illustrating ReasonReact usage.\n\ - - Extra helper documentation for ReasonReact (full ReasonReact docs [here](https://reasonml.github.io/reason-react/)).\n\ - \n\ - `src` contains 4 sub-folders, each an independent, self-contained ReasonReact example. Feel free to delete any of them and shape this into your project! This template's more malleable than you might be used to =).\n\ - \n\ - The point of this template and examples is to let you understand and personally tweak the entirely of it. We **don't** give you an opaque, elaborate mega build setup just to put some boxes on the screen. It strikes to stay transparent, learnable, and simple. You're encouraged to read every file; it's a great feeling, having the full picture of what you're using and being able to touch any part.\n\ - \n\ - ## Run\n\ - \n\ - ```sh\n\ - npm install\n\ - npm run server\n\ - # in a new tab\n\ - npm start\n\ - ```\n\ - \n\ - Open a new web page to `http://localhost:8000/`. Change any `.re` file in `src` to see the page auto-reload. **You don't need any bundler when you're developing**!\n\ - \n\ - **How come we don't need any bundler during development**? We highly encourage you to open up `index.html` to check for yourself!\n\ - \n\ - # Features Used\n\ - \n\ - | | Blinking Greeting | Reducer from ReactJS Docs | Fetch Dog Pictures | Reason Using JS Using Reason |\n\ - |---------------------------|-------------------|---------------------------|--------------------|------------------------------|\n\ - | No props | | ✓ | | |\n\ - | Has props | | | | ✓ |\n\ - | Children props | ✓ | | | |\n\ - | No state | | | | ✓ |\n\ - | Has state | ✓ | | ✓ | |\n\ - | Has state with useReducer | | ✓ | | |\n\ - | ReasonReact using ReactJS | | | | ✓ |\n\ - | ReactJS using ReasonReact | | | | ✓ |\n\ - | useEffect | ✓ | | ✓ | |\n\ - | Dom attribute | ✓ | ✓ | | ✓ |\n\ - | Styling | ✓ | ✓ | ✓ | ✓ |\n\ - | React.array | | | ✓ | |\n\ - \n\ - # Bundle for Production\n\ - \n\ - We've included a convenience `UNUSED_webpack.config.js`, in case you want to ship your project to production. You can rename and/or remove that in favor of other bundlers, e.g. Rollup.\n\ - \n\ - We've also provided a barebone `indexProduction.html`, to serve your bundle.\n\ - \n\ - ```sh\n\ - npm install webpack webpack-cli\n\ - # rename file\n\ - mv UNUSED_webpack.config.js webpack.config.js\n\ - # call webpack to bundle for production\n\ - ./node_modules/.bin/webpack\n\ - open indexProduction.html\n\ - ```\n\ - \n\ - # Handle Routing Yourself\n\ - \n\ - To serve the files, this template uses a minimal dependency called `moduleserve`. A URL such as `localhost:8000/scores/john` resolves to the file `scores/john.html`. If you'd like to override this and handle URL resolution yourself, change the `server` command in `package.json` from `moduleserve ./ --port 8000` to `moduleserve ./ --port 8000 --spa` (for \"single page application\"). This will make `moduleserve` serve the default `index.html` for any URL. Since `index.html` loads `Index.bs.js`, you can grab hold of the URL in the corresponding `Index.re` and do whatever you want.\n\ - \n\ - By the way, ReasonReact comes with a small [router](https://reasonml.github.io/reason-react/docs/en/router) you might be interested in.\n\ - " - ); - File("UNUSED_webpack.config.js", - "const path = require('path');\n\ - \n\ - module.exports = {\n\ - \ entry: './src/Index.bs.js',\n\ - \ // If you ever want to use webpack during development, change 'production'\n\ - \ // to 'development' as per webpack documentation. Again, you don't have to\n\ - \ // use webpack or any other bundler during development! Recheck README if\n\ - \ // you didn't know this\n\ - \ mode: 'production',\n\ - \ output: {\n\ - \ path: path.join(__dirname, \"bundleOutput\"),\n\ - \ filename: 'index.js',\n\ - \ },\n\ - };" - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"reason\": {\n\ - \ \"react-jsx\": 3\n\ - \ },\n\ - \ \"sources\": {\n\ - \ \"dir\" : \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"bsc-flags\": [\"-bs-super-errors\", \"-bs-no-version-header\"],\n\ - \ \"package-specs\": [{\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ }],\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"namespace\": true,\n\ - \ \"bs-dependencies\": [\n\ - \ \"reason-react\"\n\ - \ ],\n\ - \ \"refmt\": 3\n\ - }\n\ - " - ); - File("index.html", - "\n\ - \n\ - \n\ - \ \n\ - \ ReasonReact Examples\n\ - \n\ - \n\ - \ \n\ - \n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \n\ - \n\ - " - ); - File("indexProduction.html", - "\n\ - \n\ - \n\ - \ \n\ - \ ReasonReact Examples\n\ - \n\ - \n\ - \ \n\ - \n\ - \n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"start\": \"bsb -make-world -w -ws _ \",\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"server\": \"moduleserve ./ --port 8000\",\n\ - \ \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\",\n\ - \ \"ReasonReact\",\n\ - \ \"reason-react\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"dependencies\": {\n\ - \ \"react\": \"^16.8.1\",\n\ - \ \"react-dom\": \"^16.8.1\",\n\ - \ \"reason-react\": \">=0.7.1\"\n\ - \ },\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\",\n\ - \ \"moduleserve\": \"^0.9.0\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - Dir("BlinkingGreeting",[ - File("BlinkingGreeting.re", - "[@react.component]\n\ - let make = (~children) => {\n\ - \ let (show, setShow) = React.useState(() => true);\n\ - \n\ - \ // Notice that instead of `useEffect`, we have `useEffect0`. See\n\ - \ // reasonml.github.io/reason-react/docs/en/components#hooks for more info\n\ - \ React.useEffect0(() => {\n\ - \ let id =\n\ - \ Js.Global.setInterval(\n\ - \ () => setShow(previousShow => !previousShow),\n\ - \ 1000,\n\ - \ );\n\ - \n\ - \ Some(() => Js.Global.clearInterval(id));\n\ - \ });\n\ - \n\ - \ let style =\n\ - \ if (show) {\n\ - \ ReactDOMRe.Style.make(~opacity=\"1\", ~transition=\"opacity 1s\", ());\n\ - \ } else {\n\ - \ ReactDOMRe.Style.make(~opacity=\"0\", ~transition=\"opacity 1s\", ());\n\ - \ };\n\ - \n\ - \
children
;\n\ - };\n\ - " - ) - ]); - File("ExampleStyles.re", - "let reasonReactBlue = \"#48a9dc\";\n\ - \n\ - // The {j|...|j} feature is just string interpolation, from\n\ - // bucklescript.github.io/docs/en/interop-cheatsheet#string-unicode-interpolation\n\ - // This allows us to conveniently write CSS, together with variables, by\n\ - // constructing a string\n\ - let style = {j|\n\ - \ body {\n\ - \ background-color: rgb(224, 226, 229);\n\ - \ display: flex;\n\ - \ flex-direction: column;\n\ - \ align-items: center;\n\ - \ }\n\ - \ button {\n\ - \ background-color: white;\n\ - \ color: $reasonReactBlue;\n\ - \ box-shadow: 0 0 0 1px $reasonReactBlue;\n\ - \ border: none;\n\ - \ padding: 8px;\n\ - \ font-size: 16px;\n\ - \ }\n\ - \ button:active {\n\ - \ background-color: $reasonReactBlue;\n\ - \ color: white;\n\ - \ }\n\ - \ .container {\n\ - \ margin: 12px 0px;\n\ - \ box-shadow: 0px 4px 16px rgb(200, 200, 200);\n\ - \ width: 720px;\n\ - \ border-radius: 12px;\n\ - \ font-family: sans-serif;\n\ - \ }\n\ - \ .containerTitle {\n\ - \ background-color: rgb(242, 243, 245);\n\ - \ border-radius: 12px 12px 0px 0px;\n\ - \ padding: 12px;\n\ - \ font-weight: bold;\n\ - \ }\n\ - \ .containerContent {\n\ - \ background-color: white;\n\ - \ padding: 16px;\n\ - \ border-radius: 0px 0px 12px 12px;\n\ - \ }\n\ - |j};\n\ - " - ); - Dir("FetchedDogPictures",[ - File("FetchedDogPictures.re", - "[@bs.val] external fetch: string => Js.Promise.t('a) = \"fetch\";\n\ - \n\ - type state =\n\ - \ | LoadingDogs\n\ - \ | ErrorFetchingDogs\n\ - \ | LoadedDogs(array(string));\n\ - \n\ - [@react.component]\n\ - let make = () => {\n\ - \ let (state, setState) = React.useState(() => LoadingDogs);\n\ - \n\ - \ // Notice that instead of `useEffect`, we have `useEffect0`. See\n\ - \ // reasonml.github.io/reason-react/docs/en/components#hooks for more info\n\ - \ React.useEffect0(() => {\n\ - \ Js.Promise.(\n\ - \ fetch(\"https://dog.ceo/api/breeds/image/random/3\")\n\ - \ |> then_(response => response##json())\n\ - \ |> then_(jsonResponse => {\n\ - \ setState(_previousState => LoadedDogs(jsonResponse##message));\n\ - \ Js.Promise.resolve();\n\ - \ })\n\ - \ |> catch(_err => {\n\ - \ setState(_previousState => ErrorFetchingDogs);\n\ - \ Js.Promise.resolve();\n\ - \ })\n\ - \ |> ignore\n\ - \ );\n\ - \n\ - \ // Returning None, instead of Some(() => ...), means we don't have any\n\ - \ // cleanup to do before unmounting. That's not 100% true. We should\n\ - \ // technically cancel the promise. Unofortunately, there's currently no\n\ - \ // way to cancel a promise. Promises in general should be way less used\n\ - \ // for React components; but since folks do use them, we provide such an\n\ - \ // example here. In reality, this fetch should just be a plain callback,\n\ - \ // with a cancellation API\n\ - \ None;\n\ - \ });\n\ - \n\ - \ \n\ - \ {switch (state) {\n\ - \ | ErrorFetchingDogs => React.string(\"An error occurred!\")\n\ - \ | LoadingDogs => React.string(\"Loading...\")\n\ - \ | LoadedDogs(dogs) =>\n\ - \ dogs\n\ - \ ->Belt.Array.mapWithIndex((i, dog) => {\n\ - \ let imageStyle =\n\ - \ ReactDOMRe.Style.make(\n\ - \ ~height=\"120px\",\n\ - \ ~width=\"100%\",\n\ - \ ~marginRight=i === Js.Array.length(dogs) - 1 ? \"0px\" : \"8px\",\n\ - \ ~borderRadius=\"8px\",\n\ - \ ~boxShadow=\"0px 4px 16px rgb(200, 200, 200)\",\n\ - \ ~backgroundSize=\"cover\",\n\ - \ ~backgroundImage={j|url($dog)|j},\n\ - \ ~backgroundPosition=\"center\",\n\ - \ (),\n\ - \ );\n\ - \
;\n\ - \ })\n\ - \ ->React.array\n\ - \ }}\n\ - \
;\n\ - };\n\ - " - ) - ]); - File("Index.re", - "// Entry point\n\ - \n\ - [@bs.val] external document: Js.t({..}) = \"document\";\n\ - \n\ - // We're using raw DOM manipulations here, to avoid making you read\n\ - // ReasonReact when you might precisely be trying to learn it for the first\n\ - // time through the examples later.\n\ - let style = document##createElement(\"style\");\n\ - document##head##appendChild(style);\n\ - style##innerHTML #= ExampleStyles.style;\n\ - \n\ - let makeContainer = text => {\n\ - \ let container = document##createElement(\"div\");\n\ - \ container##className #= \"container\";\n\ - \n\ - \ let title = document##createElement(\"div\");\n\ - \ title##className #= \"containerTitle\";\n\ - \ title##innerText #= text;\n\ - \n\ - \ let content = document##createElement(\"div\");\n\ - \ content##className #= \"containerContent\";\n\ - \n\ - \ let () = container##appendChild(title);\n\ - \ let () = container##appendChild(content);\n\ - \ let () = document##body##appendChild(container);\n\ - \n\ - \ content;\n\ - };\n\ - \n\ - // All 4 examples.\n\ - ReactDOMRe.render(\n\ - \ \n\ - \ {React.string(\"Hello!\")}\n\ - \ ,\n\ - \ makeContainer(\"Blinking Greeting\"),\n\ - );\n\ - \n\ - ReactDOMRe.render(\n\ - \ ,\n\ - \ makeContainer(\"Reducer From ReactJS Docs\"),\n\ - );\n\ - \n\ - ReactDOMRe.render(\n\ - \ ,\n\ - \ makeContainer(\"Fetched Dog Pictures\"),\n\ - );\n\ - \n\ - ReactDOMRe.render(\n\ - \ ,\n\ - \ makeContainer(\"Reason Using JS Using Reason\"),\n\ - );\n\ - " - ); - Dir("ReasonUsingJSUsingReason",[ - File("ReactJSCard.js", - "// In this Interop example folder, we have:\n\ - // - A ReasonReact component, ReasonReactCard.re\n\ - // - Used by a ReactJS component, ReactJSCard.js (this file)\n\ - // - ReactJSCard.js can be used by ReasonReact, through bindings in ReasonUsingJSUsingReason.re\n\ - // - ReasonUsingJSUsingReason.re is used by Index.re\n\ - \n\ - var ReactDOM = require('react-dom');\n\ - var React = require('react');\n\ - \n\ - var ReasonReactCard = require('./ReasonReactCard.bs').make;\n\ - \n\ - var ReactJSComponent = function() {\n\ - \ let backgroundColor = \"rgba(0, 0, 0, 0.05)\";\n\ - \ let padding = \"12px\";\n\ - \n\ - \ // We're not using JSX here, to avoid folks needing to install the related\n\ - \ // React toolchains just for this example.\n\ - \ //
\n\ - \ //
This is a ReactJS card
\n\ - \ // \n\ - \ //
\n\ - \ return React.createElement(\n\ - \ \"div\",\n\ - \ {style: {backgroundColor, padding, borderRadius: \"8px\"}},\n\ - \ React.createElement(\"div\", {style: {marginBottom: \"8px\"}}, \"This is a ReactJS card\"),\n\ - \ React.createElement(ReasonReactCard, {style: {backgroundColor, padding, borderRadius: \"4px\"}}),\n\ - \ )\n\ - };\n\ - ReactJSComponent.displayName = \"MyBanner\";\n\ - \n\ - module.exports = ReactJSComponent;\n\ - " - ); - File("ReasonReactCard.re", - "// In this Interop example folder, we have:\n\ - // - A ReasonReact component, ReasonReactCard.re (this file)\n\ - // - Used by a ReactJS component, ReactJSCard.js\n\ - // - ReactJSCard.js can be used by ReasonReact, through bindings in ReasonUsingJSUsingReason.re\n\ - // - ReasonUsingJSUsingReason.re is used by Index.re\n\ - \n\ - [@react.component]\n\ - let make = (~style) => {\n\ - \
{React.string(\"This is a ReasonReact card\")}
;\n\ - };\n\ - " - ); - File("ReasonUsingJSUsingReason.re", - "// In this Interop example folder, we have:\n\ - // - A ReasonReact component, ReasonReactCard.re\n\ - // - Used by a ReactJS component, ReactJSCard.js\n\ - // - ReactJSCard.js can be used by ReasonReact, through bindings in ReasonUsingJSUsingReason.re (this file)\n\ - // - ReasonUsingJSUsingReason.re is used by Index.re\n\ - \n\ - // All you need to do to use a ReactJS component in ReasonReact, is to write the lines below!\n\ - // reasonml.github.io/reason-react/docs/en/components#import-from-js\n\ - [@react.component] [@bs.module]\n\ - external make: unit => React.element = \"./ReactJSCard\";\n\ - " - ) - ]); - Dir("ReducerFromReactJSDocs",[ - File("ReducerFromReactJSDocs.re", - "// This is the ReactJS documentation's useReducer example, directly ported over\n\ - // https://reactjs.org/docs/hooks-reference.html#usereducer\n\ - \n\ - // A little extra we've put, because the ReactJS example has no styling\n\ - let leftButtonStyle = ReactDOMRe.Style.make(~borderRadius=\"4px 0px 0px 4px\", ~width=\"48px\", ());\n\ - let rightButtonStyle = ReactDOMRe.Style.make(~borderRadius=\"0px 4px 4px 0px\", ~width=\"48px\", ());\n\ - let containerStyle = ReactDOMRe.Style.make(~display=\"flex\", ~alignItems=\"center\", ~justifyContent=\"space-between\", ());\n\ - \n\ - // Record and variant need explicit declarations.\n\ - type state = {count: int};\n\ - \n\ - type action =\n\ - \ | Increment\n\ - \ | Decrement;\n\ - \n\ - let initialState = {count: 0};\n\ - \n\ - let reducer = (state, action) => {\n\ - \ switch (action) {\n\ - \ | Increment => {count: state.count + 1}\n\ - \ | Decrement => {count: state.count - 1}\n\ - \ };\n\ - };\n\ - \n\ - [@react.component]\n\ - let make = () => {\n\ - \ let (state, dispatch) = React.useReducer(reducer, initialState);\n\ - \n\ - \ // We can use a fragment here, but we don't, because we want to style the counter\n\ - \
\n\ - \
\n\ - \ {React.string(\"Count: \")}\n\ - \ {React.string(string_of_int(state.count))}\n\ - \
\n\ - \
\n\ - \ \n\ - \ \n\ - \
\n\ - \
;\n\ - };\n\ - " - ) - ]) - ]); - File("watcher.js", - "// This is our simple, robust watcher. It hooks into the ReScript build\n\ - // system to listen for build events.\n\ - // See package.json's `start` script and `./node_modules/.bin/bsb --help`\n\ - \n\ - // Btw, if you change this file and reload the page, your browser cache\n\ - // _might_ not pick up the new version. If you're in Chrome, do Force Reload.\n\ - \n\ - var websocketReloader;\n\ - var LAST_SUCCESS_BUILD_STAMP =\n\ - \ localStorage.getItem(\"LAST_SUCCESS_BUILD_STAMP\") || 0;\n\ - // package.json's `start` script's `bsb -ws _` means it'll pipe build events\n\ - // through a websocket connection to a default port of 9999. This is\n\ - // configurable, e.g. `-ws 5000`\n\ - var webSocketPort = 9999;\n\ - \n\ - function setUpWebSocket() {\n\ - \ if (websocketReloader == null || websocketReloader.readyState !== 1) {\n\ - \ try {\n\ - \ websocketReloader = new WebSocket(\n\ - \ `ws://${window.location.hostname}:${webSocketPort}`\n\ - \ );\n\ - \ websocketReloader.onmessage = (message) => {\n\ - \ var newData = JSON.parse(message.data).LAST_SUCCESS_BUILD_STAMP;\n\ - \ if (newData > LAST_SUCCESS_BUILD_STAMP) {\n\ - \ LAST_SUCCESS_BUILD_STAMP = newData;\n\ - \ localStorage.setItem(\n\ - \ \"LAST_SUCCESS_BUILD_STAMP\",\n\ - \ LAST_SUCCESS_BUILD_STAMP\n\ - \ );\n\ - \ // Refresh the page! This will naturally re-run everything,\n\ - \ // including our moduleserve which will re-resolve all the modules.\n\ - \ // No stable build!\n\ - \ location.reload(true);\n\ - \ }\n\ - \ };\n\ - \ } catch (exn) {\n\ - \ console.error(\n\ - \ \"The watcher tried to connect to web socket, but failed. Here's the message:\"\n\ - \ );\n\ - \ console.error(exn);\n\ - \ }\n\ - \ }\n\ - }\n\ - \n\ - setUpWebSocket();\n\ - setInterval(setUpWebSocket, 2000);\n\ - " - ) - ]); - Dir("react-starter",[ - File(".gitignore", - ".DS_Store\n\ - .merlin\n\ - .bsb.lock\n\ - npm-debug.log\n\ - /lib/bs/\n\ - /node_modules/\n\ - *.bs.js\n\ - " - ); - File("README.md", - "# Reason react starter\n\ - \n\ - ## Run Project\n\ - \n\ - ```sh\n\ - npm install\n\ - npm start\n\ - # in another tab\n\ - npm run server\n\ - ```\n\ - \n\ - View the app in the browser at http://localhost:8000. Running in this environment provides hot reloading and support for routing; just edit and save the file and the browser will automatically refresh.\n\ - \n\ - To use a port other than 8000 set the `PORT` environment variable (`PORT=8080 npm run server`).\n\ - \n\ - ## Build for Production\n\ - \n\ - ```sh\n\ - npm run clean\n\ - npm run build\n\ - npm run webpack:production\n\ - ```\n\ - \n\ - This will replace the development artifact `build/Index.js` for an optimized version as well as copy `src/index.html` into `build/`. You can then deploy the contents of the `build` directory (`index.html` and `Index.js`).\n\ - \n\ - **To enable dead code elimination**, change `bsconfig.json`'s `package-specs` `module` from `\"commonjs\"` to `\"es6\"`. Then re-run the above 2 commands. This will allow Webpack to remove unused code.\n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"reason-react-starter\",\n\ - \ \"reason\": {\n\ - \ \"react-jsx\": 3\n\ - \ },\n\ - \ \"sources\": {\n\ - \ \"dir\": \"src\",\n\ - \ \"subdirs\": true\n\ - \ },\n\ - \ \"bsc-flags\": [\"-bs-super-errors\", \"-bs-no-version-header\"],\n\ - \ \"package-specs\": [\n\ - \ {\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ }\n\ - \ ],\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"namespace\": true,\n\ - \ \"bs-dependencies\": [\"reason-react\"],\n\ - \ \"refmt\": 3\n\ - }\n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"start\": \"bsb -make-world -w -ws _ \",\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"webpack\": \"webpack -w\",\n\ - \ \"webpack:production\": \"NODE_ENV=production webpack\",\n\ - \ \"server\": \"webpack-dev-server\",\n\ - \ \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\",\n\ - \ \"ReasonReact\",\n\ - \ \"reason-react\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"dependencies\": {\n\ - \ \"react\": \"^17.0.1\",\n\ - \ \"react-dom\": \"^17.0.1\",\n\ - \ \"reason-react\": \"^0.9.1\"\n\ - \ },\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\",\n\ - \ \"css-loader\": \"^5.0.0\",\n\ - \ \"html-webpack-plugin\": \"^4.5.0\",\n\ - \ \"style-loader\": \"^2.0.0\",\n\ - \ \"webpack\": \"^4.44.2\",\n\ - \ \"webpack-cli\": \"^3.3.12\",\n\ - \ \"webpack-dev-server\": \"^3.11.0\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("App.re", - "type state = {count: int};\n\ - \n\ - type action =\n\ - \ | Increment\n\ - \ | Decrement;\n\ - \n\ - let initialState = {count: 0};\n\ - \n\ - let reducer = (state, action) =>\n\ - \ switch (action) {\n\ - \ | Increment => {count: state.count + 1}\n\ - \ | Decrement => {count: state.count - 1}\n\ - \ };\n\ - \n\ - [@react.component]\n\ - let make = () => {\n\ - \ let (state, dispatch) = React.useReducer(reducer, initialState);\n\ - \n\ - \
\n\ - \ {React.string(\"Simple counter with reducer\")}\n\ - \
\n\ - \ \n\ - \ \n\ - \ {state.count |> string_of_int |> React.string}\n\ - \ \n\ - \ \n\ - \
\n\ - \
;\n\ - };\n\ - " - ); - File("Index.re", - "[%bs.raw {|require(\"./index.css\")|}];\n\ - \n\ - ReactDOMRe.renderToElementWithId(, \"root\");\n\ - " - ); - File("index.css", - "body {\n\ - \ margin: 0;\n\ - \ font-family: -apple-system, system-ui, \"Segoe UI\", Helvetica, Arial,\n\ - \ sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n\ - }\n\ - \n\ - main {\n\ - \ padding: 20px;\n\ - }\n\ - \n\ - .counter {\n\ - \ padding: 20px;\n\ - \ display: inline-block;\n\ - }\n\ - " - ); - File("index.html", - "\n\ - \n\ - \ \n\ - \ \n\ - \ Reason react starter\n\ - \ \n\ - \ \n\ - \
\n\ - \ \n\ - \ \n\ - \n\ - " - ) - ]); - File("webpack.config.js", - "const path = require(\"path\")\n\ - const HtmlWebpackPlugin = require(\"html-webpack-plugin\")\n\ - const outputDir = path.join(__dirname, \"build/\")\n\ - \n\ - const isProd = process.env.NODE_ENV === \"production\"\n\ - \n\ - module.exports = {\n\ - \ entry: \"./src/Index.bs.js\",\n\ - \ mode: isProd ? \"production\" : \"development\",\n\ - \ devtool: \"source-map\",\n\ - \ output: {\n\ - \ path: outputDir,\n\ - \ filename: \"Index.js\"\n\ - \ },\n\ - \ plugins: [\n\ - \ new HtmlWebpackPlugin({\n\ - \ template: \"src/index.html\",\n\ - \ inject: false\n\ - \ })\n\ - \ ],\n\ - \ devServer: {\n\ - \ compress: true,\n\ - \ contentBase: outputDir,\n\ - \ port: process.env.PORT || 8000,\n\ - \ historyApiFallback: true\n\ - \ },\n\ - \ module: {\n\ - \ rules: [\n\ - \ {\n\ - \ test: /\\.css$/,\n\ - \ use: [\"style-loader\", \"css-loader\"]\n\ - \ }\n\ - \ ]\n\ - \ }\n\ - }\n\ - " - ) - ]); - Dir("tea",[ - File("README.md", - "\n\ - \n\ - # Build\n\ - ```\n\ - npm run build\n\ - ```\n\ - \n\ - # Watch\n\ - \n\ - ```\n\ - npm run watch\n\ - ```\n\ - \n\ - create a http-server\n\ - \n\ - ```\n\ - npm install -g http-server\n\ - ```\n\ - \n\ - Edit the file and see the changes automatically reloaded in the browser\n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"tea\",\n\ - \ \"version\": \"0.1.0\",\n\ - \ \"sources\": {\n\ - \ \"dir\" : \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"package-specs\": {\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ },\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"bs-dependencies\": [\n\ - \ \"bucklescript-tea\"\n\ - \ ]\n\ - }\n\ - " - ); - File("index.html", - "\n\ - \n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \ Bucklescript TEA Starter Kit\n\ - \ \n\ - \ \n\ - \n\ - \n\ - \ \n\ - \
\n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - " - ); - File("loader.js", - "/* Copyright (C) 2018 Authors of ReScript\n\ - \ *\n\ - \ * This program is free software: you can redistribute it and/or modify\n\ - \ * it under the terms of the GNU Lesser General Public License as published by\n\ - \ * the Free Software Foundation, either version 3 of the License, or\n\ - \ * (at your option) any later version.\n\ - \ *\n\ - \ * In addition to the permissions granted to you by the LGPL, you may combine\n\ - \ * or link a \"work that uses the Library\" with a publicly distributed version\n\ - \ * of this file to produce a combined library or application, then distribute\n\ - \ * that combined work under the terms of your choosing, with no requirement\n\ - \ * to comply with the obligations normally placed on you by section 4 of the\n\ - \ * LGPL version 3 (or the corresponding section of a later version of the LGPL\n\ - \ * should you choose to use a later version).\n\ - \ *\n\ - \ * This program is distributed in the hope that it will be useful,\n\ - \ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ - \ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ - \ * GNU Lesser General Public License for more details.\n\ - \ *\n\ - \ * You should have received a copy of the GNU Lesser General Public License\n\ - \ * along with this program; if not, write to the Free Software\n\ - \ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */\n\ - \n\ - //@ts-check\n\ - \n\ - // @ts-ignore\n\ - window.process = { env: { NODE_ENV: \"dev\" } };\n\ - \n\ - // local to getPath\n\ - var relativeElement = document.createElement(\"a\");\n\ - var baseElement = document.createElement(\"base\");\n\ - document.head.appendChild(baseElement);\n\ - \n\ - export function BsGetPath(id, parent) {\n\ - \ var oldPath = baseElement.href;\n\ - \ baseElement.href = parent;\n\ - \ relativeElement.href = id;\n\ - \ var result = relativeElement.href;\n\ - \ baseElement.href = oldPath;\n\ - \ return result;\n\ - }\n\ - /**\n\ - \ *\n\ - \ * Given current link and its parent, return the new link\n\ - \ * @param {string} id\n\ - \ * @param {string} parent\n\ - \ * @return {string}\n\ - \ */\n\ - function getPathWithJsSuffix(id, parent) {\n\ - \ var oldPath = baseElement.href;\n\ - \ baseElement.href = parent;\n\ - \ relativeElement.href = id;\n\ - \ var result = addSuffixJsIfNot(relativeElement.href);\n\ - \ baseElement.href = oldPath;\n\ - \ return result;\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} x\n\ - \ */\n\ - function addSuffixJsIfNot(x) {\n\ - \ if (x.endsWith(\".js\")) {\n\ - \ return x;\n\ - \ } else {\n\ - \ return x + \".js\";\n\ - \ }\n\ - }\n\ - \n\ - var falsePromise = Promise.resolve(false);\n\ - var fetchConfig = { cache: \"no-cache\" };\n\ - // package.json semantics\n\ - // a string to module object\n\ - // from url -> module object\n\ - // Modules : Map\n\ - // fetch the link:\n\ - // - if it is already fetched before, return the stored promise\n\ - // otherwise create the promise which will be filled with the text if successful\n\ - // or filled with boolean false when failed\n\ - var MODULES = new Map();\n\ - function cachedFetch(link) {\n\ - \ // console.info(link)\n\ - \ var linkResult = MODULES.get(link);\n\ - \ if (linkResult) {\n\ - \ return linkResult;\n\ - \ } else {\n\ - \ var p = fetch(link, fetchConfig).then((resp) => {\n\ - \ if (resp.ok) {\n\ - \ return resp.text();\n\ - \ } else {\n\ - \ return falsePromise;\n\ - \ }\n\ - \ });\n\ - \n\ - \ MODULES.set(link, p);\n\ - \ return p;\n\ - \ }\n\ - }\n\ - \n\ - // from location id -> url\n\ - // There are two rounds of caching:\n\ - // 1. if location and relative path is hit, no need to run\n\ - // 2. if location and relative path is not hit, but the resolved link is hit, no need\n\ - // for network request\n\ - /**\n\ - \ * @type {Map > > }\n\ - \ */\n\ - var IDLocations = new Map();\n\ - \n\ - /**\n\ - \ * @type {Map > }\n\ - \ */\n\ - var SyncedIDLocations = new Map();\n\ - // Its value is an object\n\ - // { link : String }\n\ - // We will first mark it when visiting (to avoid duplicated computation)\n\ - // and populate its link later\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} location\n\ - \ */\n\ - function getIdLocation(id, location) {\n\ - \ var idMap = IDLocations.get(location);\n\ - \ if (idMap) {\n\ - \ return idMap.get(id);\n\ - \ }\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} location\n\ - \ */\n\ - function getIdLocationSync(id, location) {\n\ - \ var idMap = SyncedIDLocations.get(location);\n\ - \ if (idMap) {\n\ - \ return idMap.get(id);\n\ - \ }\n\ - }\n\ - \n\ - function countIDLocations() {\n\ - \ var count = 0;\n\ - \ for (let [k, vv] of IDLocations) {\n\ - \ for (let [kv, v] of vv) {\n\ - \ count += 1;\n\ - \ }\n\ - \ }\n\ - \ console.log(count, \"modules loaded\");\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} location\n\ - \ * @param {Function} cb\n\ - \ * @returns Promise\n\ - \ */\n\ - function visitIdLocation(id, location, cb) {\n\ - \ var result;\n\ - \ var idMap = IDLocations.get(location);\n\ - \ if (idMap && (result = idMap.get(id))) {\n\ - \ return result;\n\ - \ } else {\n\ - \ result = new Promise((resolve) => {\n\ - \ return cb().then((res) => {\n\ - \ var idMap = SyncedIDLocations.get(location);\n\ - \ if (idMap) {\n\ - \ idMap.set(id, res);\n\ - \ } else {\n\ - \ SyncedIDLocations.set(location, new Map([[id, res]]));\n\ - \ }\n\ - \ return resolve(res);\n\ - \ });\n\ - \ });\n\ - \ if (idMap) {\n\ - \ idMap.set(id, result);\n\ - \ } else {\n\ - \ IDLocations.set(location, new Map([[id, result]]));\n\ - \ }\n\ - \ return result;\n\ - \ }\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} text\n\ - \ * @return {string[]}\n\ - \ */\n\ - function getDeps(text) {\n\ - \ var deps = [];\n\ - \ text.replace(\n\ - \ /(\\/\\*[\\w\\W]*?\\*\\/|\\/\\/[^\\n]*|[.$]r)|\\brequire\\s*\\(\\s*[\"']([^\"']*)[\"']\\s*\\)/g,\n\ - \ function (_, ignore, id) {\n\ - \ if (!ignore) deps.push(id);\n\ - \ }\n\ - \ );\n\ - \ return deps;\n\ - }\n\ - \n\ - // By using a named \"eval\" most browsers will execute in the global scope.\n\ - // http://www.davidflanagan.com/2010/12/global-eval-in.html\n\ - var globalEval = eval;\n\ - \n\ - // function parentURL(url) {\n\ - // if (url.endsWith('/')) {\n\ - // return url + '../'\n\ - // } else {\n\ - // return url + '/../'\n\ - // }\n\ - // }\n\ - \n\ - // loader.js:23 http://localhost:8080/node_modules/react-dom/cjs/react-dom.development.js/..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//../ fbjs/lib/containsNode Promise {}\n\ - // 23:10:02.884 loader.js:23 http://localhost:8080/node_modules/react-dom/cjs/react-dom.development.js/..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//../ fbjs/lib/invariant Promise {}\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} parent\n\ - \ */\n\ - function getParentModulePromise(id, parent) {\n\ - \ var parentLink = BsGetPath(\"..\", parent);\n\ - \ if (parentLink === parent) {\n\ - \ return falsePromise;\n\ - \ }\n\ - \ return getPackageJsPromise(id, parentLink);\n\ - }\n\ - // In the beginning\n\ - // it is `resolveModule('./main.js', '')\n\ - // return the promise of link and text\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ */\n\ - function getPackageName(id) {\n\ - \ var index = id.indexOf(\"/\");\n\ - \ if (id[0] === \"@\") index = id.indexOf(\"/\", index + 1);\n\ - \ if (index === -1) {\n\ - \ return id;\n\ - \ }\n\ - \ return id.substring(0, index);\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} s\n\ - \ * @param {string} text\n\ - \ * @returns {undefined | string }\n\ - \ */\n\ - function isJustAPackageAndHasMainField(s, text) {\n\ - \ if (s.indexOf(\"/\") >= 0) {\n\ - \ return;\n\ - \ } else {\n\ - \ var mainField;\n\ - \ try {\n\ - \ mainField = JSON.parse(text).main;\n\ - \ } catch (_) {}\n\ - \ if (mainField === undefined) {\n\ - \ return;\n\ - \ } else {\n\ - \ return mainField;\n\ - \ }\n\ - \ }\n\ - }\n\ - function getPackageJsPromise(id, parent) {\n\ - \ var idNodeModulesPrefix = \"./node_modules/\" + id;\n\ - \ var link = getPathWithJsSuffix(idNodeModulesPrefix, parent);\n\ - \ if (parent.endsWith(\"node_modules/\")) {\n\ - \ // impossible that `node_modules/node_modules/xx/x\n\ - \ // return falsePromise\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \n\ - \ var packageJson = BsGetPath(\n\ - \ `./node_modules/${getPackageName(id)}/package.json`,\n\ - \ parent\n\ - \ );\n\ - \n\ - \ return cachedFetch(packageJson).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ var mainField;\n\ - \ if ((mainField = isJustAPackageAndHasMainField(id, text)) !== undefined) {\n\ - \ var packageLink = BsGetPath(\n\ - \ addSuffixJsIfNot(`./node_modules/${id}/${mainField}`),\n\ - \ parent\n\ - \ );\n\ - \ return cachedFetch(packageLink).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link: packageLink };\n\ - \ } else {\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \ });\n\ - \ } else {\n\ - \ // package indeed exist\n\ - \ return cachedFetch(link).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link };\n\ - \ } else if (!id.endsWith(\".js\")) {\n\ - \ var linkNew = getPathWithJsSuffix(\n\ - \ idNodeModulesPrefix + `/index.js`,\n\ - \ parent\n\ - \ );\n\ - \ return cachedFetch(linkNew).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link: linkNew };\n\ - \ } else {\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \ });\n\ - \ } else {\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \ });\n\ - \ }\n\ - \ } else {\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \ });\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} parent\n\ - \ * can return Promise , false means\n\ - \ * this module can not be resolved\n\ - \ */\n\ - function getModulePromise(id, parent) {\n\ - \ var done = getIdLocation(id, parent);\n\ - \ if (!done) {\n\ - \ return visitIdLocation(id, parent, function () {\n\ - \ if (id[0] != \".\") {\n\ - \ // package path\n\ - \ return getPackageJsPromise(id, parent);\n\ - \ } else {\n\ - \ // relative path, one shot resolve\n\ - \ let link = getPathWithJsSuffix(id, parent);\n\ - \ return cachedFetch(link).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link };\n\ - \ } else if (!id.endsWith(\".js\")) {\n\ - \ // could be \"./dir\"\n\ - \ var newLink = getPathWithJsSuffix(id + \"/index.js\", parent);\n\ - \ return cachedFetch(newLink).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link: newLink };\n\ - \ } else {\n\ - \ throw new Error(` ${id} : ${parent} could not be resolved`);\n\ - \ }\n\ - \ });\n\ - \ } else {\n\ - \ throw new Error(` ${id} : ${parent} could not be resolved`);\n\ - \ }\n\ - \ });\n\ - \ }\n\ - \ });\n\ - \ } else {\n\ - \ return done;\n\ - \ }\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} parent\n\ - \ * @returns {Promise}\n\ - \ */\n\ - function getAll(id, parent) {\n\ - \ return getModulePromise(id, parent).then(function (obj) {\n\ - \ if (obj) {\n\ - \ var deps = getDeps(obj.text);\n\ - \ return Promise.all(deps.map((x) => getAll(x, obj.link)));\n\ - \ } else {\n\ - \ throw new Error(`${id}@${parent} was not resolved successfully`);\n\ - \ }\n\ - \ });\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} text\n\ - \ * @param {string} parent\n\ - \ * @returns {Promise}\n\ - \ */\n\ - function getAllFromText(text, parent) {\n\ - \ var deps = getDeps(text);\n\ - \ return Promise.all(deps.map((x) => getAll(x, parent)));\n\ - }\n\ - \n\ - var evaluatedModules = new Map();\n\ - \n\ - function loadSync(id, parent) {\n\ - \ var baseOrModule = getIdLocationSync(id, parent);\n\ - \ if (baseOrModule && baseOrModule.link !== undefined) {\n\ - \ if (evaluatedModules.has(baseOrModule.link)) {\n\ - \ return evaluatedModules.get(baseOrModule.link).exports;\n\ - \ }\n\ - \ if (!baseOrModule.exports) {\n\ - \ baseOrModule.exports = {};\n\ - \ globalEval(\n\ - \ `(function(require,exports,module){${baseOrModule.text}\\n})//# sourceURL=${baseOrModule.link}`\n\ - \ )(\n\ - \ function require(id) {\n\ - \ return loadSync(id, baseOrModule.link);\n\ - \ }, // require\n\ - \ (baseOrModule.exports = {}), // exports\n\ - \ baseOrModule // module\n\ - \ );\n\ - \ }\n\ - \ if (!evaluatedModules.has(baseOrModule.link)) {\n\ - \ evaluatedModules.set(baseOrModule.link, baseOrModule);\n\ - \ }\n\ - \ return baseOrModule.exports;\n\ - \ } else {\n\ - \ throw new Error(`${id} : ${parent} could not be resolved`);\n\ - \ }\n\ - }\n\ - \n\ - function genEvalName() {\n\ - \ return \"eval-\" + (\"\" + Math.random()).substr(2, 5);\n\ - }\n\ - /**\n\ - \ *\n\ - \ * @param {string} text\n\ - \ * @param {string} link\n\ - \ * In this case [text] evaluated result will not be cached\n\ - \ */\n\ - function loadTextSync(text, link) {\n\ - \ var baseOrModule = { exports: {}, text, link };\n\ - \ globalEval(\n\ - \ `(function(require,exports,module){${baseOrModule.text}\\n})//# sourceURL=${\n\ - \ baseOrModule.link\n\ - \ }/${genEvalName()}.js`\n\ - \ )(\n\ - \ function require(id) {\n\ - \ return loadSync(id, baseOrModule.link);\n\ - \ }, // require\n\ - \ baseOrModule.exports, // exports\n\ - \ baseOrModule // module\n\ - \ );\n\ - \ return baseOrModule.exports;\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} text\n\ - \ */\n\ - function BSloadText(text) {\n\ - \ console.time(\"Loading\");\n\ - \ var parent = BsGetPath(\".\", document.baseURI);\n\ - \ return getAllFromText(text, parent).then(function () {\n\ - \ var result = loadTextSync(text, parent);\n\ - \ console.timeEnd(\"Loading\");\n\ - \ return result;\n\ - \ });\n\ - }\n\ - \n\ - function load(id, parent) {\n\ - \ return getAll(id, parent).then(function () {\n\ - \ return loadSync(id, parent);\n\ - \ });\n\ - }\n\ - \n\ - export function BSload(id) {\n\ - \ var parent = BsGetPath(\".\", document.baseURI);\n\ - \ return load(id, parent);\n\ - }\n\ - \n\ - export var BSLoader = {\n\ - \ loadText: BSloadText,\n\ - \ load: BSload,\n\ - \ SyncedIDLocations: SyncedIDLocations,\n\ - };\n\ - \n\ - window.BSLoader = BSLoader;\n\ - \n\ - var main = document.querySelector(\"script[data-main]\");\n\ - if (main) {\n\ - \ BSload(main.dataset.main);\n\ - }\n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"watch\": \"bsb -make-world -w -ws _\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ },\n\ - \ \"dependencies\": {\n\ - \ \"bucklescript-tea\": \"^0.7.4\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("demo.ml", - "(* This line opens the Tea.App modules into the current scope for Program access functions and types *)\n\ - open Tea.App\n\ - \n\ - (* This opens the Elm-style virtual-dom functions and types into the current scope *)\n\ - open Tea.Html\n\ - \n\ - (* Let's create a new type here to be our main message type that is passed around *)\n\ - type msg =\n\ - \ | Increment (* This will be our message to increment the counter *)\n\ - \ | Decrement (* This will be our message to decrement the counter *)\n\ - \ | Reset (* This will be our message to reset the counter to 0 *)\n\ - \ | Set of int (* This will be our message to set the counter to a specific value *)\n\ - \ [@@bs.deriving {accessors}] (* This is a nice quality-of-life addon from Bucklescript, it will generate function names for each constructor name, optional, but nice to cut down on code, this is unused in this example but good to have regardless *)\n\ - \n\ - (* This is optional for such a simple example, but it is good to have an `init` function to define your initial model default values, the model for Counter is just an integer *)\n\ - let init () = 4\n\ - \n\ - (* This is the central message handler, it takes the model as the first argument *)\n\ - let update model = function (* These should be simple enough to be self-explanatory, mutate the model based on the message, easy to read and follow *)\n\ - \ | Increment -> model + 1\n\ - \ | Decrement -> model - 1\n\ - \ | Reset -> 0\n\ - \ | Set v -> v\n\ - \n\ - (* This is just a helper function for the view, a simple function that returns a button based on some argument *)\n\ - let view_button title msg =\n\ - \ button\n\ - \ [ onClick msg\n\ - \ ]\n\ - \ [ text title\n\ - \ ]\n\ - \n\ - (* This is the main callback to generate the virtual-dom.\n\ - \ This returns a virtual-dom node that becomes the view, only changes from call-to-call are set on the real DOM for efficiency, this is also only called once per frame even with many messages sent in within that frame, otherwise does nothing *)\n\ - let view model =\n\ - \ div\n\ - \ []\n\ - \ [ span\n\ - \ [ style \"text-weight\" \"bold\" ]\n\ - \ [ text (string_of_int model) ]\n\ - \ ; br []\n\ - \ ; view_button \"Increment\" Increment\n\ - \ ; br []\n\ - \ ; view_button \"Decrement\" Decrement\n\ - \ ; br []\n\ - \ ; view_button \"Set to 2\" (Set 42)\n\ - \ ; br []\n\ - \ ; if model <> 0 then view_button \"Reset\" Reset else noNode\n\ - \ ]\n\ - \n\ - (* This is the main function, it can be named anything you want but `main` is traditional.\n\ - \ The Program returned here has a set of callbacks that can easily be called from\n\ - \ Bucklescript or from javascript for running this main attached to an element,\n\ - \ or even to pass a message into the event loop. You can even expose the\n\ - \ constructors to the messages to javascript via the above [@@bs.deriving {accessors}]\n\ - \ attribute on the `msg` type or manually, that way even javascript can use it safely. *)\n\ - let main =\n\ - \ beginnerProgram { (* The beginnerProgram just takes a set model state and the update and view functions *)\n\ - \ model = init (); (* Since model is a set value here, we call our init function to generate that value *)\n\ - \ update;\n\ - \ view;\n\ - \ }" - ); - File("main.ml", - "\n\ - \n\ - \n\ - Js.Global.setTimeout\n\ - \ (fun _ -> \n\ - \ Demo.main (Web.Document.getElementById \"my-element\") () \n\ - \ |. ignore\n\ - \ ) \n\ - 0" - ) - ]); - File("watcher.js", - "\n\ - \n\ - var wsReloader;\n\ - var LAST_SUCCESS_BUILD_STAMP = (localStorage.getItem('LAST_SUCCESS_BUILD_STAMP') || 0)\n\ - var WS_PORT = 9999; // configurable\n\ - \n\ - function setUpWebScoket() {\n\ - \ if (wsReloader == null || wsReloader.readyState !== 1) {\n\ - \ try {\n\ - \ wsReloader = new WebSocket(`ws://${window.location.hostname}:${WS_PORT}`)\n\ - \ wsReloader.onmessage = (msg) => {\n\ - \ var newData = JSON.parse(msg.data).LAST_SUCCESS_BUILD_STAMP\n\ - \ if (newData > LAST_SUCCESS_BUILD_STAMP) {\n\ - \ LAST_SUCCESS_BUILD_STAMP = newData\n\ - \ localStorage.setItem('LAST_SUCCESS_BUILD_STAMP', LAST_SUCCESS_BUILD_STAMP)\n\ - \ location.reload(true)\n\ - \ }\n\ - \n\ - \ }\n\ - \ } catch (exn) {\n\ - \ console.error(\"web socket failed connect\")\n\ - \ }\n\ - \ }\n\ - };\n\ - \n\ - setUpWebScoket();\n\ - setInterval(setUpWebScoket, 2000);" - ) - ]) -]) \ No newline at end of file diff --git a/jscomp/bsb/bsb_templates.mli b/jscomp/bsb/bsb_templates.mli deleted file mode 100644 index e29db93cb8..0000000000 --- a/jscomp/bsb/bsb_templates.mli +++ /dev/null @@ -1,6 +0,0 @@ -type node = - | Dir of string * node list - | File of string * string - - -val root : node list \ No newline at end of file diff --git a/jscomp/bsb/bsb_theme_init.ml b/jscomp/bsb/bsb_theme_init.ml deleted file mode 100644 index a65fa296df..0000000000 --- a/jscomp/bsb/bsb_theme_init.ml +++ /dev/null @@ -1,136 +0,0 @@ -(* Copyright (C) 2015-2016 Bloomberg Finance L.P. - * Copyright (C) 2017 - Hongbo Zhang, Authors of ReScript - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - -type file_type = Directory | Non_directory_file | Non_exists - -let classify_file name = - let exists = Sys.file_exists name in - if exists then if Sys.is_directory name then Directory else Non_directory_file - else Non_exists - -let replace s env : string = - Bsb_regex.global_substitute s ~reg:"\\${rescript:\\([-a-zA-Z0-9]+\\)}" - (fun (_s : string) templates -> - match templates with - | key :: _ -> Hash_string.find_exn env key - | _ -> assert false) - -let ( // ) = Filename.concat - -let enter_dir cwd x action = - Unix.chdir x; - match action () with - | exception e -> - Unix.chdir cwd; - raise e - | v -> v - -let mkdir_or_not_if_exists dir = - match classify_file dir with - | Directory -> () - | Non_directory_file -> - Format.fprintf Format.err_formatter - "%s expected to be added as dir but exist file is not a dir" dir - | Non_exists -> Unix.mkdir dir 0o777 - -let rec process_theme_aux env cwd (x : Bsb_templates.node) = - match x with - | File (name, content) -> - let new_file = cwd // name in - if not @@ Sys.file_exists new_file then - Ext_io.write_file new_file (replace content env) - | Dir (current, nodes) -> - let new_cwd = cwd // current in - mkdir_or_not_if_exists new_cwd; - List.iter (fun x -> process_theme_aux env new_cwd x) nodes - -let list_themes () = - Format.fprintf Format.std_formatter "Available themes: @."; - Ext_list.iter Bsb_templates.root (fun x -> - match x with - | Dir (x, _) -> Format.fprintf Format.std_formatter "%s@." x - | _ -> ()) - -(* @raise [Not_found] *) -let process_themes env theme proj_dir (themes : Bsb_templates.node list) = - match - Ext_list.find_first themes (fun x -> - match x with Dir (dir, _) -> dir = theme | File _ -> false) - with - | None -> - list_themes (); - Bsb_arg.bad_arg ("theme " ^ theme ^ " not found") - | Some (Dir (_theme, nodes)) -> - List.iter (fun node -> process_theme_aux env proj_dir node) nodes - | Some _ -> assert false - -(** TODO: run npm link *) -let init_sample_project ~cwd ~theme name = - let env = Hash_string.create 0 in - List.iter - (fun (k, v) -> Hash_string.add env k v) - [ - ("proj-version", "0.1.0"); - ("bs-version", Bs_version.version); - ("bsb", Filename.current_dir_name // "node_modules" // ".bin" // "bsb"); - ("platform", !Bs_version.package_name); - ]; - let action _ = - process_themes env theme Filename.current_dir_name Bsb_templates.root - in - match name with - | "." -> - let name = Filename.basename cwd in - if Ext_namespace.is_valid_npm_package_name name then ( - Hash_string.add env "name" name; - action ()) - else ( - Format.fprintf Format.err_formatter - "@{Invalid package name@} %S@}: the project name must be both \ - a valid npm package name and a valid name as namespace@." - name; - exit 2) - | _ -> - if Ext_namespace.is_valid_npm_package_name name then ( - match classify_file name with - | Non_directory_file -> - Format.fprintf Format.err_formatter - "@{%s already exists but it is not a directory@}@." name; - exit 2 - | Directory -> - Format.fprintf Format.std_formatter - "Adding files into existing dir %s@." name; - Hash_string.add env "name" name; - enter_dir cwd name action - | Non_exists -> - Format.fprintf Format.std_formatter "Making directory %s@." name; - Unix.mkdir name 0o777; - Hash_string.add env "name" name; - enter_dir cwd name action) - else ( - Format.fprintf Format.err_formatter - "@{Invalid package name@} %S.@} The project name must be a \ - valid npm name, thus can't contain upper-case letters, for example." - name; - exit 2) diff --git a/jscomp/bsb/bsb_theme_init.mli b/jscomp/bsb/bsb_theme_init.mli deleted file mode 100644 index 117551ab38..0000000000 --- a/jscomp/bsb/bsb_theme_init.mli +++ /dev/null @@ -1,27 +0,0 @@ -(* Copyright (C) 2015 - 2016 Bloomberg Finance L.P. - * Copyright (C) 2017 - Hongbo Zhang, Authors of ReScript - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - -val init_sample_project : cwd:string -> theme:string -> string -> unit - -val list_themes : unit -> unit diff --git a/jscomp/bsb/templates/basic-reason/.gitignore b/jscomp/bsb/templates/basic-reason/.gitignore deleted file mode 100644 index 8e67d6680b..0000000000 --- a/jscomp/bsb/templates/basic-reason/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.DS_Store -.merlin -.bsb.lock -npm-debug.log -/lib/bs/ -/node_modules/ diff --git a/jscomp/bsb/templates/basic-reason/README.md b/jscomp/bsb/templates/basic-reason/README.md deleted file mode 100644 index 7c78f6f561..0000000000 --- a/jscomp/bsb/templates/basic-reason/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Basic Reason Template - -Hello! This project allows you to quickly get started with ReScript using Reason syntax. If you wanted a more sophisticated version, try the `react` template (`bsb -theme react -init .`). - -# Build - -```bash -# for yarn -yarn build - -# for npm -npm run build -``` - -# Build + Watch - -```bash -# for yarn -yarn start - -# for npm -npm run start -``` - diff --git a/jscomp/bsb/templates/basic-reason/bsconfig.json b/jscomp/bsb/templates/basic-reason/bsconfig.json deleted file mode 100644 index 42b6bb1a20..0000000000 --- a/jscomp/bsb/templates/basic-reason/bsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "sources": { - "dir" : "src", - "subdirs" : true - }, - "package-specs": { - "module": "commonjs", - "in-source": true - }, - "suffix": ".bs.js", - "bs-dependencies": [ - - ], - "warnings": { - "error" : "+101" - }, - "namespace": true, - "refmt": 3 -} diff --git a/jscomp/bsb/templates/basic-reason/package.json b/jscomp/bsb/templates/basic-reason/package.json deleted file mode 100644 index da0970c287..0000000000 --- a/jscomp/bsb/templates/basic-reason/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "scripts": { - "build": "bsb -make-world", - "start": "bsb -make-world -w", - "clean": "bsb -clean-world" - }, - "keywords": [ - "ReScript" - ], - "author": "", - "license": "MIT", - "devDependencies": { - "${rescript:platform}": "^${rescript:bs-version}" - } -} diff --git a/jscomp/bsb/templates/basic-reason/src/Demo.res b/jscomp/bsb/templates/basic-reason/src/Demo.res deleted file mode 100644 index dec7fe8880..0000000000 --- a/jscomp/bsb/templates/basic-reason/src/Demo.res +++ /dev/null @@ -1 +0,0 @@ -Js.log("Hello, ReScript!") diff --git a/jscomp/bsb/templates/basic/.gitignore b/jscomp/bsb/templates/basic/.gitignore deleted file mode 100644 index 1dd11f93b0..0000000000 --- a/jscomp/bsb/templates/basic/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ -*.exe -*.obj -*.out -*.compile -*.native -*.byte -*.cmo -*.annot -*.cmi -*.cmx -*.cmt -*.cmti -*.cma -*.a -*.cmxa -*.obj -*~ -*.annot -*.cmj -*.bak -lib/bs -*.mlast -*.mliast -.vscode -.merlin -.bsb.lock -/node_modules/ diff --git a/jscomp/bsb/templates/basic/README.md b/jscomp/bsb/templates/basic/README.md deleted file mode 100644 index b20ab1bade..0000000000 --- a/jscomp/bsb/templates/basic/README.md +++ /dev/null @@ -1,13 +0,0 @@ - - -# Build -``` -npm run build -``` - -# Watch - -``` -npm run watch -``` - diff --git a/jscomp/bsb/templates/basic/bsconfig.json b/jscomp/bsb/templates/basic/bsconfig.json deleted file mode 100644 index 0ad75900e9..0000000000 --- a/jscomp/bsb/templates/basic/bsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "sources": { - "dir" : "src", - "subdirs" : true - }, - "package-specs": { - "module": "es6", - "in-source": true - }, - "suffix": ".bs.js" -} diff --git a/jscomp/bsb/templates/basic/package.json b/jscomp/bsb/templates/basic/package.json deleted file mode 100644 index 279b898cf6..0000000000 --- a/jscomp/bsb/templates/basic/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "scripts": { - "clean": "rescript clean", - "build": "rescript build", - "watch": "rescript build -w" - }, - "keywords": [ - "ReScript" - ], - "author": "", - "license": "MIT", - "devDependencies": { - "${rescript:platform}": "^${rescript:bs-version}" - } -} \ No newline at end of file diff --git a/jscomp/bsb/templates/basic/src/Demo.res b/jscomp/bsb/templates/basic/src/Demo.res deleted file mode 100644 index fcea153b27..0000000000 --- a/jscomp/bsb/templates/basic/src/Demo.res +++ /dev/null @@ -1,2 +0,0 @@ - -Js.log("Hello, ReScript") \ No newline at end of file diff --git a/jscomp/bsb/templates/generator/.gitignore b/jscomp/bsb/templates/generator/.gitignore deleted file mode 100644 index 1dd11f93b0..0000000000 --- a/jscomp/bsb/templates/generator/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ -*.exe -*.obj -*.out -*.compile -*.native -*.byte -*.cmo -*.annot -*.cmi -*.cmx -*.cmt -*.cmti -*.cma -*.a -*.cmxa -*.obj -*~ -*.annot -*.cmj -*.bak -lib/bs -*.mlast -*.mliast -.vscode -.merlin -.bsb.lock -/node_modules/ diff --git a/jscomp/bsb/templates/generator/README.md b/jscomp/bsb/templates/generator/README.md deleted file mode 100644 index 1c02d2a072..0000000000 --- a/jscomp/bsb/templates/generator/README.md +++ /dev/null @@ -1,16 +0,0 @@ - - -# Build -``` -npm run build -``` - -# Watch - -``` -npm run watch -``` - - -# Editor -If you use `vscode`, Press `Windows + Shift + B` it will build automatically \ No newline at end of file diff --git a/jscomp/bsb/templates/generator/bsconfig.json b/jscomp/bsb/templates/generator/bsconfig.json deleted file mode 100644 index efa3b7a3d8..0000000000 --- a/jscomp/bsb/templates/generator/bsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "sources": { - "dir": "src", - "generators": [{ - "name": "cpp", - "edge": ["test.ml", ":", "test.cpp.ml"] - }], - "subdirs": true - }, - "generators": [{ - "name" : "cpp", - "command": "sed 's/OCAML/3/' $in > $out" - }], - "bs-dependencies" : [ - ] -} \ No newline at end of file diff --git a/jscomp/bsb/templates/generator/package.json b/jscomp/bsb/templates/generator/package.json deleted file mode 100644 index 75615943fa..0000000000 --- a/jscomp/bsb/templates/generator/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "scripts": { - "clean": "bsb -clean-world", - "build": "bsb -make-world", - "watch": "bsb -make-world -w" - }, - "keywords": [ - "ReScript" - ], - "author": "", - "license": "MIT", - "devDependencies": { - "${rescript:platform}": "^${rescript:bs-version}" - } -} diff --git a/jscomp/bsb/templates/generator/src/demo.ml b/jscomp/bsb/templates/generator/src/demo.ml deleted file mode 100644 index 26bac43b25..0000000000 --- a/jscomp/bsb/templates/generator/src/demo.ml +++ /dev/null @@ -1,3 +0,0 @@ - - -let () = Js.log "Hello, ReScript" \ No newline at end of file diff --git a/jscomp/bsb/templates/generator/src/test.cpp.ml b/jscomp/bsb/templates/generator/src/test.cpp.ml deleted file mode 100644 index 9cce515143..0000000000 --- a/jscomp/bsb/templates/generator/src/test.cpp.ml +++ /dev/null @@ -1,10 +0,0 @@ - -(* -#define FS_VAL(name,ty) external name : ty = "" [@@bs.module "fs"] - - -FS_VAL(readdirSync, string -> string array) - *) - - - let ocaml = OCAML \ No newline at end of file diff --git a/jscomp/bsb/templates/minimal/.gitignore b/jscomp/bsb/templates/minimal/.gitignore deleted file mode 100644 index 55e500e2f1..0000000000 --- a/jscomp/bsb/templates/minimal/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.DS_Store -.merlin -.bsb.lock -npm-debug.log -/lib/bs/ -/node_modules/ \ No newline at end of file diff --git a/jscomp/bsb/templates/minimal/README.md b/jscomp/bsb/templates/minimal/README.md deleted file mode 100644 index 3ff33afdda..0000000000 --- a/jscomp/bsb/templates/minimal/README.md +++ /dev/null @@ -1,2 +0,0 @@ - - # ${rescript:name} \ No newline at end of file diff --git a/jscomp/bsb/templates/minimal/bsconfig.json b/jscomp/bsb/templates/minimal/bsconfig.json deleted file mode 100644 index 0cb4190817..0000000000 --- a/jscomp/bsb/templates/minimal/bsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "${rescript:name}", - "sources": { - "dir": "src", - "subdirs": true - } -} \ No newline at end of file diff --git a/jscomp/bsb/templates/minimal/package.json b/jscomp/bsb/templates/minimal/package.json deleted file mode 100644 index 61a1c53cd2..0000000000 --- a/jscomp/bsb/templates/minimal/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "scripts": { - "clean": "bsb -clean-world", - "build": "bsb -make-world", - "start": "bsb -make-world -w" - }, - "keywords": [ - "ReScript" - ], - "author": "", - "license": "MIT", - "devDependencies": { - "${rescript:platform}": "^${rescript:bs-version}" - } -} diff --git a/jscomp/bsb/templates/minimal/src/main.ml b/jscomp/bsb/templates/minimal/src/main.ml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/jscomp/bsb/templates/node/.gitignore b/jscomp/bsb/templates/node/.gitignore deleted file mode 100644 index 1dd11f93b0..0000000000 --- a/jscomp/bsb/templates/node/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ -*.exe -*.obj -*.out -*.compile -*.native -*.byte -*.cmo -*.annot -*.cmi -*.cmx -*.cmt -*.cmti -*.cma -*.a -*.cmxa -*.obj -*~ -*.annot -*.cmj -*.bak -lib/bs -*.mlast -*.mliast -.vscode -.merlin -.bsb.lock -/node_modules/ diff --git a/jscomp/bsb/templates/node/README.md b/jscomp/bsb/templates/node/README.md deleted file mode 100644 index f873629ed1..0000000000 --- a/jscomp/bsb/templates/node/README.md +++ /dev/null @@ -1,16 +0,0 @@ - - -# Build -``` -npm run build -``` - -# Watch - -``` -npm run watch -``` - - -# Editor -If you use `vscode`, Press `Windows + Shift + B` it will build automatically diff --git a/jscomp/bsb/templates/node/bsconfig.json b/jscomp/bsb/templates/node/bsconfig.json deleted file mode 100644 index 2cde1448d1..0000000000 --- a/jscomp/bsb/templates/node/bsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "sources": { - "dir": "src", - "subdirs" : true - }, - "package-specs": { - "module": "commonjs", - "in-source": true - }, - "suffix": ".bs.js", - "bs-dependencies": [ - ] -} \ No newline at end of file diff --git a/jscomp/bsb/templates/node/package.json b/jscomp/bsb/templates/node/package.json deleted file mode 100644 index 75615943fa..0000000000 --- a/jscomp/bsb/templates/node/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "scripts": { - "clean": "bsb -clean-world", - "build": "bsb -make-world", - "watch": "bsb -make-world -w" - }, - "keywords": [ - "ReScript" - ], - "author": "", - "license": "MIT", - "devDependencies": { - "${rescript:platform}": "^${rescript:bs-version}" - } -} diff --git a/jscomp/bsb/templates/node/src/demo.ml b/jscomp/bsb/templates/node/src/demo.ml deleted file mode 100644 index 26bac43b25..0000000000 --- a/jscomp/bsb/templates/node/src/demo.ml +++ /dev/null @@ -1,3 +0,0 @@ - - -let () = Js.log "Hello, ReScript" \ No newline at end of file diff --git a/jscomp/bsb/templates/react-hooks/.gitignore b/jscomp/bsb/templates/react-hooks/.gitignore deleted file mode 100644 index 9c32a28e49..0000000000 --- a/jscomp/bsb/templates/react-hooks/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.DS_Store -.merlin -.bsb.lock -npm-debug.log -/lib/bs/ -/node_modules/ -/bundleOutput/ \ No newline at end of file diff --git a/jscomp/bsb/templates/react-hooks/README.md b/jscomp/bsb/templates/react-hooks/README.md deleted file mode 100644 index e55514ec69..0000000000 --- a/jscomp/bsb/templates/react-hooks/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# ReasonReact Template & Examples - -This is: -- A template for your new ReasonReact project. -- A collection of thin examples illustrating ReasonReact usage. -- Extra helper documentation for ReasonReact (full ReasonReact docs [here](https://reasonml.github.io/reason-react/)). - -`src` contains 4 sub-folders, each an independent, self-contained ReasonReact example. Feel free to delete any of them and shape this into your project! This template's more malleable than you might be used to =). - -The point of this template and examples is to let you understand and personally tweak the entirely of it. We **don't** give you an opaque, elaborate mega build setup just to put some boxes on the screen. It strikes to stay transparent, learnable, and simple. You're encouraged to read every file; it's a great feeling, having the full picture of what you're using and being able to touch any part. - -## Run - -```sh -npm install -npm run server -# in a new tab -npm start -``` - -Open a new web page to `http://localhost:8000/`. Change any `.re` file in `src` to see the page auto-reload. **You don't need any bundler when you're developing**! - -**How come we don't need any bundler during development**? We highly encourage you to open up `index.html` to check for yourself! - -# Features Used - -| | Blinking Greeting | Reducer from ReactJS Docs | Fetch Dog Pictures | Reason Using JS Using Reason | -|---------------------------|-------------------|---------------------------|--------------------|------------------------------| -| No props | | ✓ | | | -| Has props | | | | ✓ | -| Children props | ✓ | | | | -| No state | | | | ✓ | -| Has state | ✓ | | ✓ | | -| Has state with useReducer | | ✓ | | | -| ReasonReact using ReactJS | | | | ✓ | -| ReactJS using ReasonReact | | | | ✓ | -| useEffect | ✓ | | ✓ | | -| Dom attribute | ✓ | ✓ | | ✓ | -| Styling | ✓ | ✓ | ✓ | ✓ | -| React.array | | | ✓ | | - -# Bundle for Production - -We've included a convenience `UNUSED_webpack.config.js`, in case you want to ship your project to production. You can rename and/or remove that in favor of other bundlers, e.g. Rollup. - -We've also provided a barebone `indexProduction.html`, to serve your bundle. - -```sh -npm install webpack webpack-cli -# rename file -mv UNUSED_webpack.config.js webpack.config.js -# call webpack to bundle for production -./node_modules/.bin/webpack -open indexProduction.html -``` - -# Handle Routing Yourself - -To serve the files, this template uses a minimal dependency called `moduleserve`. A URL such as `localhost:8000/scores/john` resolves to the file `scores/john.html`. If you'd like to override this and handle URL resolution yourself, change the `server` command in `package.json` from `moduleserve ./ --port 8000` to `moduleserve ./ --port 8000 --spa` (for "single page application"). This will make `moduleserve` serve the default `index.html` for any URL. Since `index.html` loads `Index.bs.js`, you can grab hold of the URL in the corresponding `Index.re` and do whatever you want. - -By the way, ReasonReact comes with a small [router](https://reasonml.github.io/reason-react/docs/en/router) you might be interested in. diff --git a/jscomp/bsb/templates/react-hooks/UNUSED_webpack.config.js b/jscomp/bsb/templates/react-hooks/UNUSED_webpack.config.js deleted file mode 100644 index 3260e8f645..0000000000 --- a/jscomp/bsb/templates/react-hooks/UNUSED_webpack.config.js +++ /dev/null @@ -1,14 +0,0 @@ -const path = require('path'); - -module.exports = { - entry: './src/Index.bs.js', - // If you ever want to use webpack during development, change 'production' - // to 'development' as per webpack documentation. Again, you don't have to - // use webpack or any other bundler during development! Recheck README if - // you didn't know this - mode: 'production', - output: { - path: path.join(__dirname, "bundleOutput"), - filename: 'index.js', - }, -}; \ No newline at end of file diff --git a/jscomp/bsb/templates/react-hooks/bsconfig.json b/jscomp/bsb/templates/react-hooks/bsconfig.json deleted file mode 100644 index 0e4cba1a68..0000000000 --- a/jscomp/bsb/templates/react-hooks/bsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "${rescript:name}", - "reason": { - "react-jsx": 3 - }, - "sources": { - "dir" : "src", - "subdirs" : true - }, - "bsc-flags": ["-bs-super-errors", "-bs-no-version-header"], - "package-specs": [{ - "module": "commonjs", - "in-source": true - }], - "suffix": ".bs.js", - "namespace": true, - "bs-dependencies": [ - "reason-react" - ], - "refmt": 3 -} diff --git a/jscomp/bsb/templates/react-hooks/index.html b/jscomp/bsb/templates/react-hooks/index.html deleted file mode 100644 index 94689a3b9c..0000000000 --- a/jscomp/bsb/templates/react-hooks/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - ReasonReact Examples - - - - - - - - - - diff --git a/jscomp/bsb/templates/react-hooks/indexProduction.html b/jscomp/bsb/templates/react-hooks/indexProduction.html deleted file mode 100644 index 1597bfa6c6..0000000000 --- a/jscomp/bsb/templates/react-hooks/indexProduction.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - ReasonReact Examples - - - - - diff --git a/jscomp/bsb/templates/react-hooks/package.json b/jscomp/bsb/templates/react-hooks/package.json deleted file mode 100644 index d1e6aeb37a..0000000000 --- a/jscomp/bsb/templates/react-hooks/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "scripts": { - "build": "bsb -make-world", - "start": "bsb -make-world -w -ws _ ", - "clean": "bsb -clean-world", - "server": "moduleserve ./ --port 8000", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "ReScript", - "ReasonReact", - "reason-react" - ], - "author": "", - "license": "MIT", - "dependencies": { - "react": "^16.8.1", - "react-dom": "^16.8.1", - "reason-react": ">=0.7.1" - }, - "devDependencies": { - "${rescript:platform}": "^${rescript:bs-version}", - "moduleserve": "^0.9.0" - } -} diff --git a/jscomp/bsb/templates/react-hooks/src/BlinkingGreeting/BlinkingGreeting.res b/jscomp/bsb/templates/react-hooks/src/BlinkingGreeting/BlinkingGreeting.res deleted file mode 100644 index 70d0d28d73..0000000000 --- a/jscomp/bsb/templates/react-hooks/src/BlinkingGreeting/BlinkingGreeting.res +++ /dev/null @@ -1,20 +0,0 @@ -@react.component -let make = (~children) => { - let (show, setShow) = React.useState(() => true) - - // Notice that instead of `useEffect`, we have `useEffect0`. See - // reasonml.github.io/reason-react/docs/en/components#hooks for more info - React.useEffect0(() => { - let id = Js.Global.setInterval(() => setShow(previousShow => !previousShow), 1000) - - Some(() => Js.Global.clearInterval(id)) - }) - - let style = if show { - ReactDOMRe.Style.make(~opacity="1", ~transition="opacity 1s", ()) - } else { - ReactDOMRe.Style.make(~opacity="0", ~transition="opacity 1s", ()) - } - -
children
-} diff --git a/jscomp/bsb/templates/react-hooks/src/ExampleStyles.res b/jscomp/bsb/templates/react-hooks/src/ExampleStyles.res deleted file mode 100644 index d9663ab055..0000000000 --- a/jscomp/bsb/templates/react-hooks/src/ExampleStyles.res +++ /dev/null @@ -1,44 +0,0 @@ -let reasonReactBlue = "#48a9dc" - -// The {j|...|j} feature is just string interpolation, from -// bucklescript.github.io/docs/en/interop-cheatsheet#string-unicode-interpolation -// This allows us to conveniently write CSS, together with variables, by -// constructing a string -let style = j` - body { - background-color: rgb(224, 226, 229); - display: flex; - flex-direction: column; - align-items: center; - } - button { - background-color: white; - color: $reasonReactBlue; - box-shadow: 0 0 0 1px $reasonReactBlue; - border: none; - padding: 8px; - font-size: 16px; - } - button:active { - background-color: $reasonReactBlue; - color: white; - } - .container { - margin: 12px 0px; - box-shadow: 0px 4px 16px rgb(200, 200, 200); - width: 720px; - border-radius: 12px; - font-family: sans-serif; - } - .containerTitle { - background-color: rgb(242, 243, 245); - border-radius: 12px 12px 0px 0px; - padding: 12px; - font-weight: bold; - } - .containerContent { - background-color: white; - padding: 16px; - border-radius: 0px 0px 12px 12px; - } -` diff --git a/jscomp/bsb/templates/react-hooks/src/FetchedDogPictures/FetchedDogPictures.res b/jscomp/bsb/templates/react-hooks/src/FetchedDogPictures/FetchedDogPictures.res deleted file mode 100644 index c4e4e53a0e..0000000000 --- a/jscomp/bsb/templates/react-hooks/src/FetchedDogPictures/FetchedDogPictures.res +++ /dev/null @@ -1,70 +0,0 @@ -@val external fetch: string => Js.Promise.t<'a> = "fetch" - -type state = - | LoadingDogs - | ErrorFetchingDogs - | LoadedDogs(array) - -@react.component -let make = () => { - let (state, setState) = React.useState(() => LoadingDogs) - - // Notice that instead of `useEffect`, we have `useEffect0`. See - // reasonml.github.io/reason-react/docs/en/components#hooks for more info - React.useEffect0(() => { - { - open Js.Promise - fetch("https://dog.ceo/api/breeds/image/random/3") - |> then_(response => response["json"]()) - |> then_(jsonResponse => { - setState(_previousState => LoadedDogs(jsonResponse["message"])) - Js.Promise.resolve() - }) - |> catch(_err => { - setState(_previousState => ErrorFetchingDogs) - Js.Promise.resolve() - }) - |> ignore - } - - // Returning None, instead of Some(() => ...), means we don't have any - // cleanup to do before unmounting. That's not 100% true. We should - // technically cancel the promise. Unofortunately, there's currently no - // way to cancel a promise. Promises in general should be way less used - // for React components; but since folks do use them, we provide such an - // example here. In reality, this fetch should just be a plain callback, - // with a cancellation API - None - }) - -
- {switch state { - | ErrorFetchingDogs => React.string("An error occurred!") - | LoadingDogs => React.string("Loading...") - | LoadedDogs(dogs) => - dogs - ->Belt.Array.mapWithIndex((i, dog) => { - let imageStyle = ReactDOMRe.Style.make( - ~height="120px", - ~width="100%", - ~marginRight=i === Js.Array.length(dogs) - 1 ? "0px" : "8px", - ~borderRadius="8px", - ~boxShadow="0px 4px 16px rgb(200, 200, 200)", - ~backgroundSize="cover", - ~backgroundImage=j`url($dog)`, - ~backgroundPosition="center", - (), - ) -
- }) - ->React.array - }} -
-} diff --git a/jscomp/bsb/templates/react-hooks/src/Index.res b/jscomp/bsb/templates/react-hooks/src/Index.res deleted file mode 100644 index 987e18bbcd..0000000000 --- a/jscomp/bsb/templates/react-hooks/src/Index.res +++ /dev/null @@ -1,40 +0,0 @@ -// Entry point - -@val external document: {..} = "document" - -// We're using raw DOM manipulations here, to avoid making you read -// ReasonReact when you might precisely be trying to learn it for the first -// time through the examples later. -let style = document["createElement"]("style") -document["head"]["appendChild"](style) -style["innerHTML"] = ExampleStyles.style - -let makeContainer = text => { - let container = document["createElement"]("div") - container["className"] = "container" - - let title = document["createElement"]("div") - title["className"] = "containerTitle" - title["innerText"] = text - - let content = document["createElement"]("div") - content["className"] = "containerContent" - - let () = container["appendChild"](title) - let () = container["appendChild"](content) - let () = document["body"]["appendChild"](container) - - content -} - -// All 4 examples. -ReactDOMRe.render( - {React.string("Hello!")} , - makeContainer("Blinking Greeting"), -) - -ReactDOMRe.render(, makeContainer("Reducer From ReactJS Docs")) - -ReactDOMRe.render(, makeContainer("Fetched Dog Pictures")) - -ReactDOMRe.render(, makeContainer("Reason Using JS Using Reason")) diff --git a/jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReactJSCard.js b/jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReactJSCard.js deleted file mode 100644 index 6e71d726a3..0000000000 --- a/jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReactJSCard.js +++ /dev/null @@ -1,31 +0,0 @@ -// In this Interop example folder, we have: -// - A ReasonReact component, ReasonReactCard.re -// - Used by a ReactJS component, ReactJSCard.js (this file) -// - ReactJSCard.js can be used by ReasonReact, through bindings in ReasonUsingJSUsingReason.re -// - ReasonUsingJSUsingReason.re is used by Index.re - -var ReactDOM = require('react-dom'); -var React = require('react'); - -var ReasonReactCard = require('./ReasonReactCard.bs').make; - -var ReactJSComponent = function() { - let backgroundColor = "rgba(0, 0, 0, 0.05)"; - let padding = "12px"; - - // We're not using JSX here, to avoid folks needing to install the related - // React toolchains just for this example. - //
- //
This is a ReactJS card
- // - //
- return React.createElement( - "div", - {style: {backgroundColor, padding, borderRadius: "8px"}}, - React.createElement("div", {style: {marginBottom: "8px"}}, "This is a ReactJS card"), - React.createElement(ReasonReactCard, {style: {backgroundColor, padding, borderRadius: "4px"}}), - ) -}; -ReactJSComponent.displayName = "MyBanner"; - -module.exports = ReactJSComponent; diff --git a/jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReasonReactCard.res b/jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReasonReactCard.res deleted file mode 100644 index fe4cce0599..0000000000 --- a/jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReasonReactCard.res +++ /dev/null @@ -1,8 +0,0 @@ -// In this Interop example folder, we have: -// - A ReasonReact component, ReasonReactCard.re (this file) -// - Used by a ReactJS component, ReactJSCard.js -// - ReactJSCard.js can be used by ReasonReact, through bindings in ReasonUsingJSUsingReason.re -// - ReasonUsingJSUsingReason.re is used by Index.re - -@react.component -let make = (~style) =>
{React.string("This is a ReasonReact card")}
diff --git a/jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReasonUsingJSUsingReason.res b/jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReasonUsingJSUsingReason.res deleted file mode 100644 index bb770e16b0..0000000000 --- a/jscomp/bsb/templates/react-hooks/src/ReasonUsingJSUsingReason/ReasonUsingJSUsingReason.res +++ /dev/null @@ -1,10 +0,0 @@ -// In this Interop example folder, we have: -// - A ReasonReact component, ReasonReactCard.re -// - Used by a ReactJS component, ReactJSCard.js -// - ReactJSCard.js can be used by ReasonReact, through bindings in ReasonUsingJSUsingReason.re (this file) -// - ReasonUsingJSUsingReason.re is used by Index.re - -// All you need to do to use a ReactJS component in ReasonReact, is to write the lines below! -// reasonml.github.io/reason-react/docs/en/components#import-from-js -@react.component @module -external make: unit => React.element = "./ReactJSCard" diff --git a/jscomp/bsb/templates/react-hooks/src/ReducerFromReactJSDocs/ReducerFromReactJSDocs.res b/jscomp/bsb/templates/react-hooks/src/ReducerFromReactJSDocs/ReducerFromReactJSDocs.res deleted file mode 100644 index 0bd9160d83..0000000000 --- a/jscomp/bsb/templates/react-hooks/src/ReducerFromReactJSDocs/ReducerFromReactJSDocs.res +++ /dev/null @@ -1,45 +0,0 @@ -// This is the ReactJS documentation's useReducer example, directly ported over -// https://reactjs.org/docs/hooks-reference.html#usereducer - -// A little extra we've put, because the ReactJS example has no styling -let leftButtonStyle = ReactDOMRe.Style.make(~borderRadius="4px 0px 0px 4px", ~width="48px", ()) -let rightButtonStyle = ReactDOMRe.Style.make(~borderRadius="0px 4px 4px 0px", ~width="48px", ()) -let containerStyle = ReactDOMRe.Style.make( - ~display="flex", - ~alignItems="center", - ~justifyContent="space-between", - (), -) - -// Record and variant need explicit declarations. -type state = {count: int} - -type action = - | Increment - | Decrement - -let initialState = {count: 0} - -let reducer = (state, action) => - switch action { - | Increment => {count: state.count + 1} - | Decrement => {count: state.count - 1} - } - -@react.component -let make = () => { - let (state, dispatch) = React.useReducer(reducer, initialState) - - // We can use a fragment here, but we don't, because we want to style the counter -
-
{React.string("Count: ")} {React.string(string_of_int(state.count))}
-
- - -
-
-} diff --git a/jscomp/bsb/templates/react-hooks/watcher.js b/jscomp/bsb/templates/react-hooks/watcher.js deleted file mode 100644 index f35e93ad3e..0000000000 --- a/jscomp/bsb/templates/react-hooks/watcher.js +++ /dev/null @@ -1,46 +0,0 @@ -// This is our simple, robust watcher. It hooks into the ReScript build -// system to listen for build events. -// See package.json's `start` script and `./node_modules/.bin/bsb --help` - -// Btw, if you change this file and reload the page, your browser cache -// _might_ not pick up the new version. If you're in Chrome, do Force Reload. - -var websocketReloader; -var LAST_SUCCESS_BUILD_STAMP = - localStorage.getItem("LAST_SUCCESS_BUILD_STAMP") || 0; -// package.json's `start` script's `bsb -ws _` means it'll pipe build events -// through a websocket connection to a default port of 9999. This is -// configurable, e.g. `-ws 5000` -var webSocketPort = 9999; - -function setUpWebSocket() { - if (websocketReloader == null || websocketReloader.readyState !== 1) { - try { - websocketReloader = new WebSocket( - `ws://${window.location.hostname}:${webSocketPort}` - ); - websocketReloader.onmessage = (message) => { - var newData = JSON.parse(message.data).LAST_SUCCESS_BUILD_STAMP; - if (newData > LAST_SUCCESS_BUILD_STAMP) { - LAST_SUCCESS_BUILD_STAMP = newData; - localStorage.setItem( - "LAST_SUCCESS_BUILD_STAMP", - LAST_SUCCESS_BUILD_STAMP - ); - // Refresh the page! This will naturally re-run everything, - // including our moduleserve which will re-resolve all the modules. - // No stable build! - location.reload(true); - } - }; - } catch (exn) { - console.error( - "The watcher tried to connect to web socket, but failed. Here's the message:" - ); - console.error(exn); - } - } -} - -setUpWebSocket(); -setInterval(setUpWebSocket, 2000); diff --git a/jscomp/bsb/templates/react-starter/.gitignore b/jscomp/bsb/templates/react-starter/.gitignore deleted file mode 100644 index eab1b40407..0000000000 --- a/jscomp/bsb/templates/react-starter/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.DS_Store -.merlin -.bsb.lock -npm-debug.log -/lib/bs/ -/node_modules/ -*.bs.js diff --git a/jscomp/bsb/templates/react-starter/README.md b/jscomp/bsb/templates/react-starter/README.md deleted file mode 100644 index b8b6bcb89c..0000000000 --- a/jscomp/bsb/templates/react-starter/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Reason react starter - -## Run Project - -```sh -npm install -npm start -# in another tab -npm run server -``` - -View the app in the browser at http://localhost:8000. Running in this environment provides hot reloading and support for routing; just edit and save the file and the browser will automatically refresh. - -To use a port other than 8000 set the `PORT` environment variable (`PORT=8080 npm run server`). - -## Build for Production - -```sh -npm run clean -npm run build -npm run webpack:production -``` - -This will replace the development artifact `build/Index.js` for an optimized version as well as copy `src/index.html` into `build/`. You can then deploy the contents of the `build` directory (`index.html` and `Index.js`). - -**To enable dead code elimination**, change `bsconfig.json`'s `package-specs` `module` from `"commonjs"` to `"es6"`. Then re-run the above 2 commands. This will allow Webpack to remove unused code. diff --git a/jscomp/bsb/templates/react-starter/bsconfig.json b/jscomp/bsb/templates/react-starter/bsconfig.json deleted file mode 100644 index 02c1a036d1..0000000000 --- a/jscomp/bsb/templates/react-starter/bsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "reason-react-starter", - "reason": { - "react-jsx": 3 - }, - "sources": { - "dir": "src", - "subdirs": true - }, - "bsc-flags": ["-bs-super-errors", "-bs-no-version-header"], - "package-specs": [ - { - "module": "commonjs", - "in-source": true - } - ], - "suffix": ".bs.js", - "namespace": true, - "bs-dependencies": ["reason-react"], - "refmt": 3 -} diff --git a/jscomp/bsb/templates/react-starter/package.json b/jscomp/bsb/templates/react-starter/package.json deleted file mode 100644 index 71f7ee9b55..0000000000 --- a/jscomp/bsb/templates/react-starter/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "scripts": { - "build": "bsb -make-world", - "start": "bsb -make-world -w -ws _ ", - "clean": "bsb -clean-world", - "webpack": "webpack -w", - "webpack:production": "NODE_ENV=production webpack", - "server": "webpack-dev-server", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "ReScript", - "ReasonReact", - "reason-react" - ], - "author": "", - "license": "MIT", - "dependencies": { - "react": "^17.0.1", - "react-dom": "^17.0.1", - "reason-react": "^0.9.1" - }, - "devDependencies": { - "${rescript:platform}": "^${rescript:bs-version}", - "css-loader": "^5.0.0", - "html-webpack-plugin": "^4.5.0", - "style-loader": "^2.0.0", - "webpack": "^4.44.2", - "webpack-cli": "^3.3.12", - "webpack-dev-server": "^3.11.0" - } -} diff --git a/jscomp/bsb/templates/react-starter/src/App.res b/jscomp/bsb/templates/react-starter/src/App.res deleted file mode 100644 index 6515e8e5f3..0000000000 --- a/jscomp/bsb/templates/react-starter/src/App.res +++ /dev/null @@ -1,27 +0,0 @@ -type state = {count: int} - -type action = - | Increment - | Decrement - -let initialState = {count: 0} - -let reducer = (state, action) => - switch action { - | Increment => {count: state.count + 1} - | Decrement => {count: state.count - 1} - } - -@react.component -let make = () => { - let (state, dispatch) = React.useReducer(reducer, initialState) - -
- {React.string("Simple counter with reducer")} -
- - {state.count |> string_of_int |> React.string} - -
-
-} diff --git a/jscomp/bsb/templates/react-starter/src/Index.res b/jscomp/bsb/templates/react-starter/src/Index.res deleted file mode 100644 index c5fab6b312..0000000000 --- a/jscomp/bsb/templates/react-starter/src/Index.res +++ /dev/null @@ -1,3 +0,0 @@ -%raw(`require("./index.css")`) - -ReactDOMRe.renderToElementWithId(, "root") diff --git a/jscomp/bsb/templates/react-starter/src/index.css b/jscomp/bsb/templates/react-starter/src/index.css deleted file mode 100644 index 7bfaf86cea..0000000000 --- a/jscomp/bsb/templates/react-starter/src/index.css +++ /dev/null @@ -1,14 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, - sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; -} - -main { - padding: 20px; -} - -.counter { - padding: 20px; - display: inline-block; -} diff --git a/jscomp/bsb/templates/react-starter/src/index.html b/jscomp/bsb/templates/react-starter/src/index.html deleted file mode 100644 index 4b96fba53a..0000000000 --- a/jscomp/bsb/templates/react-starter/src/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Reason react starter - - -
- - - diff --git a/jscomp/bsb/templates/react-starter/webpack.config.js b/jscomp/bsb/templates/react-starter/webpack.config.js deleted file mode 100644 index 292b87262d..0000000000 --- a/jscomp/bsb/templates/react-starter/webpack.config.js +++ /dev/null @@ -1,35 +0,0 @@ -const path = require("path") -const HtmlWebpackPlugin = require("html-webpack-plugin") -const outputDir = path.join(__dirname, "build/") - -const isProd = process.env.NODE_ENV === "production" - -module.exports = { - entry: "./src/Index.bs.js", - mode: isProd ? "production" : "development", - devtool: "source-map", - output: { - path: outputDir, - filename: "Index.js" - }, - plugins: [ - new HtmlWebpackPlugin({ - template: "src/index.html", - inject: false - }) - ], - devServer: { - compress: true, - contentBase: outputDir, - port: process.env.PORT || 8000, - historyApiFallback: true - }, - module: { - rules: [ - { - test: /\.css$/, - use: ["style-loader", "css-loader"] - } - ] - } -} diff --git a/jscomp/bsb/templates/tea/README.md b/jscomp/bsb/templates/tea/README.md deleted file mode 100644 index a387ad8549..0000000000 --- a/jscomp/bsb/templates/tea/README.md +++ /dev/null @@ -1,20 +0,0 @@ - - -# Build -``` -npm run build -``` - -# Watch - -``` -npm run watch -``` - -create a http-server - -``` -npm install -g http-server -``` - -Edit the file and see the changes automatically reloaded in the browser diff --git a/jscomp/bsb/templates/tea/bsconfig.json b/jscomp/bsb/templates/tea/bsconfig.json deleted file mode 100644 index 0baa10e4d7..0000000000 --- a/jscomp/bsb/templates/tea/bsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "tea", - "version": "0.1.0", - "sources": { - "dir" : "src", - "subdirs" : true - }, - "package-specs": { - "module": "commonjs", - "in-source": true - }, - "suffix": ".bs.js", - "bs-dependencies": [ - "bucklescript-tea" - ] -} diff --git a/jscomp/bsb/templates/tea/index.html b/jscomp/bsb/templates/tea/index.html deleted file mode 100644 index 24e9c7da92..0000000000 --- a/jscomp/bsb/templates/tea/index.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - Bucklescript TEA Starter Kit - - - - - -
- - - - - \ No newline at end of file diff --git a/jscomp/bsb/templates/tea/loader.js b/jscomp/bsb/templates/tea/loader.js deleted file mode 100644 index a35f881e5d..0000000000 --- a/jscomp/bsb/templates/tea/loader.js +++ /dev/null @@ -1,484 +0,0 @@ -/* Copyright (C) 2018 Authors of ReScript - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -//@ts-check - -// @ts-ignore -window.process = { env: { NODE_ENV: "dev" } }; - -// local to getPath -var relativeElement = document.createElement("a"); -var baseElement = document.createElement("base"); -document.head.appendChild(baseElement); - -export function BsGetPath(id, parent) { - var oldPath = baseElement.href; - baseElement.href = parent; - relativeElement.href = id; - var result = relativeElement.href; - baseElement.href = oldPath; - return result; -} -/** - * - * Given current link and its parent, return the new link - * @param {string} id - * @param {string} parent - * @return {string} - */ -function getPathWithJsSuffix(id, parent) { - var oldPath = baseElement.href; - baseElement.href = parent; - relativeElement.href = id; - var result = addSuffixJsIfNot(relativeElement.href); - baseElement.href = oldPath; - return result; -} - -/** - * - * @param {string} x - */ -function addSuffixJsIfNot(x) { - if (x.endsWith(".js")) { - return x; - } else { - return x + ".js"; - } -} - -var falsePromise = Promise.resolve(false); -var fetchConfig = { cache: "no-cache" }; -// package.json semantics -// a string to module object -// from url -> module object -// Modules : Map -// fetch the link: -// - if it is already fetched before, return the stored promise -// otherwise create the promise which will be filled with the text if successful -// or filled with boolean false when failed -var MODULES = new Map(); -function cachedFetch(link) { - // console.info(link) - var linkResult = MODULES.get(link); - if (linkResult) { - return linkResult; - } else { - var p = fetch(link, fetchConfig).then((resp) => { - if (resp.ok) { - return resp.text(); - } else { - return falsePromise; - } - }); - - MODULES.set(link, p); - return p; - } -} - -// from location id -> url -// There are two rounds of caching: -// 1. if location and relative path is hit, no need to run -// 2. if location and relative path is not hit, but the resolved link is hit, no need -// for network request -/** - * @type {Map > > } - */ -var IDLocations = new Map(); - -/** - * @type {Map > } - */ -var SyncedIDLocations = new Map(); -// Its value is an object -// { link : String } -// We will first mark it when visiting (to avoid duplicated computation) -// and populate its link later - -/** - * - * @param {string} id - * @param {string} location - */ -function getIdLocation(id, location) { - var idMap = IDLocations.get(location); - if (idMap) { - return idMap.get(id); - } -} - -/** - * - * @param {string} id - * @param {string} location - */ -function getIdLocationSync(id, location) { - var idMap = SyncedIDLocations.get(location); - if (idMap) { - return idMap.get(id); - } -} - -function countIDLocations() { - var count = 0; - for (let [k, vv] of IDLocations) { - for (let [kv, v] of vv) { - count += 1; - } - } - console.log(count, "modules loaded"); -} - -/** - * - * @param {string} id - * @param {string} location - * @param {Function} cb - * @returns Promise - */ -function visitIdLocation(id, location, cb) { - var result; - var idMap = IDLocations.get(location); - if (idMap && (result = idMap.get(id))) { - return result; - } else { - result = new Promise((resolve) => { - return cb().then((res) => { - var idMap = SyncedIDLocations.get(location); - if (idMap) { - idMap.set(id, res); - } else { - SyncedIDLocations.set(location, new Map([[id, res]])); - } - return resolve(res); - }); - }); - if (idMap) { - idMap.set(id, result); - } else { - IDLocations.set(location, new Map([[id, result]])); - } - return result; - } -} - -/** - * - * @param {string} text - * @return {string[]} - */ -function getDeps(text) { - var deps = []; - text.replace( - /(\/\*[\w\W]*?\*\/|\/\/[^\n]*|[.$]r)|\brequire\s*\(\s*["']([^"']*)["']\s*\)/g, - function (_, ignore, id) { - if (!ignore) deps.push(id); - } - ); - return deps; -} - -// By using a named "eval" most browsers will execute in the global scope. -// http://www.davidflanagan.com/2010/12/global-eval-in.html -var globalEval = eval; - -// function parentURL(url) { -// if (url.endsWith('/')) { -// return url + '../' -// } else { -// return url + '/../' -// } -// } - -// loader.js:23 http://localhost:8080/node_modules/react-dom/cjs/react-dom.development.js/..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//../ fbjs/lib/containsNode Promise {} -// 23:10:02.884 loader.js:23 http://localhost:8080/node_modules/react-dom/cjs/react-dom.development.js/..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//../ fbjs/lib/invariant Promise {} - -/** - * - * @param {string} id - * @param {string} parent - */ -function getParentModulePromise(id, parent) { - var parentLink = BsGetPath("..", parent); - if (parentLink === parent) { - return falsePromise; - } - return getPackageJsPromise(id, parentLink); -} -// In the beginning -// it is `resolveModule('./main.js', '') -// return the promise of link and text - -/** - * - * @param {string} id - */ -function getPackageName(id) { - var index = id.indexOf("/"); - if (id[0] === "@") index = id.indexOf("/", index + 1); - if (index === -1) { - return id; - } - return id.substring(0, index); -} - -/** - * - * @param {string} s - * @param {string} text - * @returns {undefined | string } - */ -function isJustAPackageAndHasMainField(s, text) { - if (s.indexOf("/") >= 0) { - return; - } else { - var mainField; - try { - mainField = JSON.parse(text).main; - } catch (_) {} - if (mainField === undefined) { - return; - } else { - return mainField; - } - } -} -function getPackageJsPromise(id, parent) { - var idNodeModulesPrefix = "./node_modules/" + id; - var link = getPathWithJsSuffix(idNodeModulesPrefix, parent); - if (parent.endsWith("node_modules/")) { - // impossible that `node_modules/node_modules/xx/x - // return falsePromise - return getParentModulePromise(id, parent); - } - - var packageJson = BsGetPath( - `./node_modules/${getPackageName(id)}/package.json`, - parent - ); - - return cachedFetch(packageJson).then(function (text) { - if (text !== false) { - var mainField; - if ((mainField = isJustAPackageAndHasMainField(id, text)) !== undefined) { - var packageLink = BsGetPath( - addSuffixJsIfNot(`./node_modules/${id}/${mainField}`), - parent - ); - return cachedFetch(packageLink).then(function (text) { - if (text !== false) { - return { text, link: packageLink }; - } else { - return getParentModulePromise(id, parent); - } - }); - } else { - // package indeed exist - return cachedFetch(link).then(function (text) { - if (text !== false) { - return { text, link }; - } else if (!id.endsWith(".js")) { - var linkNew = getPathWithJsSuffix( - idNodeModulesPrefix + `/index.js`, - parent - ); - return cachedFetch(linkNew).then(function (text) { - if (text !== false) { - return { text, link: linkNew }; - } else { - return getParentModulePromise(id, parent); - } - }); - } else { - return getParentModulePromise(id, parent); - } - }); - } - } else { - return getParentModulePromise(id, parent); - } - }); -} - -/** - * - * @param {string} id - * @param {string} parent - * can return Promise , false means - * this module can not be resolved - */ -function getModulePromise(id, parent) { - var done = getIdLocation(id, parent); - if (!done) { - return visitIdLocation(id, parent, function () { - if (id[0] != ".") { - // package path - return getPackageJsPromise(id, parent); - } else { - // relative path, one shot resolve - let link = getPathWithJsSuffix(id, parent); - return cachedFetch(link).then(function (text) { - if (text !== false) { - return { text, link }; - } else if (!id.endsWith(".js")) { - // could be "./dir" - var newLink = getPathWithJsSuffix(id + "/index.js", parent); - return cachedFetch(newLink).then(function (text) { - if (text !== false) { - return { text, link: newLink }; - } else { - throw new Error(` ${id} : ${parent} could not be resolved`); - } - }); - } else { - throw new Error(` ${id} : ${parent} could not be resolved`); - } - }); - } - }); - } else { - return done; - } -} - -/** - * - * @param {string} id - * @param {string} parent - * @returns {Promise} - */ -function getAll(id, parent) { - return getModulePromise(id, parent).then(function (obj) { - if (obj) { - var deps = getDeps(obj.text); - return Promise.all(deps.map((x) => getAll(x, obj.link))); - } else { - throw new Error(`${id}@${parent} was not resolved successfully`); - } - }); -} - -/** - * - * @param {string} text - * @param {string} parent - * @returns {Promise} - */ -function getAllFromText(text, parent) { - var deps = getDeps(text); - return Promise.all(deps.map((x) => getAll(x, parent))); -} - -var evaluatedModules = new Map(); - -function loadSync(id, parent) { - var baseOrModule = getIdLocationSync(id, parent); - if (baseOrModule && baseOrModule.link !== undefined) { - if (evaluatedModules.has(baseOrModule.link)) { - return evaluatedModules.get(baseOrModule.link).exports; - } - if (!baseOrModule.exports) { - baseOrModule.exports = {}; - globalEval( - `(function(require,exports,module){${baseOrModule.text}\n})//# sourceURL=${baseOrModule.link}` - )( - function require(id) { - return loadSync(id, baseOrModule.link); - }, // require - (baseOrModule.exports = {}), // exports - baseOrModule // module - ); - } - if (!evaluatedModules.has(baseOrModule.link)) { - evaluatedModules.set(baseOrModule.link, baseOrModule); - } - return baseOrModule.exports; - } else { - throw new Error(`${id} : ${parent} could not be resolved`); - } -} - -function genEvalName() { - return "eval-" + ("" + Math.random()).substr(2, 5); -} -/** - * - * @param {string} text - * @param {string} link - * In this case [text] evaluated result will not be cached - */ -function loadTextSync(text, link) { - var baseOrModule = { exports: {}, text, link }; - globalEval( - `(function(require,exports,module){${baseOrModule.text}\n})//# sourceURL=${ - baseOrModule.link - }/${genEvalName()}.js` - )( - function require(id) { - return loadSync(id, baseOrModule.link); - }, // require - baseOrModule.exports, // exports - baseOrModule // module - ); - return baseOrModule.exports; -} - -/** - * - * @param {string} text - */ -function BSloadText(text) { - console.time("Loading"); - var parent = BsGetPath(".", document.baseURI); - return getAllFromText(text, parent).then(function () { - var result = loadTextSync(text, parent); - console.timeEnd("Loading"); - return result; - }); -} - -function load(id, parent) { - return getAll(id, parent).then(function () { - return loadSync(id, parent); - }); -} - -export function BSload(id) { - var parent = BsGetPath(".", document.baseURI); - return load(id, parent); -} - -export var BSLoader = { - loadText: BSloadText, - load: BSload, - SyncedIDLocations: SyncedIDLocations, -}; - -window.BSLoader = BSLoader; - -var main = document.querySelector("script[data-main]"); -if (main) { - BSload(main.dataset.main); -} diff --git a/jscomp/bsb/templates/tea/package.json b/jscomp/bsb/templates/tea/package.json deleted file mode 100644 index d88b5f32a8..0000000000 --- a/jscomp/bsb/templates/tea/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "${rescript:name}", - "version": "${rescript:proj-version}", - "scripts": { - "clean": "bsb -clean-world", - "build": "bsb -make-world", - "watch": "bsb -make-world -w -ws _" - }, - "keywords": [ - "ReScript" - ], - "author": "", - "license": "MIT", - "devDependencies": { - "${rescript:platform}": "^${rescript:bs-version}" - }, - "dependencies": { - "bucklescript-tea": "^0.7.4" - } -} diff --git a/jscomp/bsb/templates/tea/src/demo.ml b/jscomp/bsb/templates/tea/src/demo.ml deleted file mode 100644 index 6eab1de469..0000000000 --- a/jscomp/bsb/templates/tea/src/demo.ml +++ /dev/null @@ -1,62 +0,0 @@ -(* This line opens the Tea.App modules into the current scope for Program access functions and types *) -open Tea.App - -(* This opens the Elm-style virtual-dom functions and types into the current scope *) -open Tea.Html - -(* Let's create a new type here to be our main message type that is passed around *) -type msg = - | Increment (* This will be our message to increment the counter *) - | Decrement (* This will be our message to decrement the counter *) - | Reset (* This will be our message to reset the counter to 0 *) - | Set of int (* This will be our message to set the counter to a specific value *) - [@@bs.deriving {accessors}] (* This is a nice quality-of-life addon from Bucklescript, it will generate function names for each constructor name, optional, but nice to cut down on code, this is unused in this example but good to have regardless *) - -(* This is optional for such a simple example, but it is good to have an `init` function to define your initial model default values, the model for Counter is just an integer *) -let init () = 4 - -(* This is the central message handler, it takes the model as the first argument *) -let update model = function (* These should be simple enough to be self-explanatory, mutate the model based on the message, easy to read and follow *) - | Increment -> model + 1 - | Decrement -> model - 1 - | Reset -> 0 - | Set v -> v - -(* This is just a helper function for the view, a simple function that returns a button based on some argument *) -let view_button title msg = - button - [ onClick msg - ] - [ text title - ] - -(* This is the main callback to generate the virtual-dom. - This returns a virtual-dom node that becomes the view, only changes from call-to-call are set on the real DOM for efficiency, this is also only called once per frame even with many messages sent in within that frame, otherwise does nothing *) -let view model = - div - [] - [ span - [ style "text-weight" "bold" ] - [ text (string_of_int model) ] - ; br [] - ; view_button "Increment" Increment - ; br [] - ; view_button "Decrement" Decrement - ; br [] - ; view_button "Set to 2" (Set 42) - ; br [] - ; if model <> 0 then view_button "Reset" Reset else noNode - ] - -(* This is the main function, it can be named anything you want but `main` is traditional. - The Program returned here has a set of callbacks that can easily be called from - Bucklescript or from javascript for running this main attached to an element, - or even to pass a message into the event loop. You can even expose the - constructors to the messages to javascript via the above [@@bs.deriving {accessors}] - attribute on the `msg` type or manually, that way even javascript can use it safely. *) -let main = - beginnerProgram { (* The beginnerProgram just takes a set model state and the update and view functions *) - model = init (); (* Since model is a set value here, we call our init function to generate that value *) - update; - view; - } \ No newline at end of file diff --git a/jscomp/bsb/templates/tea/src/main.ml b/jscomp/bsb/templates/tea/src/main.ml deleted file mode 100644 index 0646bedd6b..0000000000 --- a/jscomp/bsb/templates/tea/src/main.ml +++ /dev/null @@ -1,9 +0,0 @@ - - - -Js.Global.setTimeout - (fun _ -> - Demo.main (Web.Document.getElementById "my-element") () - |. ignore - ) -0 \ No newline at end of file diff --git a/jscomp/bsb/templates/tea/watcher.js b/jscomp/bsb/templates/tea/watcher.js deleted file mode 100644 index ee1e93953c..0000000000 --- a/jscomp/bsb/templates/tea/watcher.js +++ /dev/null @@ -1,27 +0,0 @@ - - -var wsReloader; -var LAST_SUCCESS_BUILD_STAMP = (localStorage.getItem('LAST_SUCCESS_BUILD_STAMP') || 0) -var WS_PORT = 9999; // configurable - -function setUpWebScoket() { - if (wsReloader == null || wsReloader.readyState !== 1) { - try { - wsReloader = new WebSocket(`ws://${window.location.hostname}:${WS_PORT}`) - wsReloader.onmessage = (msg) => { - var newData = JSON.parse(msg.data).LAST_SUCCESS_BUILD_STAMP - if (newData > LAST_SUCCESS_BUILD_STAMP) { - LAST_SUCCESS_BUILD_STAMP = newData - localStorage.setItem('LAST_SUCCESS_BUILD_STAMP', LAST_SUCCESS_BUILD_STAMP) - location.reload(true) - } - - } - } catch (exn) { - console.error("web socket failed connect") - } - } -}; - -setUpWebScoket(); -setInterval(setUpWebScoket, 2000); \ No newline at end of file diff --git a/jscomp/main/rescript_main.ml b/jscomp/main/rescript_main.ml index 06b4800a39..2513321a82 100644 --- a/jscomp/main/rescript_main.ml +++ b/jscomp/main/rescript_main.ml @@ -24,8 +24,6 @@ let () = Bsb_log.setup () -let current_theme = ref "basic" - let separator = "--" let watch_mode = ref false @@ -189,24 +187,6 @@ let clean_subcommand ~start argv = Bsb_clean.clean_bs_deps Bsb_global_paths.cwd; Bsb_clean.clean_self Bsb_global_paths.cwd -let init_usage = - "Usage: rescript init [folder-name]\n\n\ - `rescript init` adds a small ReScript project template to the current \ - folder\n\n\ - Pass folder-name to add them to a dedicated folder\n" - -let init_subcommand ~start argv = - Bsb_arg.parse_exn ~usage:init_usage ~start ~argv [||] (fun ~rev_args -> - let location = - match rev_args with - | [ x ] -> x - | last :: _another :: _ -> - raise (Bsb_arg.Bad ("Don't know what to do with " ^ last)) - | [] -> "." - in - Bsb_theme_init.init_sample_project ~cwd:Bsb_global_paths.cwd - ~theme:!current_theme location) - let list_files = ref false let info_subcommand ~start argv = @@ -257,7 +237,6 @@ let () = match argv.(1) with | "build" -> build_subcommand ~start:2 argv argv_len | "clean" -> clean_subcommand ~start:2 argv - | "init" -> init_subcommand ~start:2 argv | "info" -> (* internal *) info_subcommand ~start:2 argv diff --git a/lib/4.06.1/rescript.ml b/lib/4.06.1/rescript.ml index ab7f852315..66097a6a4a 100644 --- a/lib/4.06.1/rescript.ml +++ b/lib/4.06.1/rescript.ml @@ -12874,2163 +12874,6 @@ let regenerate_ninja ~(package_kind : Bsb_package_kind.t) ~forced ~per_proj_dir (Literals.bsconfig_json :: config.file_groups.globbed_dirs); Some config -end -module Bsb_regex : sig -#1 "bsb_regex.mli" -(* Copyright (C) 2017 Hongbo Zhang, Authors of ReScript - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - -val global_substitute : - string -> reg:string -> (string -> string list -> string) -> string -(** Used in `bsb -init` command *) - -end = struct -#1 "bsb_regex.ml" -(* Copyright (C) 2017 Hongbo Zhang, Authors of ReScript - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - -let string_after s n = String.sub s n (String.length s - n) - -(* There seems to be a bug in {!Str.global_substitute} - {[ - Str.global_substitute (Str.regexp "\\${rescript:\\([-a-zA-Z0-9]+\\)}") (fun x -> (x^":found")) {| ${rescript:hello-world} ${rescript:x} ${x}|} ;; - - : bytes = - " ${rescript:hello-world} ${rescript:x} ${x}:found ${rescript:hello-world} ${rescript:x} ${x}:found ${x}" - ]} -*) -let global_substitute text ~reg:expr repl_fun = - let text_len = String.length text in - let expr = Str.regexp expr in - let rec replace accu start last_was_empty = - let startpos = if last_was_empty then start + 1 else start in - if startpos > text_len then string_after text start :: accu - else - match Str.search_forward expr text startpos with - | exception Not_found -> string_after text start :: accu - | pos -> - let end_pos = Str.match_end () in - let matched = Str.matched_string text in - let groups = - let rec aux n acc = - match Str.matched_group n text with - | exception (Not_found | Invalid_argument _) -> acc - | v -> aux (succ n) (v :: acc) - in - aux 1 [] - in - let repl_text = repl_fun matched groups in - replace - (repl_text :: String.sub text start (pos - start) :: accu) - end_pos (end_pos = pos) - in - String.concat "" (List.rev (replace [] 0 false)) - -end -module Bsb_templates : sig -#1 "bsb_templates.mli" -type node = - | Dir of string * node list - | File of string * string - - -val root : node list -end = struct -#1 "bsb_templates.ml" - -type node = - | Dir of string * node list - | File of string * string -let root = ([ - Dir("basic",[ - File(".gitignore", - "*.exe\n\ - *.obj\n\ - *.out\n\ - *.compile\n\ - *.native\n\ - *.byte\n\ - *.cmo\n\ - *.annot\n\ - *.cmi\n\ - *.cmx\n\ - *.cmt\n\ - *.cmti\n\ - *.cma\n\ - *.a\n\ - *.cmxa\n\ - *.obj\n\ - *~\n\ - *.annot\n\ - *.cmj\n\ - *.bak\n\ - lib/bs\n\ - *.mlast\n\ - *.mliast\n\ - .vscode\n\ - .merlin\n\ - .bsb.lock\n\ - /node_modules/\n\ - " - ); - File("README.md", - "\n\ - \n\ - # Build\n\ - ```\n\ - npm run build\n\ - ```\n\ - \n\ - # Watch\n\ - \n\ - ```\n\ - npm run watch\n\ - ```\n\ - \n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"sources\": {\n\ - \ \"dir\" : \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"package-specs\": {\n\ - \ \"module\": \"es6\",\n\ - \ \"in-source\": true\n\ - \ },\n\ - \ \"suffix\": \".bs.js\"\n\ - }\n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"rescript clean\",\n\ - \ \"build\": \"rescript build\",\n\ - \ \"watch\": \"rescript build -w\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }" - ); - Dir("src",[ - File("Demo.res", - "\n\ - Js.log(\"Hello, ReScript\")" - ) - ]) - ]); - Dir("basic-reason",[ - File(".gitignore", - ".DS_Store\n\ - .merlin\n\ - .bsb.lock\n\ - npm-debug.log\n\ - /lib/bs/\n\ - /node_modules/\n\ - " - ); - File("README.md", - "# Basic Reason Template\n\ - \n\ - Hello! This project allows you to quickly get started with ReScript using Reason syntax. If you wanted a more sophisticated version, try the `react` template (`bsb -theme react -init .`).\n\ - \n\ - # Build\n\ - \n\ - ```bash\n\ - # for yarn\n\ - yarn build\n\ - \n\ - # for npm\n\ - npm run build\n\ - ```\n\ - \n\ - # Build + Watch\n\ - \n\ - ```bash\n\ - # for yarn\n\ - yarn start\n\ - \n\ - # for npm\n\ - npm run start\n\ - ```\n\ - \n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"sources\": {\n\ - \ \"dir\" : \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"package-specs\": {\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ },\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"bs-dependencies\": [\n\ - \n\ - \ ],\n\ - \ \"warnings\": {\n\ - \ \"error\" : \"+101\"\n\ - \ },\n\ - \ \"namespace\": true,\n\ - \ \"refmt\": 3\n\ - }\n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"start\": \"bsb -make-world -w\",\n\ - \ \"clean\": \"bsb -clean-world\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("Demo.re", - "Js.log(\"Hello, ReScript!\");\n\ - " - ) - ]) - ]); - Dir("generator",[ - File(".gitignore", - "*.exe\n\ - *.obj\n\ - *.out\n\ - *.compile\n\ - *.native\n\ - *.byte\n\ - *.cmo\n\ - *.annot\n\ - *.cmi\n\ - *.cmx\n\ - *.cmt\n\ - *.cmti\n\ - *.cma\n\ - *.a\n\ - *.cmxa\n\ - *.obj\n\ - *~\n\ - *.annot\n\ - *.cmj\n\ - *.bak\n\ - lib/bs\n\ - *.mlast\n\ - *.mliast\n\ - .vscode\n\ - .merlin\n\ - .bsb.lock\n\ - /node_modules/\n\ - " - ); - File("README.md", - "\n\ - \n\ - # Build\n\ - ```\n\ - npm run build\n\ - ```\n\ - \n\ - # Watch\n\ - \n\ - ```\n\ - npm run watch\n\ - ```\n\ - \n\ - \n\ - # Editor\n\ - If you use `vscode`, Press `Windows + Shift + B` it will build automatically" - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"sources\": {\n\ - \ \"dir\": \"src\",\n\ - \ \"generators\": [{\n\ - \ \"name\": \"cpp\",\n\ - \ \"edge\": [\"test.ml\", \":\", \"test.cpp.ml\"]\n\ - \ }],\n\ - \ \"subdirs\": true \n\ - \ },\n\ - \ \"generators\": [{\n\ - \ \"name\" : \"cpp\",\n\ - \ \"command\": \"sed 's/OCAML/3/' $in > $out\"\n\ - \ }],\n\ - \ \"bs-dependencies\" : [\n\ - \ ]\n\ - }" - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"watch\": \"bsb -make-world -w\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("demo.ml", - "\n\ - \n\ - let () = Js.log \"Hello, ReScript\"" - ); - File("test.cpp.ml", - "\n\ - (* \n\ - #define FS_VAL(name,ty) external name : ty = \"\" [@@bs.module \"fs\"]\n\ - \n\ - \n\ - FS_VAL(readdirSync, string -> string array)\n\ - \ *)\n\ - \n\ - \n\ - \ let ocaml = OCAML" - ) - ]) - ]); - Dir("minimal",[ - File(".gitignore", - ".DS_Store\n\ - .merlin\n\ - .bsb.lock\n\ - npm-debug.log\n\ - /lib/bs/\n\ - /node_modules/" - ); - File("README.md", - "\n\ - \ # ${rescript:name}" - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"sources\": {\n\ - \ \"dir\": \"src\",\n\ - \ \"subdirs\": true\n\ - \ }\n\ - }" - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"start\": \"bsb -make-world -w\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("main.ml", - "" - ) - ]) - ]); - Dir("node",[ - File(".gitignore", - "*.exe\n\ - *.obj\n\ - *.out\n\ - *.compile\n\ - *.native\n\ - *.byte\n\ - *.cmo\n\ - *.annot\n\ - *.cmi\n\ - *.cmx\n\ - *.cmt\n\ - *.cmti\n\ - *.cma\n\ - *.a\n\ - *.cmxa\n\ - *.obj\n\ - *~\n\ - *.annot\n\ - *.cmj\n\ - *.bak\n\ - lib/bs\n\ - *.mlast\n\ - *.mliast\n\ - .vscode\n\ - .merlin\n\ - .bsb.lock\n\ - /node_modules/\n\ - " - ); - File("README.md", - "\n\ - \n\ - # Build\n\ - ```\n\ - npm run build\n\ - ```\n\ - \n\ - # Watch\n\ - \n\ - ```\n\ - npm run watch\n\ - ```\n\ - \n\ - \n\ - # Editor\n\ - If you use `vscode`, Press `Windows + Shift + B` it will build automatically\n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"sources\": {\n\ - \ \"dir\": \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"package-specs\": {\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ },\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"bs-dependencies\": [\n\ - \ ]\n\ - }" - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"watch\": \"bsb -make-world -w\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("demo.ml", - "\n\ - \n\ - let () = Js.log \"Hello, ReScript\"" - ) - ]) - ]); - Dir("react-hooks",[ - File(".gitignore", - ".DS_Store\n\ - .merlin\n\ - .bsb.lock\n\ - npm-debug.log\n\ - /lib/bs/\n\ - /node_modules/\n\ - /bundleOutput/" - ); - File("README.md", - "# ReasonReact Template & Examples\n\ - \n\ - This is:\n\ - - A template for your new ReasonReact project.\n\ - - A collection of thin examples illustrating ReasonReact usage.\n\ - - Extra helper documentation for ReasonReact (full ReasonReact docs [here](https://reasonml.github.io/reason-react/)).\n\ - \n\ - `src` contains 4 sub-folders, each an independent, self-contained ReasonReact example. Feel free to delete any of them and shape this into your project! This template's more malleable than you might be used to =).\n\ - \n\ - The point of this template and examples is to let you understand and personally tweak the entirely of it. We **don't** give you an opaque, elaborate mega build setup just to put some boxes on the screen. It strikes to stay transparent, learnable, and simple. You're encouraged to read every file; it's a great feeling, having the full picture of what you're using and being able to touch any part.\n\ - \n\ - ## Run\n\ - \n\ - ```sh\n\ - npm install\n\ - npm run server\n\ - # in a new tab\n\ - npm start\n\ - ```\n\ - \n\ - Open a new web page to `http://localhost:8000/`. Change any `.re` file in `src` to see the page auto-reload. **You don't need any bundler when you're developing**!\n\ - \n\ - **How come we don't need any bundler during development**? We highly encourage you to open up `index.html` to check for yourself!\n\ - \n\ - # Features Used\n\ - \n\ - | | Blinking Greeting | Reducer from ReactJS Docs | Fetch Dog Pictures | Reason Using JS Using Reason |\n\ - |---------------------------|-------------------|---------------------------|--------------------|------------------------------|\n\ - | No props | | ✓ | | |\n\ - | Has props | | | | ✓ |\n\ - | Children props | ✓ | | | |\n\ - | No state | | | | ✓ |\n\ - | Has state | ✓ | | ✓ | |\n\ - | Has state with useReducer | | ✓ | | |\n\ - | ReasonReact using ReactJS | | | | ✓ |\n\ - | ReactJS using ReasonReact | | | | ✓ |\n\ - | useEffect | ✓ | | ✓ | |\n\ - | Dom attribute | ✓ | ✓ | | ✓ |\n\ - | Styling | ✓ | ✓ | ✓ | ✓ |\n\ - | React.array | | | ✓ | |\n\ - \n\ - # Bundle for Production\n\ - \n\ - We've included a convenience `UNUSED_webpack.config.js`, in case you want to ship your project to production. You can rename and/or remove that in favor of other bundlers, e.g. Rollup.\n\ - \n\ - We've also provided a barebone `indexProduction.html`, to serve your bundle.\n\ - \n\ - ```sh\n\ - npm install webpack webpack-cli\n\ - # rename file\n\ - mv UNUSED_webpack.config.js webpack.config.js\n\ - # call webpack to bundle for production\n\ - ./node_modules/.bin/webpack\n\ - open indexProduction.html\n\ - ```\n\ - \n\ - # Handle Routing Yourself\n\ - \n\ - To serve the files, this template uses a minimal dependency called `moduleserve`. A URL such as `localhost:8000/scores/john` resolves to the file `scores/john.html`. If you'd like to override this and handle URL resolution yourself, change the `server` command in `package.json` from `moduleserve ./ --port 8000` to `moduleserve ./ --port 8000 --spa` (for \"single page application\"). This will make `moduleserve` serve the default `index.html` for any URL. Since `index.html` loads `Index.bs.js`, you can grab hold of the URL in the corresponding `Index.re` and do whatever you want.\n\ - \n\ - By the way, ReasonReact comes with a small [router](https://reasonml.github.io/reason-react/docs/en/router) you might be interested in.\n\ - " - ); - File("UNUSED_webpack.config.js", - "const path = require('path');\n\ - \n\ - module.exports = {\n\ - \ entry: './src/Index.bs.js',\n\ - \ // If you ever want to use webpack during development, change 'production'\n\ - \ // to 'development' as per webpack documentation. Again, you don't have to\n\ - \ // use webpack or any other bundler during development! Recheck README if\n\ - \ // you didn't know this\n\ - \ mode: 'production',\n\ - \ output: {\n\ - \ path: path.join(__dirname, \"bundleOutput\"),\n\ - \ filename: 'index.js',\n\ - \ },\n\ - };" - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"reason\": {\n\ - \ \"react-jsx\": 3\n\ - \ },\n\ - \ \"sources\": {\n\ - \ \"dir\" : \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"bsc-flags\": [\"-bs-super-errors\", \"-bs-no-version-header\"],\n\ - \ \"package-specs\": [{\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ }],\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"namespace\": true,\n\ - \ \"bs-dependencies\": [\n\ - \ \"reason-react\"\n\ - \ ],\n\ - \ \"refmt\": 3\n\ - }\n\ - " - ); - File("index.html", - "\n\ - \n\ - \n\ - \ \n\ - \ ReasonReact Examples\n\ - \n\ - \n\ - \ \n\ - \n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \n\ - \n\ - " - ); - File("indexProduction.html", - "\n\ - \n\ - \n\ - \ \n\ - \ ReasonReact Examples\n\ - \n\ - \n\ - \ \n\ - \n\ - \n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"start\": \"bsb -make-world -w -ws _ \",\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"server\": \"moduleserve ./ --port 8000\",\n\ - \ \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\",\n\ - \ \"ReasonReact\",\n\ - \ \"reason-react\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"dependencies\": {\n\ - \ \"react\": \"^16.8.1\",\n\ - \ \"react-dom\": \"^16.8.1\",\n\ - \ \"reason-react\": \">=0.7.1\"\n\ - \ },\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\",\n\ - \ \"moduleserve\": \"^0.9.0\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - Dir("BlinkingGreeting",[ - File("BlinkingGreeting.re", - "[@react.component]\n\ - let make = (~children) => {\n\ - \ let (show, setShow) = React.useState(() => true);\n\ - \n\ - \ // Notice that instead of `useEffect`, we have `useEffect0`. See\n\ - \ // reasonml.github.io/reason-react/docs/en/components#hooks for more info\n\ - \ React.useEffect0(() => {\n\ - \ let id =\n\ - \ Js.Global.setInterval(\n\ - \ () => setShow(previousShow => !previousShow),\n\ - \ 1000,\n\ - \ );\n\ - \n\ - \ Some(() => Js.Global.clearInterval(id));\n\ - \ });\n\ - \n\ - \ let style =\n\ - \ if (show) {\n\ - \ ReactDOMRe.Style.make(~opacity=\"1\", ~transition=\"opacity 1s\", ());\n\ - \ } else {\n\ - \ ReactDOMRe.Style.make(~opacity=\"0\", ~transition=\"opacity 1s\", ());\n\ - \ };\n\ - \n\ - \
children
;\n\ - };\n\ - " - ) - ]); - File("ExampleStyles.re", - "let reasonReactBlue = \"#48a9dc\";\n\ - \n\ - // The {j|...|j} feature is just string interpolation, from\n\ - // bucklescript.github.io/docs/en/interop-cheatsheet#string-unicode-interpolation\n\ - // This allows us to conveniently write CSS, together with variables, by\n\ - // constructing a string\n\ - let style = {j|\n\ - \ body {\n\ - \ background-color: rgb(224, 226, 229);\n\ - \ display: flex;\n\ - \ flex-direction: column;\n\ - \ align-items: center;\n\ - \ }\n\ - \ button {\n\ - \ background-color: white;\n\ - \ color: $reasonReactBlue;\n\ - \ box-shadow: 0 0 0 1px $reasonReactBlue;\n\ - \ border: none;\n\ - \ padding: 8px;\n\ - \ font-size: 16px;\n\ - \ }\n\ - \ button:active {\n\ - \ background-color: $reasonReactBlue;\n\ - \ color: white;\n\ - \ }\n\ - \ .container {\n\ - \ margin: 12px 0px;\n\ - \ box-shadow: 0px 4px 16px rgb(200, 200, 200);\n\ - \ width: 720px;\n\ - \ border-radius: 12px;\n\ - \ font-family: sans-serif;\n\ - \ }\n\ - \ .containerTitle {\n\ - \ background-color: rgb(242, 243, 245);\n\ - \ border-radius: 12px 12px 0px 0px;\n\ - \ padding: 12px;\n\ - \ font-weight: bold;\n\ - \ }\n\ - \ .containerContent {\n\ - \ background-color: white;\n\ - \ padding: 16px;\n\ - \ border-radius: 0px 0px 12px 12px;\n\ - \ }\n\ - |j};\n\ - " - ); - Dir("FetchedDogPictures",[ - File("FetchedDogPictures.re", - "[@bs.val] external fetch: string => Js.Promise.t('a) = \"fetch\";\n\ - \n\ - type state =\n\ - \ | LoadingDogs\n\ - \ | ErrorFetchingDogs\n\ - \ | LoadedDogs(array(string));\n\ - \n\ - [@react.component]\n\ - let make = () => {\n\ - \ let (state, setState) = React.useState(() => LoadingDogs);\n\ - \n\ - \ // Notice that instead of `useEffect`, we have `useEffect0`. See\n\ - \ // reasonml.github.io/reason-react/docs/en/components#hooks for more info\n\ - \ React.useEffect0(() => {\n\ - \ Js.Promise.(\n\ - \ fetch(\"https://dog.ceo/api/breeds/image/random/3\")\n\ - \ |> then_(response => response##json())\n\ - \ |> then_(jsonResponse => {\n\ - \ setState(_previousState => LoadedDogs(jsonResponse##message));\n\ - \ Js.Promise.resolve();\n\ - \ })\n\ - \ |> catch(_err => {\n\ - \ setState(_previousState => ErrorFetchingDogs);\n\ - \ Js.Promise.resolve();\n\ - \ })\n\ - \ |> ignore\n\ - \ );\n\ - \n\ - \ // Returning None, instead of Some(() => ...), means we don't have any\n\ - \ // cleanup to do before unmounting. That's not 100% true. We should\n\ - \ // technically cancel the promise. Unofortunately, there's currently no\n\ - \ // way to cancel a promise. Promises in general should be way less used\n\ - \ // for React components; but since folks do use them, we provide such an\n\ - \ // example here. In reality, this fetch should just be a plain callback,\n\ - \ // with a cancellation API\n\ - \ None;\n\ - \ });\n\ - \n\ - \ \n\ - \ {switch (state) {\n\ - \ | ErrorFetchingDogs => React.string(\"An error occurred!\")\n\ - \ | LoadingDogs => React.string(\"Loading...\")\n\ - \ | LoadedDogs(dogs) =>\n\ - \ dogs\n\ - \ ->Belt.Array.mapWithIndex((i, dog) => {\n\ - \ let imageStyle =\n\ - \ ReactDOMRe.Style.make(\n\ - \ ~height=\"120px\",\n\ - \ ~width=\"100%\",\n\ - \ ~marginRight=i === Js.Array.length(dogs) - 1 ? \"0px\" : \"8px\",\n\ - \ ~borderRadius=\"8px\",\n\ - \ ~boxShadow=\"0px 4px 16px rgb(200, 200, 200)\",\n\ - \ ~backgroundSize=\"cover\",\n\ - \ ~backgroundImage={j|url($dog)|j},\n\ - \ ~backgroundPosition=\"center\",\n\ - \ (),\n\ - \ );\n\ - \
;\n\ - \ })\n\ - \ ->React.array\n\ - \ }}\n\ - \
;\n\ - };\n\ - " - ) - ]); - File("Index.re", - "// Entry point\n\ - \n\ - [@bs.val] external document: Js.t({..}) = \"document\";\n\ - \n\ - // We're using raw DOM manipulations here, to avoid making you read\n\ - // ReasonReact when you might precisely be trying to learn it for the first\n\ - // time through the examples later.\n\ - let style = document##createElement(\"style\");\n\ - document##head##appendChild(style);\n\ - style##innerHTML #= ExampleStyles.style;\n\ - \n\ - let makeContainer = text => {\n\ - \ let container = document##createElement(\"div\");\n\ - \ container##className #= \"container\";\n\ - \n\ - \ let title = document##createElement(\"div\");\n\ - \ title##className #= \"containerTitle\";\n\ - \ title##innerText #= text;\n\ - \n\ - \ let content = document##createElement(\"div\");\n\ - \ content##className #= \"containerContent\";\n\ - \n\ - \ let () = container##appendChild(title);\n\ - \ let () = container##appendChild(content);\n\ - \ let () = document##body##appendChild(container);\n\ - \n\ - \ content;\n\ - };\n\ - \n\ - // All 4 examples.\n\ - ReactDOMRe.render(\n\ - \ \n\ - \ {React.string(\"Hello!\")}\n\ - \ ,\n\ - \ makeContainer(\"Blinking Greeting\"),\n\ - );\n\ - \n\ - ReactDOMRe.render(\n\ - \ ,\n\ - \ makeContainer(\"Reducer From ReactJS Docs\"),\n\ - );\n\ - \n\ - ReactDOMRe.render(\n\ - \ ,\n\ - \ makeContainer(\"Fetched Dog Pictures\"),\n\ - );\n\ - \n\ - ReactDOMRe.render(\n\ - \ ,\n\ - \ makeContainer(\"Reason Using JS Using Reason\"),\n\ - );\n\ - " - ); - Dir("ReasonUsingJSUsingReason",[ - File("ReactJSCard.js", - "// In this Interop example folder, we have:\n\ - // - A ReasonReact component, ReasonReactCard.re\n\ - // - Used by a ReactJS component, ReactJSCard.js (this file)\n\ - // - ReactJSCard.js can be used by ReasonReact, through bindings in ReasonUsingJSUsingReason.re\n\ - // - ReasonUsingJSUsingReason.re is used by Index.re\n\ - \n\ - var ReactDOM = require('react-dom');\n\ - var React = require('react');\n\ - \n\ - var ReasonReactCard = require('./ReasonReactCard.bs').make;\n\ - \n\ - var ReactJSComponent = function() {\n\ - \ let backgroundColor = \"rgba(0, 0, 0, 0.05)\";\n\ - \ let padding = \"12px\";\n\ - \n\ - \ // We're not using JSX here, to avoid folks needing to install the related\n\ - \ // React toolchains just for this example.\n\ - \ //
\n\ - \ //
This is a ReactJS card
\n\ - \ // \n\ - \ //
\n\ - \ return React.createElement(\n\ - \ \"div\",\n\ - \ {style: {backgroundColor, padding, borderRadius: \"8px\"}},\n\ - \ React.createElement(\"div\", {style: {marginBottom: \"8px\"}}, \"This is a ReactJS card\"),\n\ - \ React.createElement(ReasonReactCard, {style: {backgroundColor, padding, borderRadius: \"4px\"}}),\n\ - \ )\n\ - };\n\ - ReactJSComponent.displayName = \"MyBanner\";\n\ - \n\ - module.exports = ReactJSComponent;\n\ - " - ); - File("ReasonReactCard.re", - "// In this Interop example folder, we have:\n\ - // - A ReasonReact component, ReasonReactCard.re (this file)\n\ - // - Used by a ReactJS component, ReactJSCard.js\n\ - // - ReactJSCard.js can be used by ReasonReact, through bindings in ReasonUsingJSUsingReason.re\n\ - // - ReasonUsingJSUsingReason.re is used by Index.re\n\ - \n\ - [@react.component]\n\ - let make = (~style) => {\n\ - \
{React.string(\"This is a ReasonReact card\")}
;\n\ - };\n\ - " - ); - File("ReasonUsingJSUsingReason.re", - "// In this Interop example folder, we have:\n\ - // - A ReasonReact component, ReasonReactCard.re\n\ - // - Used by a ReactJS component, ReactJSCard.js\n\ - // - ReactJSCard.js can be used by ReasonReact, through bindings in ReasonUsingJSUsingReason.re (this file)\n\ - // - ReasonUsingJSUsingReason.re is used by Index.re\n\ - \n\ - // All you need to do to use a ReactJS component in ReasonReact, is to write the lines below!\n\ - // reasonml.github.io/reason-react/docs/en/components#import-from-js\n\ - [@react.component] [@bs.module]\n\ - external make: unit => React.element = \"./ReactJSCard\";\n\ - " - ) - ]); - Dir("ReducerFromReactJSDocs",[ - File("ReducerFromReactJSDocs.re", - "// This is the ReactJS documentation's useReducer example, directly ported over\n\ - // https://reactjs.org/docs/hooks-reference.html#usereducer\n\ - \n\ - // A little extra we've put, because the ReactJS example has no styling\n\ - let leftButtonStyle = ReactDOMRe.Style.make(~borderRadius=\"4px 0px 0px 4px\", ~width=\"48px\", ());\n\ - let rightButtonStyle = ReactDOMRe.Style.make(~borderRadius=\"0px 4px 4px 0px\", ~width=\"48px\", ());\n\ - let containerStyle = ReactDOMRe.Style.make(~display=\"flex\", ~alignItems=\"center\", ~justifyContent=\"space-between\", ());\n\ - \n\ - // Record and variant need explicit declarations.\n\ - type state = {count: int};\n\ - \n\ - type action =\n\ - \ | Increment\n\ - \ | Decrement;\n\ - \n\ - let initialState = {count: 0};\n\ - \n\ - let reducer = (state, action) => {\n\ - \ switch (action) {\n\ - \ | Increment => {count: state.count + 1}\n\ - \ | Decrement => {count: state.count - 1}\n\ - \ };\n\ - };\n\ - \n\ - [@react.component]\n\ - let make = () => {\n\ - \ let (state, dispatch) = React.useReducer(reducer, initialState);\n\ - \n\ - \ // We can use a fragment here, but we don't, because we want to style the counter\n\ - \
\n\ - \
\n\ - \ {React.string(\"Count: \")}\n\ - \ {React.string(string_of_int(state.count))}\n\ - \
\n\ - \
\n\ - \ \n\ - \ \n\ - \
\n\ - \
;\n\ - };\n\ - " - ) - ]) - ]); - File("watcher.js", - "// This is our simple, robust watcher. It hooks into the ReScript build\n\ - // system to listen for build events.\n\ - // See package.json's `start` script and `./node_modules/.bin/bsb --help`\n\ - \n\ - // Btw, if you change this file and reload the page, your browser cache\n\ - // _might_ not pick up the new version. If you're in Chrome, do Force Reload.\n\ - \n\ - var websocketReloader;\n\ - var LAST_SUCCESS_BUILD_STAMP =\n\ - \ localStorage.getItem(\"LAST_SUCCESS_BUILD_STAMP\") || 0;\n\ - // package.json's `start` script's `bsb -ws _` means it'll pipe build events\n\ - // through a websocket connection to a default port of 9999. This is\n\ - // configurable, e.g. `-ws 5000`\n\ - var webSocketPort = 9999;\n\ - \n\ - function setUpWebSocket() {\n\ - \ if (websocketReloader == null || websocketReloader.readyState !== 1) {\n\ - \ try {\n\ - \ websocketReloader = new WebSocket(\n\ - \ `ws://${window.location.hostname}:${webSocketPort}`\n\ - \ );\n\ - \ websocketReloader.onmessage = (message) => {\n\ - \ var newData = JSON.parse(message.data).LAST_SUCCESS_BUILD_STAMP;\n\ - \ if (newData > LAST_SUCCESS_BUILD_STAMP) {\n\ - \ LAST_SUCCESS_BUILD_STAMP = newData;\n\ - \ localStorage.setItem(\n\ - \ \"LAST_SUCCESS_BUILD_STAMP\",\n\ - \ LAST_SUCCESS_BUILD_STAMP\n\ - \ );\n\ - \ // Refresh the page! This will naturally re-run everything,\n\ - \ // including our moduleserve which will re-resolve all the modules.\n\ - \ // No stable build!\n\ - \ location.reload(true);\n\ - \ }\n\ - \ };\n\ - \ } catch (exn) {\n\ - \ console.error(\n\ - \ \"The watcher tried to connect to web socket, but failed. Here's the message:\"\n\ - \ );\n\ - \ console.error(exn);\n\ - \ }\n\ - \ }\n\ - }\n\ - \n\ - setUpWebSocket();\n\ - setInterval(setUpWebSocket, 2000);\n\ - " - ) - ]); - Dir("react-starter",[ - File(".gitignore", - ".DS_Store\n\ - .merlin\n\ - .bsb.lock\n\ - npm-debug.log\n\ - /lib/bs/\n\ - /node_modules/\n\ - *.bs.js\n\ - " - ); - File("README.md", - "# Reason react starter\n\ - \n\ - ## Run Project\n\ - \n\ - ```sh\n\ - npm install\n\ - npm start\n\ - # in another tab\n\ - npm run server\n\ - ```\n\ - \n\ - View the app in the browser at http://localhost:8000. Running in this environment provides hot reloading and support for routing; just edit and save the file and the browser will automatically refresh.\n\ - \n\ - To use a port other than 8000 set the `PORT` environment variable (`PORT=8080 npm run server`).\n\ - \n\ - ## Build for Production\n\ - \n\ - ```sh\n\ - npm run clean\n\ - npm run build\n\ - npm run webpack:production\n\ - ```\n\ - \n\ - This will replace the development artifact `build/Index.js` for an optimized version as well as copy `src/index.html` into `build/`. You can then deploy the contents of the `build` directory (`index.html` and `Index.js`).\n\ - \n\ - **To enable dead code elimination**, change `bsconfig.json`'s `package-specs` `module` from `\"commonjs\"` to `\"es6\"`. Then re-run the above 2 commands. This will allow Webpack to remove unused code.\n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"reason-react-starter\",\n\ - \ \"reason\": {\n\ - \ \"react-jsx\": 3\n\ - \ },\n\ - \ \"sources\": {\n\ - \ \"dir\": \"src\",\n\ - \ \"subdirs\": true\n\ - \ },\n\ - \ \"bsc-flags\": [\"-bs-super-errors\", \"-bs-no-version-header\"],\n\ - \ \"package-specs\": [\n\ - \ {\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ }\n\ - \ ],\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"namespace\": true,\n\ - \ \"bs-dependencies\": [\"reason-react\"],\n\ - \ \"refmt\": 3\n\ - }\n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"start\": \"bsb -make-world -w -ws _ \",\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"webpack\": \"webpack -w\",\n\ - \ \"webpack:production\": \"NODE_ENV=production webpack\",\n\ - \ \"server\": \"webpack-dev-server\",\n\ - \ \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\",\n\ - \ \"ReasonReact\",\n\ - \ \"reason-react\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"dependencies\": {\n\ - \ \"react\": \"^17.0.1\",\n\ - \ \"react-dom\": \"^17.0.1\",\n\ - \ \"reason-react\": \"^0.9.1\"\n\ - \ },\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\",\n\ - \ \"css-loader\": \"^5.0.0\",\n\ - \ \"html-webpack-plugin\": \"^4.5.0\",\n\ - \ \"style-loader\": \"^2.0.0\",\n\ - \ \"webpack\": \"^4.44.2\",\n\ - \ \"webpack-cli\": \"^3.3.12\",\n\ - \ \"webpack-dev-server\": \"^3.11.0\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("App.re", - "type state = {count: int};\n\ - \n\ - type action =\n\ - \ | Increment\n\ - \ | Decrement;\n\ - \n\ - let initialState = {count: 0};\n\ - \n\ - let reducer = (state, action) =>\n\ - \ switch (action) {\n\ - \ | Increment => {count: state.count + 1}\n\ - \ | Decrement => {count: state.count - 1}\n\ - \ };\n\ - \n\ - [@react.component]\n\ - let make = () => {\n\ - \ let (state, dispatch) = React.useReducer(reducer, initialState);\n\ - \n\ - \
\n\ - \ {React.string(\"Simple counter with reducer\")}\n\ - \
\n\ - \ \n\ - \ \n\ - \ {state.count |> string_of_int |> React.string}\n\ - \ \n\ - \ \n\ - \
\n\ - \
;\n\ - };\n\ - " - ); - File("Index.re", - "[%bs.raw {|require(\"./index.css\")|}];\n\ - \n\ - ReactDOMRe.renderToElementWithId(, \"root\");\n\ - " - ); - File("index.css", - "body {\n\ - \ margin: 0;\n\ - \ font-family: -apple-system, system-ui, \"Segoe UI\", Helvetica, Arial,\n\ - \ sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n\ - }\n\ - \n\ - main {\n\ - \ padding: 20px;\n\ - }\n\ - \n\ - .counter {\n\ - \ padding: 20px;\n\ - \ display: inline-block;\n\ - }\n\ - " - ); - File("index.html", - "\n\ - \n\ - \ \n\ - \ \n\ - \ Reason react starter\n\ - \ \n\ - \ \n\ - \
\n\ - \ \n\ - \ \n\ - \n\ - " - ) - ]); - File("webpack.config.js", - "const path = require(\"path\")\n\ - const HtmlWebpackPlugin = require(\"html-webpack-plugin\")\n\ - const outputDir = path.join(__dirname, \"build/\")\n\ - \n\ - const isProd = process.env.NODE_ENV === \"production\"\n\ - \n\ - module.exports = {\n\ - \ entry: \"./src/Index.bs.js\",\n\ - \ mode: isProd ? \"production\" : \"development\",\n\ - \ devtool: \"source-map\",\n\ - \ output: {\n\ - \ path: outputDir,\n\ - \ filename: \"Index.js\"\n\ - \ },\n\ - \ plugins: [\n\ - \ new HtmlWebpackPlugin({\n\ - \ template: \"src/index.html\",\n\ - \ inject: false\n\ - \ })\n\ - \ ],\n\ - \ devServer: {\n\ - \ compress: true,\n\ - \ contentBase: outputDir,\n\ - \ port: process.env.PORT || 8000,\n\ - \ historyApiFallback: true\n\ - \ },\n\ - \ module: {\n\ - \ rules: [\n\ - \ {\n\ - \ test: /\\.css$/,\n\ - \ use: [\"style-loader\", \"css-loader\"]\n\ - \ }\n\ - \ ]\n\ - \ }\n\ - }\n\ - " - ) - ]); - Dir("tea",[ - File("README.md", - "\n\ - \n\ - # Build\n\ - ```\n\ - npm run build\n\ - ```\n\ - \n\ - # Watch\n\ - \n\ - ```\n\ - npm run watch\n\ - ```\n\ - \n\ - create a http-server\n\ - \n\ - ```\n\ - npm install -g http-server\n\ - ```\n\ - \n\ - Edit the file and see the changes automatically reloaded in the browser\n\ - " - ); - File("bsconfig.json", - "{\n\ - \ \"name\": \"tea\",\n\ - \ \"version\": \"0.1.0\",\n\ - \ \"sources\": {\n\ - \ \"dir\" : \"src\",\n\ - \ \"subdirs\" : true\n\ - \ },\n\ - \ \"package-specs\": {\n\ - \ \"module\": \"commonjs\",\n\ - \ \"in-source\": true\n\ - \ },\n\ - \ \"suffix\": \".bs.js\",\n\ - \ \"bs-dependencies\": [\n\ - \ \"bucklescript-tea\"\n\ - \ ]\n\ - }\n\ - " - ); - File("index.html", - "\n\ - \n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - \ Bucklescript TEA Starter Kit\n\ - \ \n\ - \ \n\ - \n\ - \n\ - \ \n\ - \
\n\ - \ \n\ - \ \n\ - \ \n\ - \ \n\ - " - ); - File("loader.js", - "/* Copyright (C) 2018 Authors of ReScript\n\ - \ *\n\ - \ * This program is free software: you can redistribute it and/or modify\n\ - \ * it under the terms of the GNU Lesser General Public License as published by\n\ - \ * the Free Software Foundation, either version 3 of the License, or\n\ - \ * (at your option) any later version.\n\ - \ *\n\ - \ * In addition to the permissions granted to you by the LGPL, you may combine\n\ - \ * or link a \"work that uses the Library\" with a publicly distributed version\n\ - \ * of this file to produce a combined library or application, then distribute\n\ - \ * that combined work under the terms of your choosing, with no requirement\n\ - \ * to comply with the obligations normally placed on you by section 4 of the\n\ - \ * LGPL version 3 (or the corresponding section of a later version of the LGPL\n\ - \ * should you choose to use a later version).\n\ - \ *\n\ - \ * This program is distributed in the hope that it will be useful,\n\ - \ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ - \ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ - \ * GNU Lesser General Public License for more details.\n\ - \ *\n\ - \ * You should have received a copy of the GNU Lesser General Public License\n\ - \ * along with this program; if not, write to the Free Software\n\ - \ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */\n\ - \n\ - //@ts-check\n\ - \n\ - // @ts-ignore\n\ - window.process = { env: { NODE_ENV: \"dev\" } };\n\ - \n\ - // local to getPath\n\ - var relativeElement = document.createElement(\"a\");\n\ - var baseElement = document.createElement(\"base\");\n\ - document.head.appendChild(baseElement);\n\ - \n\ - export function BsGetPath(id, parent) {\n\ - \ var oldPath = baseElement.href;\n\ - \ baseElement.href = parent;\n\ - \ relativeElement.href = id;\n\ - \ var result = relativeElement.href;\n\ - \ baseElement.href = oldPath;\n\ - \ return result;\n\ - }\n\ - /**\n\ - \ *\n\ - \ * Given current link and its parent, return the new link\n\ - \ * @param {string} id\n\ - \ * @param {string} parent\n\ - \ * @return {string}\n\ - \ */\n\ - function getPathWithJsSuffix(id, parent) {\n\ - \ var oldPath = baseElement.href;\n\ - \ baseElement.href = parent;\n\ - \ relativeElement.href = id;\n\ - \ var result = addSuffixJsIfNot(relativeElement.href);\n\ - \ baseElement.href = oldPath;\n\ - \ return result;\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} x\n\ - \ */\n\ - function addSuffixJsIfNot(x) {\n\ - \ if (x.endsWith(\".js\")) {\n\ - \ return x;\n\ - \ } else {\n\ - \ return x + \".js\";\n\ - \ }\n\ - }\n\ - \n\ - var falsePromise = Promise.resolve(false);\n\ - var fetchConfig = { cache: \"no-cache\" };\n\ - // package.json semantics\n\ - // a string to module object\n\ - // from url -> module object\n\ - // Modules : Map\n\ - // fetch the link:\n\ - // - if it is already fetched before, return the stored promise\n\ - // otherwise create the promise which will be filled with the text if successful\n\ - // or filled with boolean false when failed\n\ - var MODULES = new Map();\n\ - function cachedFetch(link) {\n\ - \ // console.info(link)\n\ - \ var linkResult = MODULES.get(link);\n\ - \ if (linkResult) {\n\ - \ return linkResult;\n\ - \ } else {\n\ - \ var p = fetch(link, fetchConfig).then((resp) => {\n\ - \ if (resp.ok) {\n\ - \ return resp.text();\n\ - \ } else {\n\ - \ return falsePromise;\n\ - \ }\n\ - \ });\n\ - \n\ - \ MODULES.set(link, p);\n\ - \ return p;\n\ - \ }\n\ - }\n\ - \n\ - // from location id -> url\n\ - // There are two rounds of caching:\n\ - // 1. if location and relative path is hit, no need to run\n\ - // 2. if location and relative path is not hit, but the resolved link is hit, no need\n\ - // for network request\n\ - /**\n\ - \ * @type {Map > > }\n\ - \ */\n\ - var IDLocations = new Map();\n\ - \n\ - /**\n\ - \ * @type {Map > }\n\ - \ */\n\ - var SyncedIDLocations = new Map();\n\ - // Its value is an object\n\ - // { link : String }\n\ - // We will first mark it when visiting (to avoid duplicated computation)\n\ - // and populate its link later\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} location\n\ - \ */\n\ - function getIdLocation(id, location) {\n\ - \ var idMap = IDLocations.get(location);\n\ - \ if (idMap) {\n\ - \ return idMap.get(id);\n\ - \ }\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} location\n\ - \ */\n\ - function getIdLocationSync(id, location) {\n\ - \ var idMap = SyncedIDLocations.get(location);\n\ - \ if (idMap) {\n\ - \ return idMap.get(id);\n\ - \ }\n\ - }\n\ - \n\ - function countIDLocations() {\n\ - \ var count = 0;\n\ - \ for (let [k, vv] of IDLocations) {\n\ - \ for (let [kv, v] of vv) {\n\ - \ count += 1;\n\ - \ }\n\ - \ }\n\ - \ console.log(count, \"modules loaded\");\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} location\n\ - \ * @param {Function} cb\n\ - \ * @returns Promise\n\ - \ */\n\ - function visitIdLocation(id, location, cb) {\n\ - \ var result;\n\ - \ var idMap = IDLocations.get(location);\n\ - \ if (idMap && (result = idMap.get(id))) {\n\ - \ return result;\n\ - \ } else {\n\ - \ result = new Promise((resolve) => {\n\ - \ return cb().then((res) => {\n\ - \ var idMap = SyncedIDLocations.get(location);\n\ - \ if (idMap) {\n\ - \ idMap.set(id, res);\n\ - \ } else {\n\ - \ SyncedIDLocations.set(location, new Map([[id, res]]));\n\ - \ }\n\ - \ return resolve(res);\n\ - \ });\n\ - \ });\n\ - \ if (idMap) {\n\ - \ idMap.set(id, result);\n\ - \ } else {\n\ - \ IDLocations.set(location, new Map([[id, result]]));\n\ - \ }\n\ - \ return result;\n\ - \ }\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} text\n\ - \ * @return {string[]}\n\ - \ */\n\ - function getDeps(text) {\n\ - \ var deps = [];\n\ - \ text.replace(\n\ - \ /(\\/\\*[\\w\\W]*?\\*\\/|\\/\\/[^\\n]*|[.$]r)|\\brequire\\s*\\(\\s*[\"']([^\"']*)[\"']\\s*\\)/g,\n\ - \ function (_, ignore, id) {\n\ - \ if (!ignore) deps.push(id);\n\ - \ }\n\ - \ );\n\ - \ return deps;\n\ - }\n\ - \n\ - // By using a named \"eval\" most browsers will execute in the global scope.\n\ - // http://www.davidflanagan.com/2010/12/global-eval-in.html\n\ - var globalEval = eval;\n\ - \n\ - // function parentURL(url) {\n\ - // if (url.endsWith('/')) {\n\ - // return url + '../'\n\ - // } else {\n\ - // return url + '/../'\n\ - // }\n\ - // }\n\ - \n\ - // loader.js:23 http://localhost:8080/node_modules/react-dom/cjs/react-dom.development.js/..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//../ fbjs/lib/containsNode Promise {}\n\ - // 23:10:02.884 loader.js:23 http://localhost:8080/node_modules/react-dom/cjs/react-dom.development.js/..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//..//../ fbjs/lib/invariant Promise {}\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} parent\n\ - \ */\n\ - function getParentModulePromise(id, parent) {\n\ - \ var parentLink = BsGetPath(\"..\", parent);\n\ - \ if (parentLink === parent) {\n\ - \ return falsePromise;\n\ - \ }\n\ - \ return getPackageJsPromise(id, parentLink);\n\ - }\n\ - // In the beginning\n\ - // it is `resolveModule('./main.js', '')\n\ - // return the promise of link and text\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ */\n\ - function getPackageName(id) {\n\ - \ var index = id.indexOf(\"/\");\n\ - \ if (id[0] === \"@\") index = id.indexOf(\"/\", index + 1);\n\ - \ if (index === -1) {\n\ - \ return id;\n\ - \ }\n\ - \ return id.substring(0, index);\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} s\n\ - \ * @param {string} text\n\ - \ * @returns {undefined | string }\n\ - \ */\n\ - function isJustAPackageAndHasMainField(s, text) {\n\ - \ if (s.indexOf(\"/\") >= 0) {\n\ - \ return;\n\ - \ } else {\n\ - \ var mainField;\n\ - \ try {\n\ - \ mainField = JSON.parse(text).main;\n\ - \ } catch (_) {}\n\ - \ if (mainField === undefined) {\n\ - \ return;\n\ - \ } else {\n\ - \ return mainField;\n\ - \ }\n\ - \ }\n\ - }\n\ - function getPackageJsPromise(id, parent) {\n\ - \ var idNodeModulesPrefix = \"./node_modules/\" + id;\n\ - \ var link = getPathWithJsSuffix(idNodeModulesPrefix, parent);\n\ - \ if (parent.endsWith(\"node_modules/\")) {\n\ - \ // impossible that `node_modules/node_modules/xx/x\n\ - \ // return falsePromise\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \n\ - \ var packageJson = BsGetPath(\n\ - \ `./node_modules/${getPackageName(id)}/package.json`,\n\ - \ parent\n\ - \ );\n\ - \n\ - \ return cachedFetch(packageJson).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ var mainField;\n\ - \ if ((mainField = isJustAPackageAndHasMainField(id, text)) !== undefined) {\n\ - \ var packageLink = BsGetPath(\n\ - \ addSuffixJsIfNot(`./node_modules/${id}/${mainField}`),\n\ - \ parent\n\ - \ );\n\ - \ return cachedFetch(packageLink).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link: packageLink };\n\ - \ } else {\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \ });\n\ - \ } else {\n\ - \ // package indeed exist\n\ - \ return cachedFetch(link).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link };\n\ - \ } else if (!id.endsWith(\".js\")) {\n\ - \ var linkNew = getPathWithJsSuffix(\n\ - \ idNodeModulesPrefix + `/index.js`,\n\ - \ parent\n\ - \ );\n\ - \ return cachedFetch(linkNew).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link: linkNew };\n\ - \ } else {\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \ });\n\ - \ } else {\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \ });\n\ - \ }\n\ - \ } else {\n\ - \ return getParentModulePromise(id, parent);\n\ - \ }\n\ - \ });\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} parent\n\ - \ * can return Promise , false means\n\ - \ * this module can not be resolved\n\ - \ */\n\ - function getModulePromise(id, parent) {\n\ - \ var done = getIdLocation(id, parent);\n\ - \ if (!done) {\n\ - \ return visitIdLocation(id, parent, function () {\n\ - \ if (id[0] != \".\") {\n\ - \ // package path\n\ - \ return getPackageJsPromise(id, parent);\n\ - \ } else {\n\ - \ // relative path, one shot resolve\n\ - \ let link = getPathWithJsSuffix(id, parent);\n\ - \ return cachedFetch(link).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link };\n\ - \ } else if (!id.endsWith(\".js\")) {\n\ - \ // could be \"./dir\"\n\ - \ var newLink = getPathWithJsSuffix(id + \"/index.js\", parent);\n\ - \ return cachedFetch(newLink).then(function (text) {\n\ - \ if (text !== false) {\n\ - \ return { text, link: newLink };\n\ - \ } else {\n\ - \ throw new Error(` ${id} : ${parent} could not be resolved`);\n\ - \ }\n\ - \ });\n\ - \ } else {\n\ - \ throw new Error(` ${id} : ${parent} could not be resolved`);\n\ - \ }\n\ - \ });\n\ - \ }\n\ - \ });\n\ - \ } else {\n\ - \ return done;\n\ - \ }\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} id\n\ - \ * @param {string} parent\n\ - \ * @returns {Promise}\n\ - \ */\n\ - function getAll(id, parent) {\n\ - \ return getModulePromise(id, parent).then(function (obj) {\n\ - \ if (obj) {\n\ - \ var deps = getDeps(obj.text);\n\ - \ return Promise.all(deps.map((x) => getAll(x, obj.link)));\n\ - \ } else {\n\ - \ throw new Error(`${id}@${parent} was not resolved successfully`);\n\ - \ }\n\ - \ });\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} text\n\ - \ * @param {string} parent\n\ - \ * @returns {Promise}\n\ - \ */\n\ - function getAllFromText(text, parent) {\n\ - \ var deps = getDeps(text);\n\ - \ return Promise.all(deps.map((x) => getAll(x, parent)));\n\ - }\n\ - \n\ - var evaluatedModules = new Map();\n\ - \n\ - function loadSync(id, parent) {\n\ - \ var baseOrModule = getIdLocationSync(id, parent);\n\ - \ if (baseOrModule && baseOrModule.link !== undefined) {\n\ - \ if (evaluatedModules.has(baseOrModule.link)) {\n\ - \ return evaluatedModules.get(baseOrModule.link).exports;\n\ - \ }\n\ - \ if (!baseOrModule.exports) {\n\ - \ baseOrModule.exports = {};\n\ - \ globalEval(\n\ - \ `(function(require,exports,module){${baseOrModule.text}\\n})//# sourceURL=${baseOrModule.link}`\n\ - \ )(\n\ - \ function require(id) {\n\ - \ return loadSync(id, baseOrModule.link);\n\ - \ }, // require\n\ - \ (baseOrModule.exports = {}), // exports\n\ - \ baseOrModule // module\n\ - \ );\n\ - \ }\n\ - \ if (!evaluatedModules.has(baseOrModule.link)) {\n\ - \ evaluatedModules.set(baseOrModule.link, baseOrModule);\n\ - \ }\n\ - \ return baseOrModule.exports;\n\ - \ } else {\n\ - \ throw new Error(`${id} : ${parent} could not be resolved`);\n\ - \ }\n\ - }\n\ - \n\ - function genEvalName() {\n\ - \ return \"eval-\" + (\"\" + Math.random()).substr(2, 5);\n\ - }\n\ - /**\n\ - \ *\n\ - \ * @param {string} text\n\ - \ * @param {string} link\n\ - \ * In this case [text] evaluated result will not be cached\n\ - \ */\n\ - function loadTextSync(text, link) {\n\ - \ var baseOrModule = { exports: {}, text, link };\n\ - \ globalEval(\n\ - \ `(function(require,exports,module){${baseOrModule.text}\\n})//# sourceURL=${\n\ - \ baseOrModule.link\n\ - \ }/${genEvalName()}.js`\n\ - \ )(\n\ - \ function require(id) {\n\ - \ return loadSync(id, baseOrModule.link);\n\ - \ }, // require\n\ - \ baseOrModule.exports, // exports\n\ - \ baseOrModule // module\n\ - \ );\n\ - \ return baseOrModule.exports;\n\ - }\n\ - \n\ - /**\n\ - \ *\n\ - \ * @param {string} text\n\ - \ */\n\ - function BSloadText(text) {\n\ - \ console.time(\"Loading\");\n\ - \ var parent = BsGetPath(\".\", document.baseURI);\n\ - \ return getAllFromText(text, parent).then(function () {\n\ - \ var result = loadTextSync(text, parent);\n\ - \ console.timeEnd(\"Loading\");\n\ - \ return result;\n\ - \ });\n\ - }\n\ - \n\ - function load(id, parent) {\n\ - \ return getAll(id, parent).then(function () {\n\ - \ return loadSync(id, parent);\n\ - \ });\n\ - }\n\ - \n\ - export function BSload(id) {\n\ - \ var parent = BsGetPath(\".\", document.baseURI);\n\ - \ return load(id, parent);\n\ - }\n\ - \n\ - export var BSLoader = {\n\ - \ loadText: BSloadText,\n\ - \ load: BSload,\n\ - \ SyncedIDLocations: SyncedIDLocations,\n\ - };\n\ - \n\ - window.BSLoader = BSLoader;\n\ - \n\ - var main = document.querySelector(\"script[data-main]\");\n\ - if (main) {\n\ - \ BSload(main.dataset.main);\n\ - }\n\ - " - ); - File("package.json", - "{\n\ - \ \"name\": \"${rescript:name}\",\n\ - \ \"version\": \"${rescript:proj-version}\",\n\ - \ \"scripts\": {\n\ - \ \"clean\": \"bsb -clean-world\",\n\ - \ \"build\": \"bsb -make-world\",\n\ - \ \"watch\": \"bsb -make-world -w -ws _\"\n\ - \ },\n\ - \ \"keywords\": [\n\ - \ \"ReScript\"\n\ - \ ],\n\ - \ \"author\": \"\",\n\ - \ \"license\": \"MIT\",\n\ - \ \"devDependencies\": {\n\ - \ \"${rescript:platform}\": \"^${rescript:bs-version}\"\n\ - \ },\n\ - \ \"dependencies\": {\n\ - \ \"bucklescript-tea\": \"^0.7.4\"\n\ - \ }\n\ - }\n\ - " - ); - Dir("src",[ - File("demo.ml", - "(* This line opens the Tea.App modules into the current scope for Program access functions and types *)\n\ - open Tea.App\n\ - \n\ - (* This opens the Elm-style virtual-dom functions and types into the current scope *)\n\ - open Tea.Html\n\ - \n\ - (* Let's create a new type here to be our main message type that is passed around *)\n\ - type msg =\n\ - \ | Increment (* This will be our message to increment the counter *)\n\ - \ | Decrement (* This will be our message to decrement the counter *)\n\ - \ | Reset (* This will be our message to reset the counter to 0 *)\n\ - \ | Set of int (* This will be our message to set the counter to a specific value *)\n\ - \ [@@bs.deriving {accessors}] (* This is a nice quality-of-life addon from Bucklescript, it will generate function names for each constructor name, optional, but nice to cut down on code, this is unused in this example but good to have regardless *)\n\ - \n\ - (* This is optional for such a simple example, but it is good to have an `init` function to define your initial model default values, the model for Counter is just an integer *)\n\ - let init () = 4\n\ - \n\ - (* This is the central message handler, it takes the model as the first argument *)\n\ - let update model = function (* These should be simple enough to be self-explanatory, mutate the model based on the message, easy to read and follow *)\n\ - \ | Increment -> model + 1\n\ - \ | Decrement -> model - 1\n\ - \ | Reset -> 0\n\ - \ | Set v -> v\n\ - \n\ - (* This is just a helper function for the view, a simple function that returns a button based on some argument *)\n\ - let view_button title msg =\n\ - \ button\n\ - \ [ onClick msg\n\ - \ ]\n\ - \ [ text title\n\ - \ ]\n\ - \n\ - (* This is the main callback to generate the virtual-dom.\n\ - \ This returns a virtual-dom node that becomes the view, only changes from call-to-call are set on the real DOM for efficiency, this is also only called once per frame even with many messages sent in within that frame, otherwise does nothing *)\n\ - let view model =\n\ - \ div\n\ - \ []\n\ - \ [ span\n\ - \ [ style \"text-weight\" \"bold\" ]\n\ - \ [ text (string_of_int model) ]\n\ - \ ; br []\n\ - \ ; view_button \"Increment\" Increment\n\ - \ ; br []\n\ - \ ; view_button \"Decrement\" Decrement\n\ - \ ; br []\n\ - \ ; view_button \"Set to 2\" (Set 42)\n\ - \ ; br []\n\ - \ ; if model <> 0 then view_button \"Reset\" Reset else noNode\n\ - \ ]\n\ - \n\ - (* This is the main function, it can be named anything you want but `main` is traditional.\n\ - \ The Program returned here has a set of callbacks that can easily be called from\n\ - \ Bucklescript or from javascript for running this main attached to an element,\n\ - \ or even to pass a message into the event loop. You can even expose the\n\ - \ constructors to the messages to javascript via the above [@@bs.deriving {accessors}]\n\ - \ attribute on the `msg` type or manually, that way even javascript can use it safely. *)\n\ - let main =\n\ - \ beginnerProgram { (* The beginnerProgram just takes a set model state and the update and view functions *)\n\ - \ model = init (); (* Since model is a set value here, we call our init function to generate that value *)\n\ - \ update;\n\ - \ view;\n\ - \ }" - ); - File("main.ml", - "\n\ - \n\ - \n\ - Js.Global.setTimeout\n\ - \ (fun _ -> \n\ - \ Demo.main (Web.Document.getElementById \"my-element\") () \n\ - \ |. ignore\n\ - \ ) \n\ - 0" - ) - ]); - File("watcher.js", - "\n\ - \n\ - var wsReloader;\n\ - var LAST_SUCCESS_BUILD_STAMP = (localStorage.getItem('LAST_SUCCESS_BUILD_STAMP') || 0)\n\ - var WS_PORT = 9999; // configurable\n\ - \n\ - function setUpWebScoket() {\n\ - \ if (wsReloader == null || wsReloader.readyState !== 1) {\n\ - \ try {\n\ - \ wsReloader = new WebSocket(`ws://${window.location.hostname}:${WS_PORT}`)\n\ - \ wsReloader.onmessage = (msg) => {\n\ - \ var newData = JSON.parse(msg.data).LAST_SUCCESS_BUILD_STAMP\n\ - \ if (newData > LAST_SUCCESS_BUILD_STAMP) {\n\ - \ LAST_SUCCESS_BUILD_STAMP = newData\n\ - \ localStorage.setItem('LAST_SUCCESS_BUILD_STAMP', LAST_SUCCESS_BUILD_STAMP)\n\ - \ location.reload(true)\n\ - \ }\n\ - \n\ - \ }\n\ - \ } catch (exn) {\n\ - \ console.error(\"web socket failed connect\")\n\ - \ }\n\ - \ }\n\ - };\n\ - \n\ - setUpWebScoket();\n\ - setInterval(setUpWebScoket, 2000);" - ) - ]) -]) -end -module Bsb_theme_init : sig -#1 "bsb_theme_init.mli" -(* Copyright (C) 2015 - 2016 Bloomberg Finance L.P. - * Copyright (C) 2017 - Hongbo Zhang, Authors of ReScript - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - -val init_sample_project : cwd:string -> theme:string -> string -> unit - -val list_themes : unit -> unit - -end = struct -#1 "bsb_theme_init.ml" -(* Copyright (C) 2015-2016 Bloomberg Finance L.P. - * Copyright (C) 2017 - Hongbo Zhang, Authors of ReScript - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - -type file_type = Directory | Non_directory_file | Non_exists - -let classify_file name = - let exists = Sys.file_exists name in - if exists then if Sys.is_directory name then Directory else Non_directory_file - else Non_exists - -let replace s env : string = - Bsb_regex.global_substitute s ~reg:"\\${rescript:\\([-a-zA-Z0-9]+\\)}" - (fun (_s : string) templates -> - match templates with - | key :: _ -> Hash_string.find_exn env key - | _ -> assert false) - -let ( // ) = Filename.concat - -let enter_dir cwd x action = - Unix.chdir x; - match action () with - | exception e -> - Unix.chdir cwd; - raise e - | v -> v - -let mkdir_or_not_if_exists dir = - match classify_file dir with - | Directory -> () - | Non_directory_file -> - Format.fprintf Format.err_formatter - "%s expected to be added as dir but exist file is not a dir" dir - | Non_exists -> Unix.mkdir dir 0o777 - -let rec process_theme_aux env cwd (x : Bsb_templates.node) = - match x with - | File (name, content) -> - let new_file = cwd // name in - if not @@ Sys.file_exists new_file then - Ext_io.write_file new_file (replace content env) - | Dir (current, nodes) -> - let new_cwd = cwd // current in - mkdir_or_not_if_exists new_cwd; - List.iter (fun x -> process_theme_aux env new_cwd x) nodes - -let list_themes () = - Format.fprintf Format.std_formatter "Available themes: @."; - Ext_list.iter Bsb_templates.root (fun x -> - match x with - | Dir (x, _) -> Format.fprintf Format.std_formatter "%s@." x - | _ -> ()) - -(* @raise [Not_found] *) -let process_themes env theme proj_dir (themes : Bsb_templates.node list) = - match - Ext_list.find_first themes (fun x -> - match x with Dir (dir, _) -> dir = theme | File _ -> false) - with - | None -> - list_themes (); - Bsb_arg.bad_arg ("theme " ^ theme ^ " not found") - | Some (Dir (_theme, nodes)) -> - List.iter (fun node -> process_theme_aux env proj_dir node) nodes - | Some _ -> assert false - -(** TODO: run npm link *) -let init_sample_project ~cwd ~theme name = - let env = Hash_string.create 0 in - List.iter - (fun (k, v) -> Hash_string.add env k v) - [ - ("proj-version", "0.1.0"); - ("bs-version", Bs_version.version); - ("bsb", Filename.current_dir_name // "node_modules" // ".bin" // "bsb"); - ("platform", !Bs_version.package_name); - ]; - let action _ = - process_themes env theme Filename.current_dir_name Bsb_templates.root - in - match name with - | "." -> - let name = Filename.basename cwd in - if Ext_namespace.is_valid_npm_package_name name then ( - Hash_string.add env "name" name; - action ()) - else ( - Format.fprintf Format.err_formatter - "@{Invalid package name@} %S@}: the project name must be both \ - a valid npm package name and a valid name as namespace@." - name; - exit 2) - | _ -> - if Ext_namespace.is_valid_npm_package_name name then ( - match classify_file name with - | Non_directory_file -> - Format.fprintf Format.err_formatter - "@{%s already exists but it is not a directory@}@." name; - exit 2 - | Directory -> - Format.fprintf Format.std_formatter - "Adding files into existing dir %s@." name; - Hash_string.add env "name" name; - enter_dir cwd name action - | Non_exists -> - Format.fprintf Format.std_formatter "Making directory %s@." name; - Unix.mkdir name 0o777; - Hash_string.add env "name" name; - enter_dir cwd name action) - else ( - Format.fprintf Format.err_formatter - "@{Invalid package name@} %S.@} The project name must be a \ - valid npm name, thus can't contain upper-case letters, for example." - name; - exit 2) - end module Bsb_world : sig #1 "bsb_world.mli" @@ -15218,8 +13061,6 @@ end = struct let () = Bsb_log.setup () -let current_theme = ref "basic" - let separator = "--" let watch_mode = ref false @@ -15383,24 +13224,6 @@ let clean_subcommand ~start argv = Bsb_clean.clean_bs_deps Bsb_global_paths.cwd; Bsb_clean.clean_self Bsb_global_paths.cwd -let init_usage = - "Usage: rescript init [folder-name]\n\n\ - `rescript init` adds a small ReScript project template to the current \ - folder\n\n\ - Pass folder-name to add them to a dedicated folder\n" - -let init_subcommand ~start argv = - Bsb_arg.parse_exn ~usage:init_usage ~start ~argv [||] (fun ~rev_args -> - let location = - match rev_args with - | [ x ] -> x - | last :: _another :: _ -> - raise (Bsb_arg.Bad ("Don't know what to do with " ^ last)) - | [] -> "." - in - Bsb_theme_init.init_sample_project ~cwd:Bsb_global_paths.cwd - ~theme:!current_theme location) - let list_files = ref false let info_subcommand ~start argv = @@ -15451,7 +13274,6 @@ let () = match argv.(1) with | "build" -> build_subcommand ~start:2 argv argv_len | "clean" -> clean_subcommand ~start:2 argv - | "init" -> init_subcommand ~start:2 argv | "info" -> (* internal *) info_subcommand ~start:2 argv diff --git a/lib/4.06.1/rescript.ml.d b/lib/4.06.1/rescript.ml.d index ebfcb8e90e..8d43697d5e 100644 --- a/lib/4.06.1/rescript.ml.d +++ b/lib/4.06.1/rescript.ml.d @@ -49,14 +49,8 @@ ../lib/4.06.1/rescript.ml: ./bsb/bsb_pkg_types.mli ../lib/4.06.1/rescript.ml: ./bsb/bsb_real_path.ml ../lib/4.06.1/rescript.ml: ./bsb/bsb_real_path.mli -../lib/4.06.1/rescript.ml: ./bsb/bsb_regex.ml -../lib/4.06.1/rescript.ml: ./bsb/bsb_regex.mli ../lib/4.06.1/rescript.ml: ./bsb/bsb_spec_set.ml ../lib/4.06.1/rescript.ml: ./bsb/bsb_spec_set.mli -../lib/4.06.1/rescript.ml: ./bsb/bsb_templates.ml -../lib/4.06.1/rescript.ml: ./bsb/bsb_templates.mli -../lib/4.06.1/rescript.ml: ./bsb/bsb_theme_init.ml -../lib/4.06.1/rescript.ml: ./bsb/bsb_theme_init.mli ../lib/4.06.1/rescript.ml: ./bsb/bsb_unix.ml ../lib/4.06.1/rescript.ml: ./bsb/bsb_unix.mli ../lib/4.06.1/rescript.ml: ./bsb/bsb_warning.ml diff --git a/scripts/dedupe.js b/scripts/dedupe.js index 0f2ff4473d..4bef63d912 100644 --- a/scripts/dedupe.js +++ b/scripts/dedupe.js @@ -34,7 +34,7 @@ var collection = new Map(); for (let file of filesPath) { let base = path.basename(file); if (collection.has(base)) { - if (base.endsWith(".ml") && !file.includes("templates")) { + if (base.endsWith(".ml")) { console.log(`duplicate ${base} : ${collection.get(base)} vs ${file}`); } } else { diff --git a/scripts/format.js b/scripts/format.js index 2411874cd4..66c5585f2e 100644 --- a/scripts/format.js +++ b/scripts/format.js @@ -28,7 +28,7 @@ var sourceDirs = [ // "ounit_tests", "main", ]; -var skips = ["dataset", "templates", "ident"]; +var skips = ["dataset", "ident"]; // ident comes from upstream for (let dir of sourceDirs) { let dir1 = path.join(__dirname, "..", "jscomp", dir); diff --git a/scripts/pack.js b/scripts/pack.js deleted file mode 100644 index e71d145a76..0000000000 --- a/scripts/pack.js +++ /dev/null @@ -1,107 +0,0 @@ -//@ts-check -var fs = require("fs"); -var path = require("path"); -var util = require("util"); -var child_process = require("child_process"); -// Note the escaping is escape to ocaml style string literals. -// `util.format` is useful to escape to js style string literrals. -// { name : "basic", children : ... } -// { name : "xx", content : ... } -/** - * - * @param {string} dir - */ -function scanDir(dir) { - var files = fs.readdirSync(dir).sort(); - var children = files.map(file => { - var curFile = path.join(dir, file); - var stat = fs.statSync(curFile); - if (stat.isFile()) { - var content = fs.readFileSync(curFile, "utf8"); - return { name: file, content }; - } else if (stat.isDirectory()) { - return scanDir(curFile); - } - }); - return { name: path.basename(dir), children }; -} - -/** - * - * @param {string} s - * @param {number} indent - */ -function escape(s, indent) { - return ( - " ".repeat(indent) + - '"' + - s.replace(/(\n|"|\\|\t|\r)/g, (match, _, offset) => { - switch (match) { - case "\n": - var o = `\\n\\ -${" ".repeat(indent)}`; - if (s[offset + 1] === " ") { - o += "\\"; - } - return o; - default: - return "\\" + match; - } - }) + - '"' - ); -} - -function toString(data, indent) { - var output = ""; - if (data.children) { - output += `${" ".repeat(indent)}Dir("${data.name}",[ -${data.children.map(x => toString(x, indent + 1)).join(";\n")} -${" ".repeat(indent)}])`; - } else { - output += `${" ".repeat(indent)}File("${data.name}", -${escape(data.content, indent)} -${" ".repeat(indent)})`; - } - return output; -} - -/** - * - */ -function updateThemes() { - var templatesDir = path.join(__dirname, "..", "jscomp", "bsb", "templates"); - var output = child_process.spawnSync(`git clean -dfx ${templatesDir}`, { - shell: true, - encoding: "utf-8", - }); - if (output.error) { - throw output.error; - } - console.log(output.stdout); - if (output.status !== 0) { - console.log(output.stderr); - } - - // run git clean -dfx . first - fs.writeFileSync( - path.join(templatesDir, "..", "bsb_templates.ml"), - ` -type node = - | Dir of string * node list - | File of string * string -let root = ([ -${fs - .readdirSync(templatesDir) - .filter(x => fs.statSync(path.join(templatesDir, x)).isDirectory()) - .map(x => toString(scanDir(path.join(templatesDir, x)), 3)) - .join(";\n")} -])`, - "utf8" - ); -} -exports.updateThemes = updateThemes; - -if (require.main === module) { - updateThemes(); -} diff --git a/scripts/release.js b/scripts/release.js index b53c7abcb5..2dd8cd802e 100755 --- a/scripts/release.js +++ b/scripts/release.js @@ -21,8 +21,6 @@ function run() { `git clean -dfx stubs ext common syntax depends core bsb main .`, { cwd: jscompDir, encoding: "utf8", stdio: [0, 1, 2] } ); - // cp.execSync(`git clean -dfx templates && ocp-ocamlres templates -o bsb_templates.ml`, - // { cwd: path.join(jscompDir,'bsb'), encoding: 'utf8', stdio: [0, 1, 2] }) cp.execSync(`ninja -t clean -g && ninja`, { cwd: jscompDir, encoding: "utf8", From 44d74773c714071ad381e7f34c480693d3711f20 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Thu, 22 Sep 2022 17:17:28 +0200 Subject: [PATCH 2/2] Remove init subcommand from script --- rescript | 2 -- 1 file changed, 2 deletions(-) diff --git a/rescript b/rescript index f200dc0d6b..6369e5decb 100755 --- a/rescript +++ b/rescript @@ -171,7 +171,6 @@ Options: -h, -help display help Subcommands: - init build clean format @@ -242,7 +241,6 @@ if ( maybe_subcommand !== undefined && maybe_subcommand !== "build" && maybe_subcommand !== "clean" && - maybe_subcommand !== "init" && maybe_subcommand !== "info" // delegate to native ) {