From 8d0366d95d9a876b3f3940fe22068b22f0409faf Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Wed, 18 Nov 2020 16:09:24 +0100 Subject: [PATCH 01/78] Add github-slugger bindings --- bindings/GithubSlugger.js | 2 ++ bindings/GithubSlugger.res | 1 + 2 files changed, 3 insertions(+) create mode 100644 bindings/GithubSlugger.js create mode 100644 bindings/GithubSlugger.res diff --git a/bindings/GithubSlugger.js b/bindings/GithubSlugger.js new file mode 100644 index 000000000..d856702bf --- /dev/null +++ b/bindings/GithubSlugger.js @@ -0,0 +1,2 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/bindings/GithubSlugger.res b/bindings/GithubSlugger.res new file mode 100644 index 000000000..8faf4c6cb --- /dev/null +++ b/bindings/GithubSlugger.res @@ -0,0 +1 @@ +@module("github-slugger") external slug: string => string = "slug" From 77b0a2708c71b2c58e4e9027c2268249af831d59 Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Wed, 18 Nov 2020 16:11:03 +0100 Subject: [PATCH 02/78] Add syntax lookup widget / page --- components/SyntaxLookupWidget.js | 285 ++++++++++++++++++++++++ components/SyntaxLookupWidget.res | 266 ++++++++++++++++++++++ components/SyntaxLookupWidget.resi | 2 + misc_docs/syntax/controlflow_ifelse.mdx | 16 ++ misc_docs/syntax/decorator_as.mdx | 26 +++ misc_docs/syntax/decorator_module.mdx | 1 + misc_docs/syntax/decorator_new.mdx | 34 +++ misc_docs/syntax/decorator_send.mdx | 1 + misc_docs/syntax/decorator_val.mdx | 3 + pages/syntax-lookup.mdx | 9 + src/DocsOverview.js | 7 + src/DocsOverview.res | 2 + 12 files changed, 652 insertions(+) create mode 100644 components/SyntaxLookupWidget.js create mode 100644 components/SyntaxLookupWidget.res create mode 100644 components/SyntaxLookupWidget.resi create mode 100644 misc_docs/syntax/controlflow_ifelse.mdx create mode 100644 misc_docs/syntax/decorator_as.mdx create mode 100644 misc_docs/syntax/decorator_module.mdx create mode 100644 misc_docs/syntax/decorator_new.mdx create mode 100644 misc_docs/syntax/decorator_send.mdx create mode 100644 misc_docs/syntax/decorator_val.mdx create mode 100644 pages/syntax-lookup.mdx diff --git a/components/SyntaxLookupWidget.js b/components/SyntaxLookupWidget.js new file mode 100644 index 000000000..623360c3e --- /dev/null +++ b/components/SyntaxLookupWidget.js @@ -0,0 +1,285 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Curry from "bs-platform/lib/es6/curry.js"; +import * as React from "react"; +import * as Js_dict from "bs-platform/lib/es6/js_dict.js"; +import FuseJs from "fuse.js"; +import * as Markdown from "./Markdown.js"; +import * as Belt_Array from "bs-platform/lib/es6/belt_Array.js"; +import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; +import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; +import * as Router from "next/router"; +import * as GithubSlugger from "github-slugger"; +import Decorator_asMdx from "misc_docs/syntax/decorator_as.mdx"; +import Decorator_moduleMdx from "misc_docs/syntax/decorator_module.mdx"; +import Controlflow_ifelseMdx from "misc_docs/syntax/controlflow_ifelse.mdx"; + +var render = (function(c) { + return React.createElement(c, {}); + }); + +function toString(t) { + switch (t) { + case /* Decorators */0 : + return "Decorators"; + case /* ControlFlow */1 : + return "Control Flow"; + case /* Operators */2 : + return "Operators"; + case /* Other */3 : + return "Other"; + + } +} + +function SyntaxLookupWidget$Category(Props) { + var title = Props.title; + var children = Props.children; + return React.createElement("div", undefined, React.createElement("h3", { + className: "font-sans font-black text-night-light tracking-wide text-xs uppercase" + }, title), children); +} + +var allItems = [ + { + keywords: ["@bs.module"], + name: "@module", + summary: "This is the @module decorator.", + category: /* Decorators */0, + component: Decorator_moduleMdx + }, + { + keywords: ["@bs.as"], + name: "@as", + summary: "This is the @as decorator.", + category: /* Decorators */0, + component: Decorator_asMdx + }, + { + keywords: [ + "if", + "else", + "if else" + ], + name: "if / else", + summary: "This is the if / else control flow structure.", + category: /* ControlFlow */1, + component: Controlflow_ifelseMdx + } +]; + +console.log(Decorator_asMdx.frontmatter); + +var fuseOpts = { + shouldSort: false, + includeScore: true, + threshold: 0.2, + location: 0, + distance: 30, + minMatchCharLength: 1, + keys: [ + "keywords", + "name" + ] +}; + +var fuse = new FuseJs(allItems, fuseOpts); + +function getAnchor(path) { + var match = path.split("#"); + if (match.length !== 2) { + return ; + } else { + return match[1]; + } +} + +function SyntaxLookupWidget$SearchBox(Props) { + var onChange = Props.onChange; + return React.createElement("div", { + className: "bg-" + }, React.createElement("input", { + className: "border border-snow-dark bg-snow-light", + type: "text", + onChange: onChange + })); +} + +function SyntaxLookupWidget$Tag(Props) { + var text = Props.text; + return React.createElement("span", { + className: "bg-fire-15 p-1 px-2 font-semibold rounded-lg text-fire text-16" + }, text); +} + +function SyntaxLookupWidget$DetailBox(Props) { + var summary = Props.summary; + var children = Props.children; + return React.createElement("div", undefined, React.createElement("div", { + className: "text-21 text-center mb-4 font-semibold" + }, summary), React.createElement("div", { + className: "border rounded-lg shadow-xs p-4" + }, children)); +} + +function SyntaxLookupWidget(Props) { + var router = Router.useRouter(); + var match = React.useState(function () { + return /* ShowAll */0; + }); + var setState = match[1]; + var state = match[0]; + React.useEffect((function () { + var anchor = getAnchor(router.asPath); + if (anchor !== undefined) { + Belt_Option.forEach(Caml_option.undefined_to_opt(allItems.find(function (item) { + return GithubSlugger.slug(item.name) === anchor; + })), (function (item) { + return Curry._1(setState, (function (param) { + return { + TAG: 1, + _0: item, + [Symbol.for("name")]: "ShowDetails" + }; + })); + })); + } + + }), []); + React.useEffect((function () { + var match = getAnchor(router.asPath); + var exit = 0; + if (typeof state === "number" || !state.TAG) { + exit = 1; + } else { + var item = state._0; + if (match !== undefined) { + var slug = GithubSlugger.slug(item.name); + if (slug !== match) { + router.replace("syntax-lookup#" + match); + } + + } else { + router.replace("syntax-lookup#" + GithubSlugger.slug(item.name)); + } + } + if (exit === 1) { + if (match !== undefined) { + router.replace("syntax-lookup"); + } + + } + + }), [state]); + var onChange = function (evt) { + evt.preventDefault(); + var value = evt.target.value; + return Curry._1(setState, (function (param) { + if (value === "") { + return /* ShowAll */0; + } + var filtered = Belt_Array.map(fuse.search(value), (function (m) { + return m.item; + })); + if (filtered.length === 1) { + return { + TAG: 1, + _0: filtered[0], + [Symbol.for("name")]: "ShowDetails" + }; + } else { + return { + TAG: 0, + _0: filtered, + [Symbol.for("name")]: "ShowFiltered" + }; + } + })); + }; + var details; + if (typeof state === "number" || !state.TAG) { + details = null; + } else { + var item = state._0; + details = React.createElement("div", { + className: "mb-16" + }, React.createElement(SyntaxLookupWidget$DetailBox, { + summary: item.summary, + children: render(item.component) + })); + } + var initial = Belt_Array.map([ + /* Decorators */0, + /* Operators */2, + /* ControlFlow */1, + /* Other */3 + ], (function (cat) { + return [ + toString(cat), + [] + ]; + })); + var items; + items = typeof state === "number" ? allItems : ( + state.TAG ? [] : state._0 + ); + var categories = Belt_Array.reduce(Js_dict.entries(Belt_Array.reduce(items, Js_dict.fromArray(initial), (function (acc, item) { + var key = toString(item.category); + return Belt_Option.mapWithDefault(Js_dict.get(acc, key), acc, (function (items) { + items.push(item); + acc[key] = items; + return acc; + })); + }))), [], (function (acc, entry) { + var items = entry[1]; + if (items.length === 0) { + return acc; + } + var title = entry[0]; + var children = Belt_Array.map(items, (function (item) { + var onMouseDown = function (evt) { + evt.preventDefault(); + return Curry._1(setState, (function (param) { + return { + TAG: 1, + _0: item, + [Symbol.for("name")]: "ShowDetails" + }; + })); + }; + return React.createElement("span", { + key: item.name, + className: "mr-2 cursor-pointer", + onMouseDown: onMouseDown + }, React.createElement(SyntaxLookupWidget$Tag, { + text: item.name + })); + })); + var el = React.createElement(SyntaxLookupWidget$Category, { + title: title, + children: children, + key: title + }); + acc.push(el); + return acc; + })); + return React.createElement("div", undefined, React.createElement("div", { + className: "text-center" + }, React.createElement(Markdown.H1.make, { + children: "Syntax Lookup" + }), React.createElement("div", { + className: "mb-8" + }, "Enter some language construct you want to know more about."), React.createElement("div", undefined, React.createElement(SyntaxLookupWidget$SearchBox, { + onChange: onChange + }))), React.createElement("div", { + className: "mt-10" + }, details, categories)); +} + +var make = SyntaxLookupWidget; + +export { + make , + +} +/* allItems Not a pure module */ diff --git a/components/SyntaxLookupWidget.res b/components/SyntaxLookupWidget.res new file mode 100644 index 000000000..9add6d4a7 --- /dev/null +++ b/components/SyntaxLookupWidget.res @@ -0,0 +1,266 @@ +module MdxComp = { + type props + type t = Js.t => React.element + + let render: t => React.element = %raw( + ` + function(c) { + return React.createElement(c, {}); + } + ` + ) + + @bs.get + external frontmatter: t => Js.Json.t = "frontmatter" +} + +@module("misc_docs/syntax/decorator_module.mdx") +external decorator_module: MdxComp.t = "default" + +@module("misc_docs/syntax/decorator_as.mdx") +external decorator_as: MdxComp.t = "default" + +@module("misc_docs/syntax/controlflow_ifelse.mdx") +external controlflow_ifelse: MdxComp.t = "default" + +module Category = { + type t = Decorators | ControlFlow | Operators | Other + + let toString = t => + switch t { + | Decorators => "Decorators" + | Operators => "Operators" + | ControlFlow => "Control Flow" + | Other => "Other" + } + + @react.component + let make = (~title, ~children) => { +
+

+ {React.string(title)} +

+ children +
+ } +} + +type item = { + keywords: array, + name: string, + summary: string, + category: Category.t, + component: MdxComp.t, +} + +let allItems = [ + { + keywords: ["@bs.module"], + name: "@module", + summary: "This is the @module decorator.", + category: Decorators, + component: decorator_module, + }, + { + keywords: ["@bs.as"], + name: "@as", + summary: "This is the @as decorator.", + category: Decorators, + component: decorator_as, + }, + { + keywords: ["if", "else", "if else"], + name: "if / else", + summary: "This is the if / else control flow structure.", + category: ControlFlow, + component: controlflow_ifelse, + }, +] + +decorator_as->MdxComp.frontmatter->Js.log + +let fuseOpts = Fuse.Options.t( + ~shouldSort=false, + ~includeScore=true, + ~threshold=0.2, + ~location=0, + ~distance=30, + ~minMatchCharLength=1, + ~keys=["keywords", "name"], + (), +) + +let fuse: Fuse.t = Fuse.make(allItems, fuseOpts) + +let getAnchor = path => { + switch Js.String2.split(path, "#") { + | [_, anchor] => Some(anchor) + | _ => None + } +} + +module SearchBox = { + @react.component + let make = (~onChange) => { +
+ +
+ } +} + +module Tag = { + @react.component + let make = (~text: string) => { + + {React.string(text)} + + } +} + +module DetailBox = { + @react.component + let make = (~summary, ~children) => { +
+
{React.string(summary)}
+
children
+
+ } +} + +type state = + | ShowAll + | ShowFiltered(array) + | ShowDetails(item) + +@react.component +let make = () => { + let router = Next.Router.useRouter() + let (state, setState) = React.useState(_ => ShowAll) + + React.useEffect0(() => { + switch getAnchor(router.asPath) { + | Some(anchor) => + Js.Array2.find(allItems, item => + GithubSlugger.slug(item.name) === anchor + )->Belt.Option.forEach(item => { + setState(_ => ShowDetails(item)) + }) + | None => () + } + None + }) + + /* + This effect syncs the url anchor with the currently shown final match + within the fuzzy finder. If there is a new match that doesn't align with + the current anchor, the url will be rewritten with the correct anchor. + + In case a selection got removed, it will also remove the anchor from the url. + We don't replace on every state change, because replacing the url is expensive + */ + React.useEffect1(() => { + switch (state, getAnchor(router.asPath)) { + | (ShowDetails(item), Some(anchor)) => + let slug = GithubSlugger.slug(item.name) + + if slug !== anchor { + router->Next.Router.replace("syntax-lookup#" ++ anchor) + } else { + () + } + | (ShowDetails(item), None) => + router->Next.Router.replace("syntax-lookup#" ++ GithubSlugger.slug(item.name)) + | (_, Some(_)) => router->Next.Router.replace("syntax-lookup") + | _ => () + } + None + }, [state]) + + let onChange = evt => { + ReactEvent.Form.preventDefault(evt) + let value = ReactEvent.Form.target(evt)["value"] + + setState(_ => + switch value { + | "" => ShowAll + | search => + let filtered = fuse->Fuse.search(search)->Belt.Array.map(m => { + m["item"] + }) + if Js.Array.length(filtered) === 1 { + ShowDetails(Js.Array2.unsafe_get(filtered, 0)) + } else { + ShowFiltered(filtered) + } + } + ) + /* if value === "" { */ + /* setState(_prev => All) */ + /* } else { */ + /* setState(_prev => Filtered(value)) */ + /* } */ + } + + let details = switch state { + | ShowFiltered(_) + | ShowAll => React.null + | ShowDetails(item) => +
+ {MdxComp.render(item.component)} +
+ } + + /* + Order all items in tag groups + */ + let categories = { + open Category + let initial = [Decorators, Operators, ControlFlow, Other]->Belt.Array.map(cat => { + (cat->toString, []) + }) + + let items = switch state { + | ShowAll => allItems + | ShowDetails(_) => [] + | ShowFiltered(items) => items + } + + Belt.Array.reduce(items, Js.Dict.fromArray(initial), (acc, item) => { + let key = item.category->toString + Js.Dict.get(acc, key)->Belt.Option.mapWithDefault(acc, items => { + Js.Array2.push(items, item)->ignore + Js.Dict.set(acc, key, items) + acc + }) + })->Js.Dict.entries->Belt.Array.reduce([], (acc, entry) => { + let (title, items) = entry + if Js.Array.length(items) === 0 { + acc + } else { + let children = Belt.Array.map(items, item => { + let onMouseDown = evt => { + ReactEvent.Mouse.preventDefault(evt) + setState(_ => ShowDetails(item)) + } + + + + }) + let el = {React.array(children)} + Js.Array2.push(acc, el)->ignore + acc + } + }) + } + +
+
+ {React.string("Syntax Lookup")} +
+ {React.string("Enter some language construct you want to know more about.")} +
+
+
+
{details} {React.array(categories)}
+
+} diff --git a/components/SyntaxLookupWidget.resi b/components/SyntaxLookupWidget.resi new file mode 100644 index 000000000..1ca44ce26 --- /dev/null +++ b/components/SyntaxLookupWidget.resi @@ -0,0 +1,2 @@ +@react.component +let make: unit => React.element diff --git a/misc_docs/syntax/controlflow_ifelse.mdx b/misc_docs/syntax/controlflow_ifelse.mdx new file mode 100644 index 000000000..3cc3c48d3 --- /dev/null +++ b/misc_docs/syntax/controlflow_ifelse.mdx @@ -0,0 +1,16 @@ +--- +test: "foo" +--- + +Use `if / else` expressions to express a value trough a `true` / `false` condition. + +```res +let user = "Anna" + +let ret = if user === "Anna" { + "Hi Anna!" +} +else { + "Hi unknown!" +} +``` diff --git a/misc_docs/syntax/decorator_as.mdx b/misc_docs/syntax/decorator_as.mdx new file mode 100644 index 000000000..5926018cc --- /dev/null +++ b/misc_docs/syntax/decorator_as.mdx @@ -0,0 +1,26 @@ +--- +test: "foo" +--- + +Use this decorator on record types to alias record names to a different JS attribute name. + +This is mostly useful to map to JS attribute names that cannot be expressed in ReScript (such as keywords). + +### Example + + + +```reason +type action = { + [@bs.as "type"] _type: string, +}; +``` + +```js +var action = { + type: "ADD_USER" +}; +``` + + +Refer to the [Records as Objects](/docs/manual/latest/bind-to-js-object#bind-using-rescript-record) section for a more detailed explanation. diff --git a/misc_docs/syntax/decorator_module.mdx b/misc_docs/syntax/decorator_module.mdx new file mode 100644 index 000000000..4eba66db7 --- /dev/null +++ b/misc_docs/syntax/decorator_module.mdx @@ -0,0 +1 @@ +used for [this](https://google.com) and [that](https://google.com) diff --git a/misc_docs/syntax/decorator_new.mdx b/misc_docs/syntax/decorator_new.mdx new file mode 100644 index 000000000..1a4ed55ee --- /dev/null +++ b/misc_docs/syntax/decorator_new.mdx @@ -0,0 +1,34 @@ +This decorator is used whenever you need to bind to a JS class constructor that requires the `new` keword for instantiation. + + + +```res +type t +@bs.new external create: unit => t = "Date" + +create(); +``` + +```js +new Date(); +``` + + + +When the object is not available on the global scope, combine it with `@module`: + + + +```res +type t; +@module @bs.new external book: unit => t = "Book"; + +let myBook = book(); +``` + +```js +var Book = require("Book"); +var myBook = new Book(); +``` + + diff --git a/misc_docs/syntax/decorator_send.mdx b/misc_docs/syntax/decorator_send.mdx new file mode 100644 index 000000000..b8eafdd7d --- /dev/null +++ b/misc_docs/syntax/decorator_send.mdx @@ -0,0 +1 @@ +This decorator is used to "send a value" to an instance of an object. diff --git a/misc_docs/syntax/decorator_val.mdx b/misc_docs/syntax/decorator_val.mdx new file mode 100644 index 000000000..434b0c25b --- /dev/null +++ b/misc_docs/syntax/decorator_val.mdx @@ -0,0 +1,3 @@ +This decorator is used to bind to a value in global scope. + +**Also see:** `@bs.val` diff --git a/pages/syntax-lookup.mdx b/pages/syntax-lookup.mdx new file mode 100644 index 000000000..ed8363b85 --- /dev/null +++ b/pages/syntax-lookup.mdx @@ -0,0 +1,9 @@ +--- +title: "Syntax Lookup" +description: "Discover ReScript syntax constructs with our discovery tool" +canonical: "/docs/manual/latest/syntax-discovery" +--- + +import { make as SyntaxLookupWidget } from "components/SyntaxLookupWidget" + + diff --git a/src/DocsOverview.js b/src/DocsOverview.js index 7ec9a147c..c4d10ebf7 100644 --- a/src/DocsOverview.js +++ b/src/DocsOverview.js @@ -74,6 +74,10 @@ function DocsOverview$default(Props) { "https://github.com/reason-association/reanalyze" ] ]; + var tools = [[ + "Syntax Lookup", + "/syntax-lookup" + ]]; var versionSelect; if (showVersionSelect) { var onChange = function (evt) { @@ -105,6 +109,9 @@ function DocsOverview$default(Props) { }), React.createElement(DocsOverview$Card, { title: "Ecosystem", hrefs: ecosystem + }), React.createElement(DocsOverview$Card, { + title: "Tools", + hrefs: tools }))); } diff --git a/src/DocsOverview.res b/src/DocsOverview.res index 4b739b8d7..f62665766 100644 --- a/src/DocsOverview.res +++ b/src/DocsOverview.res @@ -39,6 +39,7 @@ let default = (~showVersionSelect=true) => { ("ReasonReact", "https://reasonml.github.io/reason-react"), ("Reanalyze", "https://github.com/reason-association/reanalyze"), ] + let tools = [("Syntax Lookup", "/syntax-lookup")] let versionSelect = if showVersionSelect { let onChange = evt => { @@ -65,6 +66,7 @@ let default = (~showVersionSelect=true) => {
+
} From 4163453f58d598f3a5976deebf95dffcd23b21ff Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Wed, 18 Nov 2020 20:52:43 +0100 Subject: [PATCH 03/78] Add uncurried function misc docs --- misc_docs/syntax/function_uncurried.mdx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 misc_docs/syntax/function_uncurried.mdx diff --git a/misc_docs/syntax/function_uncurried.mdx b/misc_docs/syntax/function_uncurried.mdx new file mode 100644 index 000000000..d6d0e1503 --- /dev/null +++ b/misc_docs/syntax/function_uncurried.mdx @@ -0,0 +1,11 @@ +--- +test: "foo" +--- + +The `(.) => { ... }` (uncurried) syntax defines a function type that is not curried by default. This is useful whenever you want to make sure that your function is not being curried unintentionally, or if you want to force the compiler to emit cleaner JS source code (JS doesn't have curried functions by default). + +```res +let myFn = (cb: (. int) => unit) => { + cb(. 1) +} +``` From 02b6da1154efba66919a58a6dc0f55be4945d0a9 Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Wed, 18 Nov 2020 20:52:58 +0100 Subject: [PATCH 04/78] Improved Searchbox / UI --- components/SyntaxLookupWidget.js | 225 +++++++++++++++++++++++++----- components/SyntaxLookupWidget.res | 192 ++++++++++++++++++++----- tailwind.config.js | 3 +- 3 files changed, 348 insertions(+), 72 deletions(-) diff --git a/components/SyntaxLookupWidget.js b/components/SyntaxLookupWidget.js index 623360c3e..425eb7dec 100644 --- a/components/SyntaxLookupWidget.js +++ b/components/SyntaxLookupWidget.js @@ -1,5 +1,6 @@ // Generated by ReScript, PLEASE EDIT WITH CARE +import * as Icon from "./Icon.js"; import * as Curry from "bs-platform/lib/es6/curry.js"; import * as React from "react"; import * as Js_dict from "bs-platform/lib/es6/js_dict.js"; @@ -36,22 +37,22 @@ function SyntaxLookupWidget$Category(Props) { var title = Props.title; var children = Props.children; return React.createElement("div", undefined, React.createElement("h3", { - className: "font-sans font-black text-night-light tracking-wide text-xs uppercase" - }, title), children); + className: "font-sans font-medium text-gray-100 tracking-wide text-14 uppercase mb-2" + }, title), React.createElement("div", undefined, children)); } var allItems = [ { keywords: ["@bs.module"], name: "@module", - summary: "This is the @module decorator.", + summary: "This is the `@module` decorator.", category: /* Decorators */0, component: Decorator_moduleMdx }, { keywords: ["@bs.as"], name: "@as", - summary: "This is the @as decorator.", + summary: "This is the `@as` decorator.", category: /* Decorators */0, component: Decorator_asMdx }, @@ -62,14 +63,19 @@ var allItems = [ "if else" ], name: "if / else", - summary: "This is the if / else control flow structure.", + summary: "This is the `if / else` control flow structure.", category: /* ControlFlow */1, component: Controlflow_ifelseMdx + }, + { + keywords: ["uncurried"], + name: "(.) => {}", + summary: "This is an `uncurried` function.", + category: /* Other */3, + component: Controlflow_ifelseMdx } ]; -console.log(Decorator_asMdx.frontmatter); - var fuseOpts = { shouldSort: false, includeScore: true, @@ -95,30 +101,129 @@ function getAnchor(path) { } function SyntaxLookupWidget$SearchBox(Props) { - var onChange = Props.onChange; + var completionValuesOpt = Props.completionValues; + var value = Props.value; + var onClear = Props.onClear; + var onValueChange = Props.onValueChange; + var completionValues = completionValuesOpt !== undefined ? completionValuesOpt : []; + var match = React.useState(function () { + return /* Inactive */1; + }); + var setState = match[1]; + var state = match[0]; + var textInput = React.useRef(null); + var onMouseDownClear = function (evt) { + evt.preventDefault(); + return Curry._1(onClear, undefined); + }; + var onAreaFocus = function (_evt) { + if (state === /* Inactive */1) { + return Belt_Option.forEach(Caml_option.nullable_to_opt(textInput.current), (function (el) { + el.focus(); + + })); + } + + }; + var onFocus = function (param) { + return Curry._1(setState, (function (param) { + return /* Active */0; + })); + }; + var onBlur = function (param) { + return Curry._1(setState, (function (param) { + return /* Inactive */1; + })); + }; + var onKeyDown = function (evt) { + var key = evt.key; + var ctrlKey = evt.ctrlKey; + var full = ( + ctrlKey ? "CTRL+" : "" + ) + key; + switch (full) { + case "Escape" : + return Curry._1(onClear, undefined); + case "Tab" : + if (completionValues.length !== 1) { + return ; + } + var targetValue = Belt_Array.getExn(completionValues, 0); + if (targetValue !== value) { + evt.preventDefault(); + return Curry._1(onValueChange, targetValue); + } else { + return ; + } + default: + return ; + } + }; + var onChange = function (evt) { + evt.preventDefault(); + return Curry._1(onValueChange, evt.target.value); + }; return React.createElement("div", { - className: "bg-" - }, React.createElement("input", { - className: "border border-snow-dark bg-snow-light", + className: ( + state === /* Active */0 ? "border-fire" : "border-fire-40" + ) + " flex items-center border rounded-lg py-4 px-5", + tabIndex: -1, + onFocus: onAreaFocus + }, React.createElement(Icon.MagnifierGlass.make, { + className: ( + state === /* Active */0 ? "text-fire" : "text-fire-80" + ) + " w-4 h-4" + }), React.createElement("input", { + ref: textInput, + className: "text-16 outline-none ml-4 w-full", + placeholder: "Enter keywords or syntax...", type: "text", + value: value, + onKeyDown: onKeyDown, + onFocus: onFocus, + onBlur: onBlur, onChange: onChange - })); + }), React.createElement("button", { + className: value === "" ? "hidden" : "block", + onMouseDown: onMouseDownClear + }, React.createElement(Icon.Close.make, { + className: "w-4 h-4 text-fire" + }))); } function SyntaxLookupWidget$Tag(Props) { var text = Props.text; return React.createElement("span", { - className: "bg-fire-15 p-1 px-2 font-semibold rounded-lg text-fire text-16" + className: "bg-fire-10-tr py-1 px-3 rounded text-fire text-16" }, text); } function SyntaxLookupWidget$DetailBox(Props) { var summary = Props.summary; var children = Props.children; + var more = summary.split("`"); + var len = more.length; + var summaryEl; + if (len !== 3) { + summaryEl = len !== 0 ? Belt_Array.map(more, (function (s) { + return s; + })) : null; + } else { + var first = more[0]; + var second = more[1]; + var third = more[2]; + summaryEl = [ + first, + React.createElement("span", { + className: "text-fire" + }, second), + third + ]; + } return React.createElement("div", undefined, React.createElement("div", { - className: "text-21 text-center mb-4 font-semibold" - }, summary), React.createElement("div", { - className: "border rounded-lg shadow-xs p-4" + className: "text-21 border-b border-fire-40 pb-4 mb-4 font-semibold" + }, summaryEl), React.createElement("div", { + className: "mt-16" }, children)); } @@ -171,9 +276,7 @@ function SyntaxLookupWidget(Props) { } }), [state]); - var onChange = function (evt) { - evt.preventDefault(); - var value = evt.target.value; + var onSearchValueChange = function (value) { return Curry._1(setState, (function (param) { if (value === "") { return /* ShowAll */0; @@ -181,16 +284,26 @@ function SyntaxLookupWidget(Props) { var filtered = Belt_Array.map(fuse.search(value), (function (m) { return m.item; })); - if (filtered.length === 1) { + if (filtered.length !== 1) { + return { + TAG: 0, + _0: value, + _1: filtered, + [Symbol.for("name")]: "ShowFiltered" + }; + } + var item = Belt_Array.getExn(filtered, 0); + if (item.name === value) { return { TAG: 1, - _0: filtered[0], + _0: item, [Symbol.for("name")]: "ShowDetails" }; } else { return { TAG: 0, - _0: filtered, + _0: value, + _1: filtered, [Symbol.for("name")]: "ShowFiltered" }; } @@ -221,7 +334,7 @@ function SyntaxLookupWidget(Props) { })); var items; items = typeof state === "number" ? allItems : ( - state.TAG ? [] : state._0 + state.TAG ? [] : state._1 ); var categories = Belt_Array.reduce(Js_dict.entries(Belt_Array.reduce(items, Js_dict.fromArray(initial), (function (acc, item) { var key = toString(item.category); @@ -249,28 +362,68 @@ function SyntaxLookupWidget(Props) { }; return React.createElement("span", { key: item.name, - className: "mr-2 cursor-pointer", + className: "first:ml-0 ml-2 cursor-pointer", onMouseDown: onMouseDown }, React.createElement(SyntaxLookupWidget$Tag, { text: item.name })); })); - var el = React.createElement(SyntaxLookupWidget$Category, { - title: title, - children: children, - key: title - }); + var el = React.createElement("div", { + className: "first:mt-0 mt-12" + }, React.createElement(SyntaxLookupWidget$Category, { + title: title, + children: children, + key: title + })); acc.push(el); return acc; })); + var match$1; + if (typeof state === "number") { + match$1 = [ + "", + allItems + ]; + } else if (state.TAG) { + var item$1 = state._0; + match$1 = [ + item$1.name, + [item$1] + ]; + } else { + match$1 = [ + state._0, + state._1 + ]; + } + var onSearchClear = function (param) { + return Curry._1(setState, (function (param) { + return /* ShowAll */0; + })); + }; return React.createElement("div", undefined, React.createElement("div", { - className: "text-center" - }, React.createElement(Markdown.H1.make, { - children: "Syntax Lookup" - }), React.createElement("div", { - className: "mb-8" - }, "Enter some language construct you want to know more about."), React.createElement("div", undefined, React.createElement(SyntaxLookupWidget$SearchBox, { - onChange: onChange + className: "flex flex-col items-center" + }, React.createElement("div", { + className: "text-center", + style: { + maxWidth: "21rem" + } + }, React.createElement(Markdown.H1.make, { + children: "Syntax Lookup" + }), React.createElement("div", { + className: "mb-8 text-gray-60-tr text-14" + }, "Enter some language construct you want to know more about.")), React.createElement("div", { + className: "w-full", + style: { + maxWidth: "34rem" + } + }, React.createElement(SyntaxLookupWidget$SearchBox, { + completionValues: Belt_Array.map(match$1[1], (function (item) { + return item.name; + })), + value: match$1[0], + onClear: onSearchClear, + onValueChange: onSearchValueChange }))), React.createElement("div", { className: "mt-10" }, details, categories)); diff --git a/components/SyntaxLookupWidget.res b/components/SyntaxLookupWidget.res index 9add6d4a7..0cf373a46 100644 --- a/components/SyntaxLookupWidget.res +++ b/components/SyntaxLookupWidget.res @@ -37,10 +37,10 @@ module Category = { @react.component let make = (~title, ~children) => {
-

+

{React.string(title)}

- children +
children
} } @@ -57,28 +57,33 @@ let allItems = [ { keywords: ["@bs.module"], name: "@module", - summary: "This is the @module decorator.", + summary: "This is the `@module` decorator.", category: Decorators, component: decorator_module, }, { keywords: ["@bs.as"], name: "@as", - summary: "This is the @as decorator.", + summary: "This is the `@as` decorator.", category: Decorators, component: decorator_as, }, { keywords: ["if", "else", "if else"], name: "if / else", - summary: "This is the if / else control flow structure.", + summary: "This is the `if / else` control flow structure.", category: ControlFlow, component: controlflow_ifelse, }, + { + keywords: ["uncurried"], + name: "(.) => {}", + summary: "This is an `uncurried` function.", + category: Other, + component: controlflow_ifelse, + }, ] -decorator_as->MdxComp.frontmatter->Js.log - let fuseOpts = Fuse.Options.t( ~shouldSort=false, ~includeScore=true, @@ -100,10 +105,96 @@ let getAnchor = path => { } module SearchBox = { + @bs.send external focus: Dom.element => unit = "focus" + + type state = + | Active + | Inactive + @react.component - let make = (~onChange) => { -
- + let make = ( + ~completionValues: array=[], // set of possible values + ~value: string, + ~onClear: unit => unit, + ~onValueChange: string => unit, + ) => { + let (state, setState) = React.useState(_ => Inactive) + let textInput = React.useRef(Js.Nullable.null) + + let onMouseDownClear = evt => { + ReactEvent.Mouse.preventDefault(evt) + onClear() + } + + let focusInput = () => + textInput.current->Js.Nullable.toOption->Belt.Option.forEach(el => el->focus) + + let onAreaFocus = _evt => { + if state === Inactive { + focusInput() + } + } + + let onFocus = _ => { + setState(_ => Active) + } + + let onBlur = _ => { + setState(_ => Inactive) + } + + let onKeyDown = evt => { + let key = ReactEvent.Keyboard.key(evt) + let ctrlKey = ReactEvent.Keyboard.ctrlKey(evt) + + let full = (ctrlKey ? "CTRL+" : "") ++ key + + switch full { + | "Escape" => onClear() + | "Tab" => + if Js.Array.length(completionValues) === 1 { + let targetValue = Belt.Array.getExn(completionValues, 0) + + if targetValue !== value { + ReactEvent.Keyboard.preventDefault(evt) + onValueChange(targetValue) + } else { + () + } + } + | _ => () + } + } + + let onChange = evt => { + ReactEvent.Form.preventDefault(evt) + let value = ReactEvent.Form.target(evt)["value"] + onValueChange(value) + } + +
+ + +
} } @@ -111,7 +202,7 @@ module SearchBox = { module Tag = { @react.component let make = (~text: string) => { - + {React.string(text)} } @@ -119,17 +210,28 @@ module Tag = { module DetailBox = { @react.component - let make = (~summary, ~children) => { + let make = (~summary: string, ~children: React.element) => { + let summaryEl = switch Js.String2.split(summary, "`") { + | [] => React.null + | [first, second, third] => + [ + React.string(first), + {React.string(second)} , + React.string(third), + ]->React.array + | more => Belt.Array.map(more, s => React.string(s))->React.array + } +
-
{React.string(summary)}
-
children
+
summaryEl
+
children
} } type state = | ShowAll - | ShowFiltered(array) + | ShowFiltered(string, array) // (search, filteredItems) | ShowDetails(item) @react.component @@ -176,10 +278,7 @@ let make = () => { None }, [state]) - let onChange = evt => { - ReactEvent.Form.preventDefault(evt) - let value = ReactEvent.Form.target(evt)["value"] - + let onSearchValueChange = value => { setState(_ => switch value { | "" => ShowAll @@ -187,22 +286,23 @@ let make = () => { let filtered = fuse->Fuse.search(search)->Belt.Array.map(m => { m["item"] }) + if Js.Array.length(filtered) === 1 { - ShowDetails(Js.Array2.unsafe_get(filtered, 0)) + let item = Belt.Array.getExn(filtered, 0) + if item.name === value { + ShowDetails(item) + } else { + ShowFiltered(value, filtered) + } } else { - ShowFiltered(filtered) + ShowFiltered(value, filtered) } } ) - /* if value === "" { */ - /* setState(_prev => All) */ - /* } else { */ - /* setState(_prev => Filtered(value)) */ - /* } */ } let details = switch state { - | ShowFiltered(_) + | ShowFiltered(_, _) | ShowAll => React.null | ShowDetails(item) =>
@@ -222,7 +322,7 @@ let make = () => { let items = switch state { | ShowAll => allItems | ShowDetails(_) => [] - | ShowFiltered(items) => items + | ShowFiltered(_, items) => items } Belt.Array.reduce(items, Js.Dict.fromArray(initial), (acc, item) => { @@ -242,24 +342,46 @@ let make = () => { ReactEvent.Mouse.preventDefault(evt) setState(_ => ShowDetails(item)) } - + }) - let el = {React.array(children)} + let el = +
+ {React.array(children)} +
Js.Array2.push(acc, el)->ignore acc } }) } + let (searchValue, completionItems) = switch state { + | ShowFiltered(search, items) => (search, items) + | ShowAll => ("", allItems) + | ShowDetails(item) => (item.name, [item]) + } + + let onSearchClear = () => { + setState(_ => ShowAll) + } +
-
- {React.string("Syntax Lookup")} -
- {React.string("Enter some language construct you want to know more about.")} +
+
+ {React.string("Syntax Lookup")} +
+ {React.string("Enter some language construct you want to know more about.")} +
+
+
+ item.name)} + value=searchValue + onClear=onSearchClear + onValueChange=onSearchValueChange + />
-
{details} {React.array(categories)}
diff --git a/tailwind.config.js b/tailwind.config.js index ce14dc6b5..7dd07cfbd 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -95,7 +95,8 @@ module.exports = { "40": "rgba(230,72,79, 0.4)", "30": "#EDA7AA", "15": "rgba(230, 72, 79, 0.15)", - "10": "#FDE7E8" + "10": "#FDE7E8", + "10-tr": "rgba(230, 72, 79, 0.1)" }, sky: { default: "#376FDD", From 8de27eeba991d2f5c0ca89e1608a3e95419acef0 Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Thu, 19 Nov 2020 18:19:33 +0100 Subject: [PATCH 05/78] Improve text input focus tabbing, fix React key errors --- components/SyntaxLookupWidget.js | 33 +++++++++++++++++++------------ components/SyntaxLookupWidget.res | 28 +++++++++++++++++--------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/components/SyntaxLookupWidget.js b/components/SyntaxLookupWidget.js index 425eb7dec..cf0a5a2a2 100644 --- a/components/SyntaxLookupWidget.js +++ b/components/SyntaxLookupWidget.js @@ -116,8 +116,10 @@ function SyntaxLookupWidget$SearchBox(Props) { evt.preventDefault(); return Curry._1(onClear, undefined); }; - var onAreaFocus = function (_evt) { - if (state === /* Inactive */1) { + var onAreaFocus = function (evt) { + var el = evt.target; + var isDiv = (el.type == null); + if (isDiv && state === /* Inactive */1) { return Belt_Option.forEach(Caml_option.nullable_to_opt(textInput.current), (function (el) { el.focus(); @@ -168,7 +170,8 @@ function SyntaxLookupWidget$SearchBox(Props) { state === /* Active */0 ? "border-fire" : "border-fire-40" ) + " flex items-center border rounded-lg py-4 px-5", tabIndex: -1, - onFocus: onAreaFocus + onFocus: onAreaFocus, + onBlur: onBlur }, React.createElement(Icon.MagnifierGlass.make, { className: ( state === /* Active */0 ? "text-fire" : "text-fire-80" @@ -181,10 +184,10 @@ function SyntaxLookupWidget$SearchBox(Props) { value: value, onKeyDown: onKeyDown, onFocus: onFocus, - onBlur: onBlur, onChange: onChange }), React.createElement("button", { className: value === "" ? "hidden" : "block", + onFocus: onFocus, onMouseDown: onMouseDownClear }, React.createElement(Icon.Close.make, { className: "w-4 h-4 text-fire" @@ -212,13 +215,17 @@ function SyntaxLookupWidget$DetailBox(Props) { var first = more[0]; var second = more[1]; var third = more[2]; - summaryEl = [ - first, - React.createElement("span", { - className: "text-fire" - }, second), - third - ]; + summaryEl = Belt_Array.mapWithIndex([ + first, + React.createElement("span", { + className: "text-fire" + }, second), + third + ], (function (i, el) { + return React.createElement("span", { + key: String(i) + }, el); + })); } return React.createElement("div", undefined, React.createElement("div", { className: "text-21 border-b border-fire-40 pb-4 mb-4 font-semibold" @@ -369,11 +376,11 @@ function SyntaxLookupWidget(Props) { })); })); var el = React.createElement("div", { + key: title, className: "first:mt-0 mt-12" }, React.createElement(SyntaxLookupWidget$Category, { title: title, - children: children, - key: title + children: children })); acc.push(el); return acc; diff --git a/components/SyntaxLookupWidget.res b/components/SyntaxLookupWidget.res index 0cf373a46..d84a32665 100644 --- a/components/SyntaxLookupWidget.res +++ b/components/SyntaxLookupWidget.res @@ -10,8 +10,8 @@ module MdxComp = { ` ) - @bs.get - external frontmatter: t => Js.Json.t = "frontmatter" + /* @bs.get */ + /* external frontmatter: t => Js.Json.t = "frontmatter" */ } @module("misc_docs/syntax/decorator_module.mdx") @@ -106,6 +106,9 @@ let getAnchor = path => { module SearchBox = { @bs.send external focus: Dom.element => unit = "focus" + @bs.send external blur: Dom.element => unit = "blur" + + external toDomElement: Js.t<'a> => Dom.element = "%identity" type state = | Active @@ -129,8 +132,11 @@ module SearchBox = { let focusInput = () => textInput.current->Js.Nullable.toOption->Belt.Option.forEach(el => el->focus) - let onAreaFocus = _evt => { - if state === Inactive { + let onAreaFocus = evt => { + let el = ReactEvent.Focus.target(evt) + let isDiv = Js.Null_undefined.isNullable(el["type"]) + + if isDiv && state === Inactive { focusInput() } } @@ -175,6 +181,7 @@ module SearchBox = {
@@ -185,14 +192,13 @@ module SearchBox = { value ref={ReactDOM.Ref.domRef(textInput)} onFocus - onBlur onKeyDown onChange={onChange} placeholder="Enter keywords or syntax..." className="text-16 outline-none ml-4 w-full" type_="text" /> -
@@ -218,7 +224,11 @@ module DetailBox = { React.string(first), {React.string(second)} , React.string(third), - ]->React.array + ] + ->Belt.Array.mapWithIndex((i, el) => { + el + }) + ->React.array | more => Belt.Array.map(more, s => React.string(s))->React.array } @@ -347,8 +357,8 @@ let make = () => { }) let el = -
- {React.array(children)} +
+ {React.array(children)}
Js.Array2.push(acc, el)->ignore acc From 213668cbbe4de791eb3fe689082e031e07794a10 Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Wed, 30 Dec 2020 18:59:21 +0100 Subject: [PATCH 06/78] Use common SearchBox --- src/Packages.js | 99 +------------- src/Packages.res | 99 -------------- {bindings => src/bindings}/GithubSlugger.js | 0 {bindings => src/bindings}/GithubSlugger.res | 0 src/components/SearchBox.js | 112 +++++++++++++++ src/components/SearchBox.res | 101 ++++++++++++++ .../components}/SyntaxLookupWidget.js | 127 +++--------------- .../components}/SyntaxLookupWidget.res | 102 +------------- .../components}/SyntaxLookupWidget.resi | 0 9 files changed, 233 insertions(+), 407 deletions(-) rename {bindings => src/bindings}/GithubSlugger.js (100%) rename {bindings => src/bindings}/GithubSlugger.res (100%) create mode 100644 src/components/SearchBox.js create mode 100644 src/components/SearchBox.res rename {components => src/components}/SyntaxLookupWidget.js (74%) rename {components => src/components}/SyntaxLookupWidget.res (74%) rename {components => src/components}/SyntaxLookupWidget.resi (100%) diff --git a/src/Packages.js b/src/Packages.js index 38709ae7d..736c3cc99 100644 --- a/src/Packages.js +++ b/src/Packages.js @@ -14,6 +14,7 @@ import * as Js_null from "bs-platform/lib/es6/js_null.js"; import FuseJs from "fuse.js"; import * as Process from "process"; import * as Markdown from "./components/Markdown.js"; +import * as SearchBox from "./components/SearchBox.js"; import * as Belt_Array from "bs-platform/lib/es6/belt_Array.js"; import * as Navigation from "./components/Navigation.js"; import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; @@ -124,102 +125,6 @@ function applySearch(resources, pattern) { return Belt_Array.concat(filteredNpm, filteredUrls); } -function Packages$SearchBox(Props) { - var completionValuesOpt = Props.completionValues; - var value = Props.value; - var onClear = Props.onClear; - var placeholderOpt = Props.placeholder; - var onValueChange = Props.onValueChange; - var completionValues = completionValuesOpt !== undefined ? completionValuesOpt : []; - var placeholder = placeholderOpt !== undefined ? placeholderOpt : ""; - var match = React.useState(function () { - return /* Inactive */1; - }); - var setState = match[1]; - var state = match[0]; - var textInput = React.useRef(null); - var onMouseDownClear = function (evt) { - evt.preventDefault(); - return Curry._1(onClear, undefined); - }; - var onAreaFocus = function (evt) { - var el = evt.target; - var isDiv = (el.type == null); - if (isDiv && state === /* Inactive */1) { - return Belt_Option.forEach(Caml_option.nullable_to_opt(textInput.current), (function (el) { - el.focus(); - - })); - } - - }; - var onFocus = function (param) { - return Curry._1(setState, (function (param) { - return /* Active */0; - })); - }; - var onBlur = function (param) { - return Curry._1(setState, (function (param) { - return /* Inactive */1; - })); - }; - var onKeyDown = function (evt) { - var key = evt.key; - var ctrlKey = evt.ctrlKey; - var full = ( - ctrlKey ? "CTRL+" : "" - ) + key; - switch (full) { - case "Escape" : - return Curry._1(onClear, undefined); - case "Tab" : - if (completionValues.length !== 1) { - return ; - } - var targetValue = Belt_Array.getExn(completionValues, 0); - if (targetValue !== value) { - evt.preventDefault(); - return Curry._1(onValueChange, targetValue); - } else { - return ; - } - default: - return ; - } - }; - var onChange = function (evt) { - evt.preventDefault(); - return Curry._1(onValueChange, evt.target.value); - }; - return React.createElement("div", { - className: ( - state === /* Active */0 ? "border-fire" : "border-fire-40" - ) + " flex items-center border rounded-lg py-4 px-5", - tabIndex: -1, - onFocus: onAreaFocus, - onBlur: onBlur - }, React.createElement(Icon.MagnifierGlass.make, { - className: ( - state === /* Active */0 ? "text-fire" : "text-fire-80" - ) + " w-4 h-4" - }), React.createElement("input", { - ref: textInput, - className: "text-16 outline-none ml-4 w-full", - placeholder: placeholder, - type: "text", - value: value, - onKeyDown: onKeyDown, - onFocus: onFocus, - onChange: onChange - }), React.createElement("button", { - className: value === "" ? "hidden" : "block", - onFocus: onFocus, - onMouseDown: onMouseDownClear - }, React.createElement(Icon.Close.make, { - className: "w-4 h-4 text-fire" - }))); -} - function Packages$Card(Props) { var value = Props.value; var onKeywordSelect = Props.onKeywordSelect; @@ -580,7 +485,7 @@ function $$default(props) { } }, React.createElement(Markdown.H1.make, { children: "Libraries & Bindings" - }), React.createElement(Packages$SearchBox, { + }), React.createElement(SearchBox.make, { value: searchValue, onClear: onClear, placeholder: "Enter a search term, name, keyword, etc", diff --git a/src/Packages.res b/src/Packages.res index 84a1288df..22102751f 100644 --- a/src/Packages.res +++ b/src/Packages.res @@ -123,105 +123,6 @@ module Resource = { } } -module SearchBox = { - @bs.send external focus: Dom.element => unit = "focus" - - type state = - | Active - | Inactive - - @react.component - let make = ( - ~completionValues: array=[], // set of possible values - ~value: string, - ~onClear: unit => unit, - ~placeholder: string="", - ~onValueChange: string => unit, - ) => { - let (state, setState) = React.useState(_ => Inactive) - let textInput = React.useRef(Js.Nullable.null) - - let onMouseDownClear = evt => { - ReactEvent.Mouse.preventDefault(evt) - onClear() - } - - let focusInput = () => - textInput.current->Js.Nullable.toOption->Belt.Option.forEach(el => el->focus) - - let onAreaFocus = evt => { - let el = ReactEvent.Focus.target(evt) - let isDiv = Js.Null_undefined.isNullable(el["type"]) - - if isDiv && state === Inactive { - focusInput() - } - } - - let onFocus = _ => { - setState(_ => Active) - } - - let onBlur = _ => { - setState(_ => Inactive) - } - - let onKeyDown = evt => { - let key = ReactEvent.Keyboard.key(evt) - let ctrlKey = ReactEvent.Keyboard.ctrlKey(evt) - - let full = (ctrlKey ? "CTRL+" : "") ++ key - - switch full { - | "Escape" => onClear() - | "Tab" => - if Js.Array.length(completionValues) === 1 { - let targetValue = Belt.Array.getExn(completionValues, 0) - - if targetValue !== value { - ReactEvent.Keyboard.preventDefault(evt) - onValueChange(targetValue) - } else { - () - } - } - | _ => () - } - } - - let onChange = evt => { - ReactEvent.Form.preventDefault(evt) - let value = ReactEvent.Form.target(evt)["value"] - onValueChange(value) - } - -
- - - -
- } -} - module Card = { @react.component let make = (~value: Resource.t, ~onKeywordSelect: option unit>=?) => { diff --git a/bindings/GithubSlugger.js b/src/bindings/GithubSlugger.js similarity index 100% rename from bindings/GithubSlugger.js rename to src/bindings/GithubSlugger.js diff --git a/bindings/GithubSlugger.res b/src/bindings/GithubSlugger.res similarity index 100% rename from bindings/GithubSlugger.res rename to src/bindings/GithubSlugger.res diff --git a/src/components/SearchBox.js b/src/components/SearchBox.js new file mode 100644 index 000000000..1a82b11fd --- /dev/null +++ b/src/components/SearchBox.js @@ -0,0 +1,112 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Icon from "./Icon.js"; +import * as Curry from "bs-platform/lib/es6/curry.js"; +import * as React from "react"; +import * as Belt_Array from "bs-platform/lib/es6/belt_Array.js"; +import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; +import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; + +function SearchBox(Props) { + var completionValuesOpt = Props.completionValues; + var value = Props.value; + var onClear = Props.onClear; + var placeholderOpt = Props.placeholder; + var onValueChange = Props.onValueChange; + var completionValues = completionValuesOpt !== undefined ? completionValuesOpt : []; + var placeholder = placeholderOpt !== undefined ? placeholderOpt : ""; + var match = React.useState(function () { + return /* Inactive */1; + }); + var setState = match[1]; + var state = match[0]; + var textInput = React.useRef(null); + var onMouseDownClear = function (evt) { + evt.preventDefault(); + return Curry._1(onClear, undefined); + }; + var onAreaFocus = function (evt) { + var el = evt.target; + var isDiv = (el.type == null); + if (isDiv && state === /* Inactive */1) { + return Belt_Option.forEach(Caml_option.nullable_to_opt(textInput.current), (function (el) { + el.focus(); + + })); + } + + }; + var onFocus = function (param) { + return Curry._1(setState, (function (param) { + return /* Active */0; + })); + }; + var onBlur = function (param) { + return Curry._1(setState, (function (param) { + return /* Inactive */1; + })); + }; + var onKeyDown = function (evt) { + var key = evt.key; + var ctrlKey = evt.ctrlKey; + var full = ( + ctrlKey ? "CTRL+" : "" + ) + key; + switch (full) { + case "Escape" : + return Curry._1(onClear, undefined); + case "Tab" : + if (completionValues.length !== 1) { + return ; + } + var targetValue = Belt_Array.getExn(completionValues, 0); + if (targetValue !== value) { + evt.preventDefault(); + return Curry._1(onValueChange, targetValue); + } else { + return ; + } + default: + return ; + } + }; + var onChange = function (evt) { + evt.preventDefault(); + return Curry._1(onValueChange, evt.target.value); + }; + return React.createElement("div", { + className: ( + state === /* Active */0 ? "border-fire" : "border-fire-40" + ) + " flex items-center border rounded-lg py-4 px-5", + tabIndex: -1, + onFocus: onAreaFocus, + onBlur: onBlur + }, React.createElement(Icon.MagnifierGlass.make, { + className: ( + state === /* Active */0 ? "text-fire" : "text-fire-80" + ) + " w-4 h-4" + }), React.createElement("input", { + ref: textInput, + className: "text-16 outline-none ml-4 w-full", + placeholder: placeholder, + type: "text", + value: value, + onKeyDown: onKeyDown, + onFocus: onFocus, + onChange: onChange + }), React.createElement("button", { + className: value === "" ? "hidden" : "block", + onFocus: onFocus, + onMouseDown: onMouseDownClear + }, React.createElement(Icon.Close.make, { + className: "w-4 h-4 text-fire" + }))); +} + +var make = SearchBox; + +export { + make , + +} +/* Icon Not a pure module */ diff --git a/src/components/SearchBox.res b/src/components/SearchBox.res new file mode 100644 index 000000000..8cd14de7e --- /dev/null +++ b/src/components/SearchBox.res @@ -0,0 +1,101 @@ +/* +* This SearchBox is used for fuzzy-find search scenarios, such as the syntax widget tool or +* the package index +*/ + +@bs.send external focus: Dom.element => unit = "focus" + +type state = + | Active + | Inactive + +@react.component +let make = ( + ~completionValues: array=[], // set of possible values + ~value: string, + ~onClear: unit => unit, + ~placeholder: string="", + ~onValueChange: string => unit, +) => { + let (state, setState) = React.useState(_ => Inactive) + let textInput = React.useRef(Js.Nullable.null) + + let onMouseDownClear = evt => { + ReactEvent.Mouse.preventDefault(evt) + onClear() + } + + let focusInput = () => + textInput.current->Js.Nullable.toOption->Belt.Option.forEach(el => el->focus) + + let onAreaFocus = evt => { + let el = ReactEvent.Focus.target(evt) + let isDiv = Js.Null_undefined.isNullable(el["type"]) + + if isDiv && state === Inactive { + focusInput() + } + } + + let onFocus = _ => { + setState(_ => Active) + } + + let onBlur = _ => { + setState(_ => Inactive) + } + + let onKeyDown = evt => { + let key = ReactEvent.Keyboard.key(evt) + let ctrlKey = ReactEvent.Keyboard.ctrlKey(evt) + + let full = (ctrlKey ? "CTRL+" : "") ++ key + + switch full { + | "Escape" => onClear() + | "Tab" => + if Js.Array.length(completionValues) === 1 { + let targetValue = Belt.Array.getExn(completionValues, 0) + + if targetValue !== value { + ReactEvent.Keyboard.preventDefault(evt) + onValueChange(targetValue) + } else { + () + } + } + | _ => () + } + } + + let onChange = evt => { + ReactEvent.Form.preventDefault(evt) + let value = ReactEvent.Form.target(evt)["value"] + onValueChange(value) + } + +
+ + + +
+} diff --git a/components/SyntaxLookupWidget.js b/src/components/SyntaxLookupWidget.js similarity index 74% rename from components/SyntaxLookupWidget.js rename to src/components/SyntaxLookupWidget.js index cf0a5a2a2..fa133291b 100644 --- a/components/SyntaxLookupWidget.js +++ b/src/components/SyntaxLookupWidget.js @@ -1,15 +1,15 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as Icon from "./Icon.js"; +import * as Next from "../bindings/Next.js"; import * as Curry from "bs-platform/lib/es6/curry.js"; import * as React from "react"; import * as Js_dict from "bs-platform/lib/es6/js_dict.js"; import FuseJs from "fuse.js"; import * as Markdown from "./Markdown.js"; +import * as SearchBox from "./SearchBox.js"; import * as Belt_Array from "bs-platform/lib/es6/belt_Array.js"; import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; -import * as Router from "next/router"; import * as GithubSlugger from "github-slugger"; import Decorator_asMdx from "misc_docs/syntax/decorator_as.mdx"; import Decorator_moduleMdx from "misc_docs/syntax/decorator_module.mdx"; @@ -100,100 +100,6 @@ function getAnchor(path) { } } -function SyntaxLookupWidget$SearchBox(Props) { - var completionValuesOpt = Props.completionValues; - var value = Props.value; - var onClear = Props.onClear; - var onValueChange = Props.onValueChange; - var completionValues = completionValuesOpt !== undefined ? completionValuesOpt : []; - var match = React.useState(function () { - return /* Inactive */1; - }); - var setState = match[1]; - var state = match[0]; - var textInput = React.useRef(null); - var onMouseDownClear = function (evt) { - evt.preventDefault(); - return Curry._1(onClear, undefined); - }; - var onAreaFocus = function (evt) { - var el = evt.target; - var isDiv = (el.type == null); - if (isDiv && state === /* Inactive */1) { - return Belt_Option.forEach(Caml_option.nullable_to_opt(textInput.current), (function (el) { - el.focus(); - - })); - } - - }; - var onFocus = function (param) { - return Curry._1(setState, (function (param) { - return /* Active */0; - })); - }; - var onBlur = function (param) { - return Curry._1(setState, (function (param) { - return /* Inactive */1; - })); - }; - var onKeyDown = function (evt) { - var key = evt.key; - var ctrlKey = evt.ctrlKey; - var full = ( - ctrlKey ? "CTRL+" : "" - ) + key; - switch (full) { - case "Escape" : - return Curry._1(onClear, undefined); - case "Tab" : - if (completionValues.length !== 1) { - return ; - } - var targetValue = Belt_Array.getExn(completionValues, 0); - if (targetValue !== value) { - evt.preventDefault(); - return Curry._1(onValueChange, targetValue); - } else { - return ; - } - default: - return ; - } - }; - var onChange = function (evt) { - evt.preventDefault(); - return Curry._1(onValueChange, evt.target.value); - }; - return React.createElement("div", { - className: ( - state === /* Active */0 ? "border-fire" : "border-fire-40" - ) + " flex items-center border rounded-lg py-4 px-5", - tabIndex: -1, - onFocus: onAreaFocus, - onBlur: onBlur - }, React.createElement(Icon.MagnifierGlass.make, { - className: ( - state === /* Active */0 ? "text-fire" : "text-fire-80" - ) + " w-4 h-4" - }), React.createElement("input", { - ref: textInput, - className: "text-16 outline-none ml-4 w-full", - placeholder: "Enter keywords or syntax...", - type: "text", - value: value, - onKeyDown: onKeyDown, - onFocus: onFocus, - onChange: onChange - }), React.createElement("button", { - className: value === "" ? "hidden" : "block", - onFocus: onFocus, - onMouseDown: onMouseDownClear - }, React.createElement(Icon.Close.make, { - className: "w-4 h-4 text-fire" - }))); -} - function SyntaxLookupWidget$Tag(Props) { var text = Props.text; return React.createElement("span", { @@ -235,7 +141,7 @@ function SyntaxLookupWidget$DetailBox(Props) { } function SyntaxLookupWidget(Props) { - var router = Router.useRouter(); + var router = Next.Router.useRouter(undefined); var match = React.useState(function () { return /* ShowAll */0; }); @@ -261,23 +167,23 @@ function SyntaxLookupWidget(Props) { React.useEffect((function () { var match = getAnchor(router.asPath); var exit = 0; - if (typeof state === "number" || !state.TAG) { + if (typeof state === "number" || state.TAG === /* ShowFiltered */0) { exit = 1; } else { var item = state._0; if (match !== undefined) { var slug = GithubSlugger.slug(item.name); if (slug !== match) { - router.replace("syntax-lookup#" + match); + Next.Router.replace(router, "syntax-lookup#" + match); } } else { - router.replace("syntax-lookup#" + GithubSlugger.slug(item.name)); + Next.Router.replace(router, "syntax-lookup#" + GithubSlugger.slug(item.name)); } } if (exit === 1) { if (match !== undefined) { - router.replace("syntax-lookup"); + Next.Router.replace(router, "syntax-lookup"); } } @@ -317,7 +223,7 @@ function SyntaxLookupWidget(Props) { })); }; var details; - if (typeof state === "number" || !state.TAG) { + if (typeof state === "number" || state.TAG === /* ShowFiltered */0) { details = null; } else { var item = state._0; @@ -341,7 +247,7 @@ function SyntaxLookupWidget(Props) { })); var items; items = typeof state === "number" ? allItems : ( - state.TAG ? [] : state._1 + state.TAG === /* ShowFiltered */0 ? state._1 : [] ); var categories = Belt_Array.reduce(Js_dict.entries(Belt_Array.reduce(items, Js_dict.fromArray(initial), (function (acc, item) { var key = toString(item.category); @@ -391,16 +297,16 @@ function SyntaxLookupWidget(Props) { "", allItems ]; - } else if (state.TAG) { - var item$1 = state._0; + } else if (state.TAG === /* ShowFiltered */0) { match$1 = [ - item$1.name, - [item$1] + state._0, + state._1 ]; } else { + var item$1 = state._0; match$1 = [ - state._0, - state._1 + item$1.name, + [item$1] ]; } var onSearchClear = function (param) { @@ -424,12 +330,13 @@ function SyntaxLookupWidget(Props) { style: { maxWidth: "34rem" } - }, React.createElement(SyntaxLookupWidget$SearchBox, { + }, React.createElement(SearchBox.make, { completionValues: Belt_Array.map(match$1[1], (function (item) { return item.name; })), value: match$1[0], onClear: onSearchClear, + placeholder: "Enter keywords or syntax...", onValueChange: onSearchValueChange }))), React.createElement("div", { className: "mt-10" diff --git a/components/SyntaxLookupWidget.res b/src/components/SyntaxLookupWidget.res similarity index 74% rename from components/SyntaxLookupWidget.res rename to src/components/SyntaxLookupWidget.res index d84a32665..1fc094f95 100644 --- a/components/SyntaxLookupWidget.res +++ b/src/components/SyntaxLookupWidget.res @@ -104,107 +104,6 @@ let getAnchor = path => { } } -module SearchBox = { - @bs.send external focus: Dom.element => unit = "focus" - @bs.send external blur: Dom.element => unit = "blur" - - external toDomElement: Js.t<'a> => Dom.element = "%identity" - - type state = - | Active - | Inactive - - @react.component - let make = ( - ~completionValues: array=[], // set of possible values - ~value: string, - ~onClear: unit => unit, - ~onValueChange: string => unit, - ) => { - let (state, setState) = React.useState(_ => Inactive) - let textInput = React.useRef(Js.Nullable.null) - - let onMouseDownClear = evt => { - ReactEvent.Mouse.preventDefault(evt) - onClear() - } - - let focusInput = () => - textInput.current->Js.Nullable.toOption->Belt.Option.forEach(el => el->focus) - - let onAreaFocus = evt => { - let el = ReactEvent.Focus.target(evt) - let isDiv = Js.Null_undefined.isNullable(el["type"]) - - if isDiv && state === Inactive { - focusInput() - } - } - - let onFocus = _ => { - setState(_ => Active) - } - - let onBlur = _ => { - setState(_ => Inactive) - } - - let onKeyDown = evt => { - let key = ReactEvent.Keyboard.key(evt) - let ctrlKey = ReactEvent.Keyboard.ctrlKey(evt) - - let full = (ctrlKey ? "CTRL+" : "") ++ key - - switch full { - | "Escape" => onClear() - | "Tab" => - if Js.Array.length(completionValues) === 1 { - let targetValue = Belt.Array.getExn(completionValues, 0) - - if targetValue !== value { - ReactEvent.Keyboard.preventDefault(evt) - onValueChange(targetValue) - } else { - () - } - } - | _ => () - } - } - - let onChange = evt => { - ReactEvent.Form.preventDefault(evt) - let value = ReactEvent.Form.target(evt)["value"] - onValueChange(value) - } - -
- - - -
- } -} - module Tag = { @react.component let make = (~text: string) => { @@ -386,6 +285,7 @@ let make = () => {
item.name)} value=searchValue onClear=onSearchClear diff --git a/components/SyntaxLookupWidget.resi b/src/components/SyntaxLookupWidget.resi similarity index 100% rename from components/SyntaxLookupWidget.resi rename to src/components/SyntaxLookupWidget.resi From 7a04b3cae78274cd5e218d807ef6d1ba9671cc77 Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Sat, 2 Jan 2021 12:44:24 +0100 Subject: [PATCH 07/78] Fix import --- pages/syntax-lookup.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/syntax-lookup.mdx b/pages/syntax-lookup.mdx index ed8363b85..a132ee277 100644 --- a/pages/syntax-lookup.mdx +++ b/pages/syntax-lookup.mdx @@ -4,6 +4,6 @@ description: "Discover ReScript syntax constructs with our discovery tool" canonical: "/docs/manual/latest/syntax-discovery" --- -import { make as SyntaxLookupWidget } from "components/SyntaxLookupWidget" +import { make as SyntaxLookupWidget } from "src/components/SyntaxLookupWidget" From 0a7d303c5d91c5b87e2d79c1c30bc1f8cf8faa5e Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sun, 3 Jan 2021 13:02:12 +1100 Subject: [PATCH 08/78] Add item.id to use as syntax lookup widget slug --- src/components/SyntaxLookupWidget.js | 10 +++++++--- src/components/SyntaxLookupWidget.res | 11 ++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/components/SyntaxLookupWidget.js b/src/components/SyntaxLookupWidget.js index fa133291b..8ed53cbaf 100644 --- a/src/components/SyntaxLookupWidget.js +++ b/src/components/SyntaxLookupWidget.js @@ -43,6 +43,7 @@ function SyntaxLookupWidget$Category(Props) { var allItems = [ { + id: "module-decorator", keywords: ["@bs.module"], name: "@module", summary: "This is the `@module` decorator.", @@ -50,6 +51,7 @@ var allItems = [ component: Decorator_moduleMdx }, { + id: "as-decorator", keywords: ["@bs.as"], name: "@as", summary: "This is the `@as` decorator.", @@ -57,6 +59,7 @@ var allItems = [ component: Decorator_asMdx }, { + id: "if-else", keywords: [ "if", "else", @@ -68,6 +71,7 @@ var allItems = [ component: Controlflow_ifelseMdx }, { + id: "uncurried-function", keywords: ["uncurried"], name: "(.) => {}", summary: "This is an `uncurried` function.", @@ -151,7 +155,7 @@ function SyntaxLookupWidget(Props) { var anchor = getAnchor(router.asPath); if (anchor !== undefined) { Belt_Option.forEach(Caml_option.undefined_to_opt(allItems.find(function (item) { - return GithubSlugger.slug(item.name) === anchor; + return GithubSlugger.slug(item.id) === anchor; })), (function (item) { return Curry._1(setState, (function (param) { return { @@ -172,13 +176,13 @@ function SyntaxLookupWidget(Props) { } else { var item = state._0; if (match !== undefined) { - var slug = GithubSlugger.slug(item.name); + var slug = GithubSlugger.slug(item.id); if (slug !== match) { Next.Router.replace(router, "syntax-lookup#" + match); } } else { - Next.Router.replace(router, "syntax-lookup#" + GithubSlugger.slug(item.name)); + Next.Router.replace(router, "syntax-lookup#" + GithubSlugger.slug(item.id)); } } if (exit === 1) { diff --git a/src/components/SyntaxLookupWidget.res b/src/components/SyntaxLookupWidget.res index 1fc094f95..a884ebd9c 100644 --- a/src/components/SyntaxLookupWidget.res +++ b/src/components/SyntaxLookupWidget.res @@ -46,6 +46,7 @@ module Category = { } type item = { + id: string, keywords: array, name: string, summary: string, @@ -55,6 +56,7 @@ type item = { let allItems = [ { + id: "module-decorator", keywords: ["@bs.module"], name: "@module", summary: "This is the `@module` decorator.", @@ -62,6 +64,7 @@ let allItems = [ component: decorator_module, }, { + id: "as-decorator", keywords: ["@bs.as"], name: "@as", summary: "This is the `@as` decorator.", @@ -69,6 +72,7 @@ let allItems = [ component: decorator_as, }, { + id: "if-else", keywords: ["if", "else", "if else"], name: "if / else", summary: "This is the `if / else` control flow structure.", @@ -76,6 +80,7 @@ let allItems = [ component: controlflow_ifelse, }, { + id: "uncurried-function", keywords: ["uncurried"], name: "(.) => {}", summary: "This is an `uncurried` function.", @@ -152,7 +157,7 @@ let make = () => { switch getAnchor(router.asPath) { | Some(anchor) => Js.Array2.find(allItems, item => - GithubSlugger.slug(item.name) === anchor + GithubSlugger.slug(item.id) === anchor )->Belt.Option.forEach(item => { setState(_ => ShowDetails(item)) }) @@ -172,7 +177,7 @@ let make = () => { React.useEffect1(() => { switch (state, getAnchor(router.asPath)) { | (ShowDetails(item), Some(anchor)) => - let slug = GithubSlugger.slug(item.name) + let slug = GithubSlugger.slug(item.id) if slug !== anchor { router->Next.Router.replace("syntax-lookup#" ++ anchor) @@ -180,7 +185,7 @@ let make = () => { () } | (ShowDetails(item), None) => - router->Next.Router.replace("syntax-lookup#" ++ GithubSlugger.slug(item.name)) + router->Next.Router.replace("syntax-lookup#" ++ GithubSlugger.slug(item.id)) | (_, Some(_)) => router->Next.Router.replace("syntax-lookup") | _ => () } From 0c52467f3ffb6be5df1b8344d4506b7b42753ed6 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Mon, 4 Jan 2021 12:05:05 +1100 Subject: [PATCH 09/78] Add basic operators to the syntax widget --- misc_docs/syntax/operators_float_addition.mdx | 19 +++ misc_docs/syntax/operators_float_division.mdx | 19 +++ .../syntax/operators_float_multiplication.mdx | 19 +++ .../syntax/operators_float_subtraction.mdx | 19 +++ .../syntax/operators_integer_addition.mdx | 21 +++ .../syntax/operators_integer_division.mdx | 21 +++ .../operators_integer_multiplication.mdx | 19 +++ .../syntax/operators_integer_subtraction.mdx | 19 +++ .../syntax/operators_string_concatenation.mdx | 19 +++ src/components/SyntaxLookupWidget.js | 128 ++++++++++++++++++ src/components/SyntaxLookupWidget.res | 99 ++++++++++++++ 11 files changed, 402 insertions(+) create mode 100644 misc_docs/syntax/operators_float_addition.mdx create mode 100644 misc_docs/syntax/operators_float_division.mdx create mode 100644 misc_docs/syntax/operators_float_multiplication.mdx create mode 100644 misc_docs/syntax/operators_float_subtraction.mdx create mode 100644 misc_docs/syntax/operators_integer_addition.mdx create mode 100644 misc_docs/syntax/operators_integer_division.mdx create mode 100644 misc_docs/syntax/operators_integer_multiplication.mdx create mode 100644 misc_docs/syntax/operators_integer_subtraction.mdx create mode 100644 misc_docs/syntax/operators_string_concatenation.mdx diff --git a/misc_docs/syntax/operators_float_addition.mdx b/misc_docs/syntax/operators_float_addition.mdx new file mode 100644 index 000000000..0aff15095 --- /dev/null +++ b/misc_docs/syntax/operators_float_addition.mdx @@ -0,0 +1,19 @@ +--- +test: "foo" +--- + +This operator performs *floating point* addition. + + + +```res +let result = 1.3 +. 0.5 +``` + +```js +var result = 1.3 + 0.5; +``` + + + +For adding *integers* see the `+` operator. diff --git a/misc_docs/syntax/operators_float_division.mdx b/misc_docs/syntax/operators_float_division.mdx new file mode 100644 index 000000000..47d1c5d99 --- /dev/null +++ b/misc_docs/syntax/operators_float_division.mdx @@ -0,0 +1,19 @@ +--- +test: "foo" +--- + +This operator performs *floating point* division. + + + +```res +let result = 3.0 /. 2.5 +``` + +```js +var result = 3.0 / 2.5; +``` + + + +For dividing *integers* see the `/` operator. diff --git a/misc_docs/syntax/operators_float_multiplication.mdx b/misc_docs/syntax/operators_float_multiplication.mdx new file mode 100644 index 000000000..41a4da46c --- /dev/null +++ b/misc_docs/syntax/operators_float_multiplication.mdx @@ -0,0 +1,19 @@ +--- +test: "foo" +--- + +This operator performs *floating point* multiplication. + + + +```res +let result = 1.5 *. 2.3 +``` + +```js +var result = 1.5 * 2.3; +``` + + + +For multiplying *integers* see the `*` operator. diff --git a/misc_docs/syntax/operators_float_subtraction.mdx b/misc_docs/syntax/operators_float_subtraction.mdx new file mode 100644 index 000000000..7577712ff --- /dev/null +++ b/misc_docs/syntax/operators_float_subtraction.mdx @@ -0,0 +1,19 @@ +--- +test: "foo" +--- + +This operator performs *floating point* subtraction. + + + +```res +let result = 3.0 -. 2.5 +``` + +```js +var result = 3.0 - 2.5; +``` + + + +For subtracting *integers* see the `-` operator. diff --git a/misc_docs/syntax/operators_integer_addition.mdx b/misc_docs/syntax/operators_integer_addition.mdx new file mode 100644 index 000000000..657efb427 --- /dev/null +++ b/misc_docs/syntax/operators_integer_addition.mdx @@ -0,0 +1,21 @@ +--- +test: "foo" +--- + +This operator performs *integers* addition. + + + +```res +let result = 1 + 2 +``` + +```js +val result = 3; +``` + + + +For adding *floats* see the `+.` operator. + +For contatenating *strings* see the `++` operator. diff --git a/misc_docs/syntax/operators_integer_division.mdx b/misc_docs/syntax/operators_integer_division.mdx new file mode 100644 index 000000000..afacaa9f7 --- /dev/null +++ b/misc_docs/syntax/operators_integer_division.mdx @@ -0,0 +1,21 @@ +--- +test: "foo" +--- + +This operator performs *integer* division, with the result truncated to an integer value. + +If the second argument is *zero* then a `Division_by_zero` exception is thrown. Refer to the [Exception](/docs/manual/latest/exception) section for handling exceptions. + + + +```res +let result = 3 / 2 +``` + +```js +var result = 1; +``` + + + +For dividing *floats* see the `/.` operator. diff --git a/misc_docs/syntax/operators_integer_multiplication.mdx b/misc_docs/syntax/operators_integer_multiplication.mdx new file mode 100644 index 000000000..dd98c1941 --- /dev/null +++ b/misc_docs/syntax/operators_integer_multiplication.mdx @@ -0,0 +1,19 @@ +--- +test: "foo" +--- + +This operator performs *integer* multiplication. + + + +```res +let result = 2 * 3 +``` + +```js +var result = 6; +``` + + + +For multiplying *floats* see the `*.` operator. diff --git a/misc_docs/syntax/operators_integer_subtraction.mdx b/misc_docs/syntax/operators_integer_subtraction.mdx new file mode 100644 index 000000000..2f1fca644 --- /dev/null +++ b/misc_docs/syntax/operators_integer_subtraction.mdx @@ -0,0 +1,19 @@ +--- +test: "foo" +--- + +This operator performs *integer* subtraction. + + + +```res +let result = 3 - 2 +``` + +```js +var result = 1; +``` + + + +For subtracting *floats* see the `-.` operator. diff --git a/misc_docs/syntax/operators_string_concatenation.mdx b/misc_docs/syntax/operators_string_concatenation.mdx new file mode 100644 index 000000000..c73c70379 --- /dev/null +++ b/misc_docs/syntax/operators_string_concatenation.mdx @@ -0,0 +1,19 @@ +--- +test: "foo" +--- + +This operator concatenates two *strings* together. + + + +```res +let greetings = "Hello " ++ "world!" +``` + +```js +var greetings = "Hello world!"; +``` + + + + diff --git a/src/components/SyntaxLookupWidget.js b/src/components/SyntaxLookupWidget.js index 8ed53cbaf..c7e13ef05 100644 --- a/src/components/SyntaxLookupWidget.js +++ b/src/components/SyntaxLookupWidget.js @@ -14,6 +14,15 @@ import * as GithubSlugger from "github-slugger"; import Decorator_asMdx from "misc_docs/syntax/decorator_as.mdx"; import Decorator_moduleMdx from "misc_docs/syntax/decorator_module.mdx"; import Controlflow_ifelseMdx from "misc_docs/syntax/controlflow_ifelse.mdx"; +import Operators_float_additionMdx from "misc_docs/syntax/operators_float_addition.mdx"; +import Operators_float_divisionMdx from "misc_docs/syntax/operators_float_division.mdx"; +import Operators_integer_additionMdx from "misc_docs/syntax/operators_integer_addition.mdx"; +import Operators_integer_divisionMdx from "misc_docs/syntax/operators_integer_division.mdx"; +import Operators_float_subtractionMdx from "misc_docs/syntax/operators_float_subtraction.mdx"; +import Operators_integer_subtractionMdx from "misc_docs/syntax/operators_integer_subtraction.mdx"; +import Operators_float_multiplicationMdx from "misc_docs/syntax/operators_float_multiplication.mdx"; +import Operators_string_concatenationMdx from "misc_docs/syntax/operators_string_concatenation.mdx"; +import Operators_integer_multiplicationMdx from "misc_docs/syntax/operators_integer_multiplication.mdx"; var render = (function(c) { return React.createElement(c, {}); @@ -77,6 +86,125 @@ var allItems = [ summary: "This is an `uncurried` function.", category: /* Other */3, component: Controlflow_ifelseMdx + }, + { + id: "integer-addition", + keywords: [ + "plus", + "add", + "addition", + "sum", + "int", + "integer" + ], + name: "+", + summary: "This is the `integer addition` operator.", + category: /* Operators */2, + component: Operators_integer_additionMdx + }, + { + id: "integer-subtraction", + keywords: [ + "subtract", + "minus", + "subtraction", + "int", + "integer" + ], + name: "-", + summary: "This is the `integer subtraction` operator.", + category: /* Operators */2, + component: Operators_integer_subtractionMdx + }, + { + id: "integer-multiplication", + keywords: [ + "multiply", + "multiplication", + "int", + "integer" + ], + name: "*", + summary: "This is the `integer multiplication` operator.", + category: /* Operators */2, + component: Operators_integer_multiplicationMdx + }, + { + id: "integer-division", + keywords: [ + "divide", + "division", + "int", + "integer" + ], + name: "/", + summary: "This is the `integer division` operator.", + category: /* Operators */2, + component: Operators_integer_divisionMdx + }, + { + id: "float-addition", + keywords: [ + "plus", + "add", + "addition", + "sum", + "float" + ], + name: "+.", + summary: "This is the `floating point addition` operator.", + category: /* Operators */2, + component: Operators_float_additionMdx + }, + { + id: "float-subtraction", + keywords: [ + "subtract", + "minus", + "subtraction", + "float" + ], + name: "-.", + summary: "This is the `floating point subtraction` operator.", + category: /* Operators */2, + component: Operators_float_subtractionMdx + }, + { + id: "float-multiplication", + keywords: [ + "multiply", + "multiplication", + "float" + ], + name: "*.", + summary: "This is the `floating point multiplication` operator.", + category: /* Operators */2, + component: Operators_float_multiplicationMdx + }, + { + id: "float-division", + keywords: [ + "divide", + "division", + "float" + ], + name: "/.", + summary: "This is the `floating point division` operator.", + category: /* Operators */2, + component: Operators_float_divisionMdx + }, + { + id: "string-concatenation", + keywords: [ + "concat", + "concatenation", + "add", + "string" + ], + name: "++", + summary: "This is the `string concatenation` operator.", + category: /* Operators */2, + component: Operators_string_concatenationMdx } ]; diff --git a/src/components/SyntaxLookupWidget.res b/src/components/SyntaxLookupWidget.res index a884ebd9c..017110e1f 100644 --- a/src/components/SyntaxLookupWidget.res +++ b/src/components/SyntaxLookupWidget.res @@ -23,6 +23,33 @@ external decorator_as: MdxComp.t = "default" @module("misc_docs/syntax/controlflow_ifelse.mdx") external controlflow_ifelse: MdxComp.t = "default" +@module("misc_docs/syntax/operators_integer_addition.mdx") +external operators_integer_addition: MdxComp.t = "default" + +@module("misc_docs/syntax/operators_integer_subtraction.mdx") +external operators_integer_subtraction: MdxComp.t = "default" + +@module("misc_docs/syntax/operators_integer_multiplication.mdx") +external operators_integer_multiplication: MdxComp.t = "default" + +@module("misc_docs/syntax/operators_integer_division.mdx") +external operators_integer_division: MdxComp.t = "default" + +@module("misc_docs/syntax/operators_float_addition.mdx") +external operators_float_addition: MdxComp.t = "default" + +@module("misc_docs/syntax/operators_float_subtraction.mdx") +external operators_float_subtraction: MdxComp.t = "default" + +@module("misc_docs/syntax/operators_float_multiplication.mdx") +external operators_float_multiplication: MdxComp.t = "default" + +@module("misc_docs/syntax/operators_float_division.mdx") +external operators_float_division: MdxComp.t = "default" + +@module("misc_docs/syntax/operators_string_concatenation.mdx") +external operators_string_concatenation: MdxComp.t = "default" + module Category = { type t = Decorators | ControlFlow | Operators | Other @@ -87,6 +114,78 @@ let allItems = [ category: Other, component: controlflow_ifelse, }, + { + id: "integer-addition", + keywords: ["plus", "add", "addition", "sum", "int", "integer"], + name: "+", + summary: "This is the `integer addition` operator.", + category: Operators, + component: operators_integer_addition, + }, + { + id: "integer-subtraction", + keywords: ["subtract", "minus", "subtraction", "int", "integer"], + name: "-", + summary: "This is the `integer subtraction` operator.", + category: Operators, + component: operators_integer_subtraction, + }, + { + id: "integer-multiplication", + keywords: ["multiply", "multiplication", "int", "integer"], + name: "*", + summary: "This is the `integer multiplication` operator.", + category: Operators, + component: operators_integer_multiplication, + }, + { + id: "integer-division", + keywords: ["divide", "division", "int", "integer"], + name: "/", + summary: "This is the `integer division` operator.", + category: Operators, + component: operators_integer_division, + }, + { + id: "float-addition", + keywords: ["plus", "add", "addition", "sum", "float"], + name: "+.", + summary: "This is the `floating point addition` operator.", + category: Operators, + component: operators_float_addition, + }, + { + id: "float-subtraction", + keywords: ["subtract", "minus", "subtraction", "float"], + name: "-.", + summary: "This is the `floating point subtraction` operator.", + category: Operators, + component: operators_float_subtraction, + }, + { + id: "float-multiplication", + keywords: ["multiply", "multiplication", "float"], + name: "*.", + summary: "This is the `floating point multiplication` operator.", + category: Operators, + component: operators_float_multiplication, + }, + { + id: "float-division", + keywords: ["divide", "division", "float"], + name: "/.", + summary: "This is the `floating point division` operator.", + category: Operators, + component: operators_float_division, + }, + { + id: "string-concatenation", + keywords: ["concat", "concatenation", "add", "string"], + name: "++", + summary: "This is the `string concatenation` operator.", + category: Operators, + component: operators_string_concatenation, + }, ] let fuseOpts = Fuse.Options.t( From 1da0c4a44eeda1bee139c452b935d127daf947ad Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Mon, 4 Jan 2021 18:43:20 +1100 Subject: [PATCH 10/78] Add metadata to frontmatter --- misc_docs/syntax/operators_float_addition.mdx | 6 +++++- misc_docs/syntax/operators_float_division.mdx | 6 +++++- misc_docs/syntax/operators_float_multiplication.mdx | 6 +++++- misc_docs/syntax/operators_float_subtraction.mdx | 6 +++++- misc_docs/syntax/operators_integer_addition.mdx | 6 +++++- misc_docs/syntax/operators_integer_division.mdx | 6 +++++- misc_docs/syntax/operators_integer_multiplication.mdx | 6 +++++- misc_docs/syntax/operators_integer_subtraction.mdx | 6 +++++- misc_docs/syntax/operators_string_concatenation.mdx | 6 +++++- 9 files changed, 45 insertions(+), 9 deletions(-) diff --git a/misc_docs/syntax/operators_float_addition.mdx b/misc_docs/syntax/operators_float_addition.mdx index 0aff15095..27072c4d5 100644 --- a/misc_docs/syntax/operators_float_addition.mdx +++ b/misc_docs/syntax/operators_float_addition.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "float-addition" +keywords: ["plus", "add", "addition", "sum", "float"] +name: "+." +summary: "This is the `floating point addition` operator." +category: "operators" --- This operator performs *floating point* addition. diff --git a/misc_docs/syntax/operators_float_division.mdx b/misc_docs/syntax/operators_float_division.mdx index 47d1c5d99..899e0eac0 100644 --- a/misc_docs/syntax/operators_float_division.mdx +++ b/misc_docs/syntax/operators_float_division.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "float-division" +keywords: ["divide", "division", "float"] +name: "/." +summary: "This is the `floating point division` operator." +category: "operators" --- This operator performs *floating point* division. diff --git a/misc_docs/syntax/operators_float_multiplication.mdx b/misc_docs/syntax/operators_float_multiplication.mdx index 41a4da46c..391ad78da 100644 --- a/misc_docs/syntax/operators_float_multiplication.mdx +++ b/misc_docs/syntax/operators_float_multiplication.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "float-multiplication" +keywords: ["multiply", "multiplication", "float"] +name: "*." +summary: "This is the `floating point multiplication` operator." +category: "operators" --- This operator performs *floating point* multiplication. diff --git a/misc_docs/syntax/operators_float_subtraction.mdx b/misc_docs/syntax/operators_float_subtraction.mdx index 7577712ff..256754e2e 100644 --- a/misc_docs/syntax/operators_float_subtraction.mdx +++ b/misc_docs/syntax/operators_float_subtraction.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "float-subtraction" +keywords: ["subtract", "minus", "subtraction", "float"] +name: "-." +summary: "This is the `floating point subtraction` operator." +category: "operators" --- This operator performs *floating point* subtraction. diff --git a/misc_docs/syntax/operators_integer_addition.mdx b/misc_docs/syntax/operators_integer_addition.mdx index 657efb427..3d89ab707 100644 --- a/misc_docs/syntax/operators_integer_addition.mdx +++ b/misc_docs/syntax/operators_integer_addition.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "integer-addition" +keywords: ["plus", "add", "addition", "sum", "int", "integer"] +name: "+" +summary: "This is the `integer addition` operator." +category: "operators" --- This operator performs *integers* addition. diff --git a/misc_docs/syntax/operators_integer_division.mdx b/misc_docs/syntax/operators_integer_division.mdx index afacaa9f7..7e2670ed5 100644 --- a/misc_docs/syntax/operators_integer_division.mdx +++ b/misc_docs/syntax/operators_integer_division.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "integer-division" +keywords: ["divide", "division", "int", "integer"] +name: "/" +summary: "This is the `integer division` operator." +category: "operators" --- This operator performs *integer* division, with the result truncated to an integer value. diff --git a/misc_docs/syntax/operators_integer_multiplication.mdx b/misc_docs/syntax/operators_integer_multiplication.mdx index dd98c1941..4ea81b129 100644 --- a/misc_docs/syntax/operators_integer_multiplication.mdx +++ b/misc_docs/syntax/operators_integer_multiplication.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "integer-multiplication" +keywords: ["multiply", "multiplication", "int", "integer"] +name: "*" +summary: "This is the `integer multiplication` operator." +category: "operators" --- This operator performs *integer* multiplication. diff --git a/misc_docs/syntax/operators_integer_subtraction.mdx b/misc_docs/syntax/operators_integer_subtraction.mdx index 2f1fca644..1a090e6dc 100644 --- a/misc_docs/syntax/operators_integer_subtraction.mdx +++ b/misc_docs/syntax/operators_integer_subtraction.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "integer-subtraction" +keywords: ["subtract", "minus", "subtraction", "int", "integer"] +name: "-" +summary: "This is the `integer subtraction` operator." +category: "operators" --- This operator performs *integer* subtraction. diff --git a/misc_docs/syntax/operators_string_concatenation.mdx b/misc_docs/syntax/operators_string_concatenation.mdx index c73c70379..0d6b49ac8 100644 --- a/misc_docs/syntax/operators_string_concatenation.mdx +++ b/misc_docs/syntax/operators_string_concatenation.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "string-concatenation" +keywords: ["concat", "concatenation", "add", "string"] +name: "++" +summary: "This is the `string concatenation` operator." +category: "operators" --- This operator concatenates two *strings* together. From ee0e39bd843f38c95e05d7b308749b4b7b2e3d8a Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Tue, 5 Jan 2021 23:14:45 +1100 Subject: [PATCH 11/78] Syntax lookup dynamic include --- misc_docs/syntax/controlflow_ifelse.mdx | 6 +- scripts/extract-syntax.js | 38 +++++ src/components/SyntaxLookupWidget.js | 206 +++++------------------- src/components/SyntaxLookupWidget.res | 186 ++++++--------------- 4 files changed, 125 insertions(+), 311 deletions(-) create mode 100644 scripts/extract-syntax.js diff --git a/misc_docs/syntax/controlflow_ifelse.mdx b/misc_docs/syntax/controlflow_ifelse.mdx index 3cc3c48d3..4bdbb9ede 100644 --- a/misc_docs/syntax/controlflow_ifelse.mdx +++ b/misc_docs/syntax/controlflow_ifelse.mdx @@ -1,5 +1,9 @@ --- -test: "foo" +id: "if-else" +keywords: ["if", "else"] +name: "if / else" +summary: "This is the `if / else` control flow." +category: "controlflow" --- Use `if / else` expressions to express a value trough a `true` / `false` condition. diff --git a/scripts/extract-syntax.js b/scripts/extract-syntax.js new file mode 100644 index 000000000..c8878936a --- /dev/null +++ b/scripts/extract-syntax.js @@ -0,0 +1,38 @@ +const matter = require("gray-matter"); +const slug = require("remark-slug"); +const glob = require("glob"); +const path = require("path"); +const fs = require("fs"); + +const processFile = filepath => { + const raw = fs.readFileSync(filepath, "utf8"); + const { data } = matter(raw); + + const syntaxPath = path.resolve("./misc_docs/syntax"); + const relFilePath = path.relative(syntaxPath, filepath); + const parsedPath = path.parse(relFilePath); + + if (data.id && data.keywords && data.name && data.summary && data.category) { + return { + file: parsedPath.name, + id: data.id, + keywords: data.keywords, + name: data.name, + summary: data.summary, + category: data.category + } + } + + console.error("Metadata missing in " + parsedPath.name + ".mdx") + return null; +}; + +const extractSyntax = async version => { + const SYNTAX_MD_DIR = path.join(__dirname, "../misc_docs/syntax"); + const SYNTAX_INDEX_FILE = path.join(__dirname, "../index_data/syntax_index.json"); + const syntaxFiles = glob.sync(`${SYNTAX_MD_DIR}/*.md?(x)`); + const syntaxIndex = syntaxFiles.map(processFile).filter(Boolean).sort((a, b) => a.name.localeCompare(b.name)) + fs.writeFileSync(SYNTAX_INDEX_FILE, JSON.stringify(syntaxIndex), "utf8"); +}; + +extractSyntax().catch(console.error) diff --git a/src/components/SyntaxLookupWidget.js b/src/components/SyntaxLookupWidget.js index c7e13ef05..d492d0f6f 100644 --- a/src/components/SyntaxLookupWidget.js +++ b/src/components/SyntaxLookupWidget.js @@ -11,23 +11,17 @@ import * as Belt_Array from "bs-platform/lib/es6/belt_Array.js"; import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; import * as GithubSlugger from "github-slugger"; -import Decorator_asMdx from "misc_docs/syntax/decorator_as.mdx"; -import Decorator_moduleMdx from "misc_docs/syntax/decorator_module.mdx"; -import Controlflow_ifelseMdx from "misc_docs/syntax/controlflow_ifelse.mdx"; -import Operators_float_additionMdx from "misc_docs/syntax/operators_float_addition.mdx"; -import Operators_float_divisionMdx from "misc_docs/syntax/operators_float_division.mdx"; -import Operators_integer_additionMdx from "misc_docs/syntax/operators_integer_addition.mdx"; -import Operators_integer_divisionMdx from "misc_docs/syntax/operators_integer_division.mdx"; -import Operators_float_subtractionMdx from "misc_docs/syntax/operators_float_subtraction.mdx"; -import Operators_integer_subtractionMdx from "misc_docs/syntax/operators_integer_subtraction.mdx"; -import Operators_float_multiplicationMdx from "misc_docs/syntax/operators_float_multiplication.mdx"; -import Operators_string_concatenationMdx from "misc_docs/syntax/operators_string_concatenation.mdx"; -import Operators_integer_multiplicationMdx from "misc_docs/syntax/operators_integer_multiplication.mdx"; + +var indexData = (require('index_data/syntax_index.json')); var render = (function(c) { return React.createElement(c, {}); }); +var requireSyntaxFile = (function(name) { + return require("misc_docs/syntax/" + name + ".mdx").default + }); + function toString(t) { switch (t) { case /* Decorators */0 : @@ -50,163 +44,37 @@ function SyntaxLookupWidget$Category(Props) { }, title), React.createElement("div", undefined, children)); } -var allItems = [ - { - id: "module-decorator", - keywords: ["@bs.module"], - name: "@module", - summary: "This is the `@module` decorator.", - category: /* Decorators */0, - component: Decorator_moduleMdx - }, - { - id: "as-decorator", - keywords: ["@bs.as"], - name: "@as", - summary: "This is the `@as` decorator.", - category: /* Decorators */0, - component: Decorator_asMdx - }, - { - id: "if-else", - keywords: [ - "if", - "else", - "if else" - ], - name: "if / else", - summary: "This is the `if / else` control flow structure.", - category: /* ControlFlow */1, - component: Controlflow_ifelseMdx - }, - { - id: "uncurried-function", - keywords: ["uncurried"], - name: "(.) => {}", - summary: "This is an `uncurried` function.", - category: /* Other */3, - component: Controlflow_ifelseMdx - }, - { - id: "integer-addition", - keywords: [ - "plus", - "add", - "addition", - "sum", - "int", - "integer" - ], - name: "+", - summary: "This is the `integer addition` operator.", - category: /* Operators */2, - component: Operators_integer_additionMdx - }, - { - id: "integer-subtraction", - keywords: [ - "subtract", - "minus", - "subtraction", - "int", - "integer" - ], - name: "-", - summary: "This is the `integer subtraction` operator.", - category: /* Operators */2, - component: Operators_integer_subtractionMdx - }, - { - id: "integer-multiplication", - keywords: [ - "multiply", - "multiplication", - "int", - "integer" - ], - name: "*", - summary: "This is the `integer multiplication` operator.", - category: /* Operators */2, - component: Operators_integer_multiplicationMdx - }, - { - id: "integer-division", - keywords: [ - "divide", - "division", - "int", - "integer" - ], - name: "/", - summary: "This is the `integer division` operator.", - category: /* Operators */2, - component: Operators_integer_divisionMdx - }, - { - id: "float-addition", - keywords: [ - "plus", - "add", - "addition", - "sum", - "float" - ], - name: "+.", - summary: "This is the `floating point addition` operator.", - category: /* Operators */2, - component: Operators_float_additionMdx - }, - { - id: "float-subtraction", - keywords: [ - "subtract", - "minus", - "subtraction", - "float" - ], - name: "-.", - summary: "This is the `floating point subtraction` operator.", - category: /* Operators */2, - component: Operators_float_subtractionMdx - }, - { - id: "float-multiplication", - keywords: [ - "multiply", - "multiplication", - "float" - ], - name: "*.", - summary: "This is the `floating point multiplication` operator.", - category: /* Operators */2, - component: Operators_float_multiplicationMdx - }, - { - id: "float-division", - keywords: [ - "divide", - "division", - "float" - ], - name: "/.", - summary: "This is the `floating point division` operator.", - category: /* Operators */2, - component: Operators_float_divisionMdx - }, - { - id: "string-concatenation", - keywords: [ - "concat", - "concatenation", - "add", - "string" - ], - name: "++", - summary: "This is the `string concatenation` operator.", - category: /* Operators */2, - component: Operators_string_concatenationMdx +function toCategory(s) { + switch (s) { + case "controlflow" : + return /* ControlFlow */1; + case "decorators" : + return /* Decorators */0; + case "operators" : + return /* Operators */2; + default: + return /* Other */3; } -]; +} + +function toItem(syntaxData) { + var file = syntaxData.file; + var id = syntaxData.id; + var keywords = syntaxData.keywords; + var name = syntaxData.name; + var summary = syntaxData.summary; + var category = syntaxData.category; + return { + id: id, + keywords: keywords, + name: name, + summary: summary, + category: toCategory(category), + component: requireSyntaxFile(file) + }; +} + +var allItems = Belt_Array.map(indexData, toItem); var fuseOpts = { shouldSort: false, @@ -481,4 +349,4 @@ export { make , } -/* allItems Not a pure module */ +/* indexData Not a pure module */ diff --git a/src/components/SyntaxLookupWidget.res b/src/components/SyntaxLookupWidget.res index 017110e1f..7918f3938 100644 --- a/src/components/SyntaxLookupWidget.res +++ b/src/components/SyntaxLookupWidget.res @@ -1,3 +1,15 @@ +// Structure defined by `scripts/extract-syntax.js` +type syntaxData = { + "file": string, + "id": string, + "keywords": array, + "name": string, + "summary": string, + "category": string, +} + +let indexData: array = %raw("require('index_data/syntax_index.json')") + module MdxComp = { type props type t = Js.t => React.element @@ -14,41 +26,11 @@ module MdxComp = { /* external frontmatter: t => Js.Json.t = "frontmatter" */ } -@module("misc_docs/syntax/decorator_module.mdx") -external decorator_module: MdxComp.t = "default" - -@module("misc_docs/syntax/decorator_as.mdx") -external decorator_as: MdxComp.t = "default" - -@module("misc_docs/syntax/controlflow_ifelse.mdx") -external controlflow_ifelse: MdxComp.t = "default" - -@module("misc_docs/syntax/operators_integer_addition.mdx") -external operators_integer_addition: MdxComp.t = "default" - -@module("misc_docs/syntax/operators_integer_subtraction.mdx") -external operators_integer_subtraction: MdxComp.t = "default" - -@module("misc_docs/syntax/operators_integer_multiplication.mdx") -external operators_integer_multiplication: MdxComp.t = "default" - -@module("misc_docs/syntax/operators_integer_division.mdx") -external operators_integer_division: MdxComp.t = "default" - -@module("misc_docs/syntax/operators_float_addition.mdx") -external operators_float_addition: MdxComp.t = "default" - -@module("misc_docs/syntax/operators_float_subtraction.mdx") -external operators_float_subtraction: MdxComp.t = "default" - -@module("misc_docs/syntax/operators_float_multiplication.mdx") -external operators_float_multiplication: MdxComp.t = "default" - -@module("misc_docs/syntax/operators_float_division.mdx") -external operators_float_division: MdxComp.t = "default" - -@module("misc_docs/syntax/operators_string_concatenation.mdx") -external operators_string_concatenation: MdxComp.t = "default" +let requireSyntaxFile: string => MdxComp.t = %raw(` + function(name) { + return require("misc_docs/syntax/" + name + ".mdx").default + } +`) module Category = { type t = Decorators | ControlFlow | Operators | Other @@ -81,112 +63,34 @@ type item = { component: MdxComp.t, } -let allItems = [ - { - id: "module-decorator", - keywords: ["@bs.module"], - name: "@module", - summary: "This is the `@module` decorator.", - category: Decorators, - component: decorator_module, - }, - { - id: "as-decorator", - keywords: ["@bs.as"], - name: "@as", - summary: "This is the `@as` decorator.", - category: Decorators, - component: decorator_as, - }, - { - id: "if-else", - keywords: ["if", "else", "if else"], - name: "if / else", - summary: "This is the `if / else` control flow structure.", - category: ControlFlow, - component: controlflow_ifelse, - }, - { - id: "uncurried-function", - keywords: ["uncurried"], - name: "(.) => {}", - summary: "This is an `uncurried` function.", - category: Other, - component: controlflow_ifelse, - }, - { - id: "integer-addition", - keywords: ["plus", "add", "addition", "sum", "int", "integer"], - name: "+", - summary: "This is the `integer addition` operator.", - category: Operators, - component: operators_integer_addition, - }, - { - id: "integer-subtraction", - keywords: ["subtract", "minus", "subtraction", "int", "integer"], - name: "-", - summary: "This is the `integer subtraction` operator.", - category: Operators, - component: operators_integer_subtraction, - }, - { - id: "integer-multiplication", - keywords: ["multiply", "multiplication", "int", "integer"], - name: "*", - summary: "This is the `integer multiplication` operator.", - category: Operators, - component: operators_integer_multiplication, - }, - { - id: "integer-division", - keywords: ["divide", "division", "int", "integer"], - name: "/", - summary: "This is the `integer division` operator.", - category: Operators, - component: operators_integer_division, - }, - { - id: "float-addition", - keywords: ["plus", "add", "addition", "sum", "float"], - name: "+.", - summary: "This is the `floating point addition` operator.", - category: Operators, - component: operators_float_addition, - }, - { - id: "float-subtraction", - keywords: ["subtract", "minus", "subtraction", "float"], - name: "-.", - summary: "This is the `floating point subtraction` operator.", - category: Operators, - component: operators_float_subtraction, - }, - { - id: "float-multiplication", - keywords: ["multiply", "multiplication", "float"], - name: "*.", - summary: "This is the `floating point multiplication` operator.", - category: Operators, - component: operators_float_multiplication, - }, - { - id: "float-division", - keywords: ["divide", "division", "float"], - name: "/.", - summary: "This is the `floating point division` operator.", - category: Operators, - component: operators_float_division, - }, - { - id: "string-concatenation", - keywords: ["concat", "concatenation", "add", "string"], - name: "++", - summary: "This is the `string concatenation` operator.", - category: Operators, - component: operators_string_concatenation, - }, -] +let toCategory = (s: string): Category.t => { + switch s { + | "decorators" => Decorators + | "controlflow" => ControlFlow + | "operators" => Operators + | _ => Other + } +} + +let toItem = (syntaxData: syntaxData): item => { + let file = syntaxData["file"] + let id = syntaxData["id"] + let keywords = syntaxData["keywords"] + let name = syntaxData["name"] + let summary = syntaxData["summary"] + let category = syntaxData["category"] + let item: item = { + id: id, + keywords: keywords, + name: name, + summary: summary, + category: toCategory(category), + component: requireSyntaxFile(file) + } + item +} + +let allItems = indexData->Belt.Array.map(toItem) let fuseOpts = Fuse.Options.t( ~shouldSort=false, From d5224456ba0c297dcde1b3fac145440ad120892a Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Tue, 5 Jan 2021 23:38:27 +1100 Subject: [PATCH 12/78] Add extract-syntax to update-index script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e210e7714..e6774bd40 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "test": "node scripts/test-examples.js && node scripts/test-hrefs.js", "check-dead-code": "reanalyze -dce", "check-for-exceptions": "reanalyze -exception", - "update-index": "node scripts/extract-indices.js && node scripts/extract-tocs.js && node -r esm scripts/generate_feed.js > public/blog/feed.xml", + "update-index": "node scripts/extract-indices.js && node scripts/extract-tocs.js && node scripts/extract-syntax.js && node -r esm scripts/generate_feed.js > public/blog/feed.xml", "now-build": "yarn run build", "export": "next export", "start": "next start -p $PORT", From 6bc52bac43f759fd0bc64d2ad5100dbaa6d35e47 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Tue, 5 Jan 2021 23:46:03 +1100 Subject: [PATCH 13/78] Remove unused remark-slug import --- scripts/extract-syntax.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/extract-syntax.js b/scripts/extract-syntax.js index c8878936a..8daf3dde3 100644 --- a/scripts/extract-syntax.js +++ b/scripts/extract-syntax.js @@ -1,5 +1,4 @@ const matter = require("gray-matter"); -const slug = require("remark-slug"); const glob = require("glob"); const path = require("path"); const fs = require("fs"); From f4c479b4b00f6d33beaa5296f5202653f8cd1bad Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Tue, 5 Jan 2021 23:47:05 +1100 Subject: [PATCH 14/78] Remove unnecessary catch --- scripts/extract-syntax.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/extract-syntax.js b/scripts/extract-syntax.js index 8daf3dde3..22cf0fd7f 100644 --- a/scripts/extract-syntax.js +++ b/scripts/extract-syntax.js @@ -34,4 +34,4 @@ const extractSyntax = async version => { fs.writeFileSync(SYNTAX_INDEX_FILE, JSON.stringify(syntaxIndex), "utf8"); }; -extractSyntax().catch(console.error) +extractSyntax() From 8baa22dd523e4dd908cb31fbdaab79efec36cf46 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:04:40 +1100 Subject: [PATCH 15/78] Add get decorator syntax --- misc_docs/syntax/decorator_get.mdx | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 misc_docs/syntax/decorator_get.mdx diff --git a/misc_docs/syntax/decorator_get.mdx b/misc_docs/syntax/decorator_get.mdx new file mode 100644 index 000000000..8efc0dfd3 --- /dev/null +++ b/misc_docs/syntax/decorator_get.mdx @@ -0,0 +1,35 @@ +--- +id: "get-decorator" +keywords: ["get", "decorator", "property", "object", "bind"] +name: "@get" +summary: "This is the `@get` decorator." +category: "decorators" +--- + +The `@get` decorator is used to bind to a property of an object. + +For example: + + + +```res +type element + +@scope("document") @val +external createElement: string => element = "createElement" + +@get +external getScrollTop: element => unit = "scrollTop" + +let div = createElement("div") +let top = getScrollTop(div) +``` + +```js +var div = document.createElement("div") +var top = div.scrollTop +``` + + + + From 4987d0aab31c4ad22297bbaa7e91749688d58b84 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:06:38 +1100 Subject: [PATCH 16/78] Add set decorator syntax --- misc_docs/syntax/decorator_set.mdx | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 misc_docs/syntax/decorator_set.mdx diff --git a/misc_docs/syntax/decorator_set.mdx b/misc_docs/syntax/decorator_set.mdx new file mode 100644 index 000000000..430608437 --- /dev/null +++ b/misc_docs/syntax/decorator_set.mdx @@ -0,0 +1,36 @@ +--- +id: "set-decorator" +keywords: ["set", "property", "object", "bind"] +name: "@set" +summary: "This is the `@set` decorator." +category: "decorators" +--- + +The `@set` decorator is used to set a property of an object. + +For example: + + + +```res +type element + +@scope("document") @val +external createElement: string => element = "createElement" + +@set +external setScrollTop: (element, int) => unit = "scrollTop" + +let div = createElement("div") +setScrollTop(div, 100) +``` + +```js +var div = document.createElement("div") + +div.scrollTop = 100 +``` + + + + From f1f36e83f87a765220bc3913257bcdce38741885 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:07:46 +1100 Subject: [PATCH 17/78] Add set index decorator syntax --- misc_docs/syntax/decorator_set_index.mdx | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 misc_docs/syntax/decorator_set_index.mdx diff --git a/misc_docs/syntax/decorator_set_index.mdx b/misc_docs/syntax/decorator_set_index.mdx new file mode 100644 index 000000000..bc7f7d68b --- /dev/null +++ b/misc_docs/syntax/decorator_set_index.mdx @@ -0,0 +1,72 @@ +--- +id: "set-index-decorator" +keywords: ["set", "decorator", "array", "object"] +name: "@set_index" +summary: "This is the `@set_index` decorator." +category: "decorators" +--- + +The `@set_index` decorator is used to set a dynamic property or index. + +For example with an Array: + + + +```res +type t + +@new external create: int => t = "Array" +@set_index external set: (t, int, string) => unit = "" +@get_index external get: (t, int) => string = "" + +let a = create(3) +a->set(0, "zero") +a->set(1, "one") +a->set(2, "two") + +let value = a->get(1) +``` + +```js +var a = new Array(3); + +a[0] = "zero"; +a[1] = "one"; +a[2] = "two"; + +var value = a[1]; +``` + + + +And an example with an object: + + + +```res +type t + +@new external create: unit => t = "Object" +@set_index external set: (t, string, int) => unit = "" +@get_index external get: (t, string) => int = "" + +let o = create() +o->set("x", 1) +o->set("y", 3) +o->set("z", 5) + +let value = o->get("y") +``` + +```js +var o = new Object(); + +o["x"] = 1; +o["y"] = 3; +o["z"] = 5; + +var value = o["y"]; +``` + + + From 916b5d0a1883e341b7f5655a5bfc7e19b4f5ef1d Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:08:15 +1100 Subject: [PATCH 18/78] Add get index decorator syntax --- misc_docs/syntax/decorator_get_index.mdx | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 misc_docs/syntax/decorator_get_index.mdx diff --git a/misc_docs/syntax/decorator_get_index.mdx b/misc_docs/syntax/decorator_get_index.mdx new file mode 100644 index 000000000..9357d6959 --- /dev/null +++ b/misc_docs/syntax/decorator_get_index.mdx @@ -0,0 +1,72 @@ +--- +id: "get-index-decorator" +keywords: ["get", "decorator", "array", "object"] +name: "@get_index" +summary: "This is the `@get_index` decorator." +category: "decorators" +--- + +The `@get_index` decorator is used to access a dynamic property or index. + +For example with an Array: + + + +```res +type t + +@new external create: int => t = "Array" +@set_index external set: (t, int, string) => unit = "" +@get_index external get: (t, int) => string = "" + +let a = create(3) +a->set(0, "zero") +a->set(1, "one") +a->set(2, "two") + +let value = a->get(1) +``` + +```js +var a = new Array(3); + +a[0] = "zero"; +a[1] = "one"; +a[2] = "two"; + +var value = a[1]; +``` + + + +And an example with an object: + + + +```res +type t + +@new external create: unit => t = "Object" +@set_index external set: (t, string, int) => unit = "" +@get_index external get: (t, string) => int = "" + +let o = create() +o->set("x", 1) +o->set("y", 3) +o->set("z", 5) + +let value = o->get("y") +``` + +```js +var o = new Object(); + +o["x"] = 1; +o["y"] = 3; +o["z"] = 5; + +var value = o["y"]; +``` + + + From f288353b1f30969b5bb2e7ba45b8a7cdb9c6e03c Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:09:20 +1100 Subject: [PATCH 19/78] Add val decorator syntax --- misc_docs/syntax/decorator_val.mdx | 34 ++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/misc_docs/syntax/decorator_val.mdx b/misc_docs/syntax/decorator_val.mdx index 434b0c25b..fa13595a5 100644 --- a/misc_docs/syntax/decorator_val.mdx +++ b/misc_docs/syntax/decorator_val.mdx @@ -1,3 +1,33 @@ -This decorator is used to bind to a value in global scope. +--- +id: "val-decorator" +keywords: ["val", "decorator", "bind", "global"] +name: "@val" +summary: "This is the `@val` decorator." +category: "decorators" +--- + +The `@val` decorator allows you to bind to JavaScript values that are on the global scope. + +For example: + + + +```res +type timeoutID + +@val +external setTimeout: (unit => unit, int) => timeoutID = "setTimeout" + +let timeoutID = setTimeout(() => Js.log("Hello"), 1000) +``` + +```js +var timeoutID = setTimeout(function (param) { + console.log("Hello") +}, 1000) +``` + + + +To access global values on another global object, such as `Date.now` or `location.origin.length` see the `@scope` decorator. -**Also see:** `@bs.val` From 622dd1201d146d3ba6e756df0b64be0dd4b04bca Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:09:45 +1100 Subject: [PATCH 20/78] Add new decorator syntax --- misc_docs/syntax/decorator_new.mdx | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/misc_docs/syntax/decorator_new.mdx b/misc_docs/syntax/decorator_new.mdx index 1a4ed55ee..aceb2400e 100644 --- a/misc_docs/syntax/decorator_new.mdx +++ b/misc_docs/syntax/decorator_new.mdx @@ -1,16 +1,25 @@ -This decorator is used whenever you need to bind to a JS class constructor that requires the `new` keword for instantiation. +--- +id: "new-decorator" +keywords: ["new", "decorator", "object"] +name: "@new" +summary: "This is the `@new` decorator." +category: "decorators" +--- + +The `@new` decorator is used whenever you need to bind to a JavaScript class constructor that requires the `new` keword for instantiation. -```res +```re type t -@bs.new external create: unit => t = "Date" -create(); +@new external create: unit => t = "Date" + +let now = create() ``` ```js -new Date(); +var now = new Date(); ``` @@ -20,10 +29,11 @@ When the object is not available on the global scope, combine it with `@module`: ```res -type t; -@module @bs.new external book: unit => t = "Book"; +type t + +@module @new external book: unit => t = "Book" -let myBook = book(); +let myBook = book() ``` ```js From dfe1cdab12e45014febd1e648b4db749468b0bb7 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:10:05 +1100 Subject: [PATCH 21/78] Add send decorator syntax --- misc_docs/syntax/decorator_send.mdx | 41 ++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_send.mdx b/misc_docs/syntax/decorator_send.mdx index b8eafdd7d..961f65362 100644 --- a/misc_docs/syntax/decorator_send.mdx +++ b/misc_docs/syntax/decorator_send.mdx @@ -1 +1,40 @@ -This decorator is used to "send a value" to an instance of an object. +--- +id: "send-decorator" +keywords: ["send", "decorator", "object"] +name: "@send" +summary: "This is the `@send` decorator." +category: "decorators" +--- + +The `@send` decorator is used to call a function on an object. + +For example: + + + +```res +type element + +@scope("document") @val +external createElement: string => element = "createElement" + +@send +external appendChild: (element, element) => element = "appendChild" + +let div = createElement("div") +let button = createElement("button") + +let _ = appendChild(div, button) +``` + +```js +var div = document.createElement("div"); + +var button = document.createElement("button"); + +div.appendChild(button); +``` + + + + From 33a73706b4ef65b478e0ec9966a00d7423ae7648 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:10:30 +1100 Subject: [PATCH 22/78] Add scope decorator syntax --- misc_docs/syntax/decorator_scope.mdx | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 misc_docs/syntax/decorator_scope.mdx diff --git a/misc_docs/syntax/decorator_scope.mdx b/misc_docs/syntax/decorator_scope.mdx new file mode 100644 index 000000000..d354886a6 --- /dev/null +++ b/misc_docs/syntax/decorator_scope.mdx @@ -0,0 +1,40 @@ +--- +id: "scope-decorator" +keywords: ["scope", "decorator", "bind", "global"] +name: "@scope" +summary: "This is the `@scope` decorator." +category: "decorators" +--- + +The `@scope` decorator is used with other decorators such as `@val` and `@module` to declare a parent scope for the binding. + +For example: + + + +```res +@scope("Math") @val +external floor: float => int = "floor" + +@scope(("location", "origin")) @val +external originLength: string = "length" + +@module("MyModule") @scope("CONSTANTS") +external initialDays: int = "initialDays" + +Js.log(floor(3.4)) +Js.log(originLength) +Js.log(initialDays) +``` + +```js +var MyModule = require("MyModule") + +console.log(Math.floor(3.4)) +console.log(location.origin.length) +console.log(MyModule.CONSTANTS.initialDays) +``` + + + +Note that the order of the decorators doesn't matter. \ No newline at end of file From 46a97e837e42ea5963ecd26309aabcfb16939e44 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:11:10 +1100 Subject: [PATCH 23/78] Add string decorator syntax --- misc_docs/syntax/decorator_string.mdx | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 misc_docs/syntax/decorator_string.mdx diff --git a/misc_docs/syntax/decorator_string.mdx b/misc_docs/syntax/decorator_string.mdx new file mode 100644 index 000000000..cfed0974a --- /dev/null +++ b/misc_docs/syntax/decorator_string.mdx @@ -0,0 +1,29 @@ +--- +id: "string-decorator" +keywords: ["string", "decorator", "polymorphic", "variant", "as", "external"] +name: "@string" +summary: "This is the `@string` decorator." +category: "decorators" +--- + +The `@string` decorator can be used with polymorphic variants and the `@as` decorator on *externals* to modify the compiled JavaScript. + +For example: + + + +```res +@val external setStatus: @string[ + @as("NOT_STARTED") #NotStarted | + @as("STARTED") #Started | + @as("DONE") #Done +] => unit = "setStatus" + +setStatus(#NotStarted) +``` + +```js +setStatus("NOT_STARTED"); +``` + + From 1cb11a329e5db8b1785445b83b02a56e2fb30930 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:11:31 +1100 Subject: [PATCH 24/78] Add int decorator syntax --- misc_docs/syntax/decorator_int.mdx | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 misc_docs/syntax/decorator_int.mdx diff --git a/misc_docs/syntax/decorator_int.mdx b/misc_docs/syntax/decorator_int.mdx new file mode 100644 index 000000000..191707fd1 --- /dev/null +++ b/misc_docs/syntax/decorator_int.mdx @@ -0,0 +1,29 @@ +--- +id: "int-decorator" +keywords: ["int", "decorator", "polymorphic", "variant", "as", "external"] +name: "@int" +summary: "This is the `@int` decorator." +category: "decorators" +--- + +The `@int` decorator can be used with polymorphic variants and the `@as` decorator on *externals* to modify the compiled JavaScript. + +For example: + + + +```res +@val external setStatus: @int[ + @as(0) #NotStarted | + @as(1) #Started | + @as(2) #Done +] => unit = "setStatus" + +setStatus(#Done) +``` + +```js +setStatus(2); +``` + + From 3557fa6d6ec1221b32ab857b1b6409a5f0ddaad4 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:12:25 +1100 Subject: [PATCH 25/78] Add unwrap decorator syntax --- misc_docs/syntax/decorator_unwrap.mdx | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 misc_docs/syntax/decorator_unwrap.mdx diff --git a/misc_docs/syntax/decorator_unwrap.mdx b/misc_docs/syntax/decorator_unwrap.mdx new file mode 100644 index 000000000..a488daadf --- /dev/null +++ b/misc_docs/syntax/decorator_unwrap.mdx @@ -0,0 +1,48 @@ +--- +id: "unwrap-decorator" +keywords: ["unwrap", "decorator", "external"] +name: "@unwrap" +summary: "This is the `@unwrap` decorator." +category: "decorators" +--- + +The `@unwrap` decorator may be used when binding to external functions that accept multiple types for an argument. + +Consider the following JavaScript function: + +```js +function padLeft(padding, str) { + if (typeof padding === "number") { + return " ".repeat(padding) + str; + } + if (typeof padding === "string") { + return padding + str; + } + throw new Error("Expected padding to be number or string"); +} +``` +Note how `padding` can be either a number or a string. + +Here is how you'd bind to this function: + + + +```res +@val external padLeft: ( + @unwrap [#Int(int) | #Str(string)], + string +) => string = "padLeft"; + +let _ = padLeft(#Int(7), "eleven"); +let _ = padLeft(#Str("7"), "eleven"); +``` + +```js +padLeft(7, "eleven"); + +padLeft("7", "eleven"); +``` + + + +Review the JavaScript output and note how `@unwrap` simply unwraps the polymorphic variant constructor. From 49a7b7d8691602dfc7c869f90f1b1ea16c27b282 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:13:06 +1100 Subject: [PATCH 26/78] Add as decorator syntax --- misc_docs/syntax/decorator_as.mdx | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/misc_docs/syntax/decorator_as.mdx b/misc_docs/syntax/decorator_as.mdx index 5926018cc..5c6030bfe 100644 --- a/misc_docs/syntax/decorator_as.mdx +++ b/misc_docs/syntax/decorator_as.mdx @@ -1,19 +1,25 @@ --- -test: "foo" +id: "as-decorator" +keywords: ["as", "decorator", "record", "alias", "object"] +name: "@as" +summary: "This is the `@as` decorator." +category: "decorators" --- -Use this decorator on record types to alias record names to a different JS attribute name. +The `@as` decorator may be used on record types to alias record names to a different JavaScript attribute name. -This is mostly useful to map to JS attribute names that cannot be expressed in ReScript (such as keywords). +This is mostly useful to map to JavaScript attribute names that cannot be expressed in ReScript (such as keywords). -### Example +For example -```reason +```re type action = { - [@bs.as "type"] _type: string, -}; + @as("type") type_: string +} + +let action = {type_: "ADD_USER"} ``` ```js @@ -21,6 +27,6 @@ var action = { type: "ADD_USER" }; ``` + -Refer to the [Records as Objects](/docs/manual/latest/bind-to-js-object#bind-using-rescript-record) section for a more detailed explanation. From 55d7ff3a95bc46da0a0959d2af1842cbda9505ea Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:13:32 +1100 Subject: [PATCH 27/78] Add module decorator syntax --- misc_docs/syntax/decorator_module.mdx | 31 ++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_module.mdx b/misc_docs/syntax/decorator_module.mdx index 4eba66db7..e0548a578 100644 --- a/misc_docs/syntax/decorator_module.mdx +++ b/misc_docs/syntax/decorator_module.mdx @@ -1 +1,30 @@ -used for [this](https://google.com) and [that](https://google.com) +--- +id: "module-decorator" +keywords: ["module", "decorator", "import", "require", "bind"] +name: "@module" +summary: "This is the `@module` decorator." +category: "decorators" +--- + +The `@module` decorator is used to bind to a JavaScript module. + +For example: + + + +```res +@module("path") +external dirname: string => string = "dirname" + +let root = dirname("/User/github") +``` + +```js +var Path = require("path"); + +var root = Path.dirname("/User/github"); +``` + + + +See the [Import from JavaScript](/docs/manual/latest/import-from-export-to-js#import-from-javascript) section for full details. From c5332f54ad5453d612cd54f81f9d21acca605dde Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:26:52 +1100 Subject: [PATCH 28/78] Tweak as decorator syntax --- misc_docs/syntax/decorator_as.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/misc_docs/syntax/decorator_as.mdx b/misc_docs/syntax/decorator_as.mdx index 5c6030bfe..b3ce3386d 100644 --- a/misc_docs/syntax/decorator_as.mdx +++ b/misc_docs/syntax/decorator_as.mdx @@ -1,16 +1,16 @@ --- id: "as-decorator" -keywords: ["as", "decorator", "record", "alias", "object"] +keywords: ["as", "decorator", "record", "field", "alias", "object"] name: "@as" summary: "This is the `@as` decorator." category: "decorators" --- -The `@as` decorator may be used on record types to alias record names to a different JavaScript attribute name. +The `@as` decorator may be used on record types to alias record field names to a different JavaScript attribute name. This is mostly useful to map to JavaScript attribute names that cannot be expressed in ReScript (such as keywords). -For example +For example: From f9d4ea3ec920750198ec0bf855b15330a70e2acc Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:28:56 +1100 Subject: [PATCH 29/78] Tweak get decorator syntax --- misc_docs/syntax/decorator_get.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_get.mdx b/misc_docs/syntax/decorator_get.mdx index 8efc0dfd3..a5715fad6 100644 --- a/misc_docs/syntax/decorator_get.mdx +++ b/misc_docs/syntax/decorator_get.mdx @@ -12,7 +12,7 @@ For example: -```res +```re type element @scope("document") @val From c5bd2f92d7474532b595fbc9048939aba4587213 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:30:30 +1100 Subject: [PATCH 30/78] Tweak get index decorator syntax --- misc_docs/syntax/decorator_get_index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_get_index.mdx b/misc_docs/syntax/decorator_get_index.mdx index 9357d6959..37d854921 100644 --- a/misc_docs/syntax/decorator_get_index.mdx +++ b/misc_docs/syntax/decorator_get_index.mdx @@ -1,6 +1,6 @@ --- id: "get-index-decorator" -keywords: ["get", "decorator", "array", "object"] +keywords: ["get", "decorator", "array", "object", "index"] name: "@get_index" summary: "This is the `@get_index` decorator." category: "decorators" From 37ca04ec585f8c7d3c4694299bacf04058c55785 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:33:50 +1100 Subject: [PATCH 31/78] Tweak get index decorator syntax --- misc_docs/syntax/decorator_get_index.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc_docs/syntax/decorator_get_index.mdx b/misc_docs/syntax/decorator_get_index.mdx index 37d854921..45e27f587 100644 --- a/misc_docs/syntax/decorator_get_index.mdx +++ b/misc_docs/syntax/decorator_get_index.mdx @@ -12,7 +12,7 @@ For example with an Array: -```res +```re type t @new external create: int => t = "Array" @@ -43,7 +43,7 @@ And an example with an object: -```res +```re type t @new external create: unit => t = "Object" From d60db1fac20b43fea2892221c82057c49a46275f Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:37:21 +1100 Subject: [PATCH 32/78] Tweak int decorator syntax --- misc_docs/syntax/decorator_int.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc_docs/syntax/decorator_int.mdx b/misc_docs/syntax/decorator_int.mdx index 191707fd1..6e83bc100 100644 --- a/misc_docs/syntax/decorator_int.mdx +++ b/misc_docs/syntax/decorator_int.mdx @@ -6,13 +6,13 @@ summary: "This is the `@int` decorator." category: "decorators" --- -The `@int` decorator can be used with polymorphic variants and the `@as` decorator on *externals* to modify the compiled JavaScript. +The `@int` decorator can be used with [polymorphic variants](/docs/manual/latest/polymorphic-variant) and the `@as` decorator on *externals* to modify the compiled JavaScript to use integers for the values instead of strings. For example: -```res +```re @val external setStatus: @int[ @as(0) #NotStarted | @as(1) #Started | From f24d471917391f6e0ae12c75ef578eb02a1c723a Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:38:24 +1100 Subject: [PATCH 33/78] Tweak string decorator syntax --- misc_docs/syntax/decorator_string.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc_docs/syntax/decorator_string.mdx b/misc_docs/syntax/decorator_string.mdx index cfed0974a..94b51d79e 100644 --- a/misc_docs/syntax/decorator_string.mdx +++ b/misc_docs/syntax/decorator_string.mdx @@ -6,13 +6,13 @@ summary: "This is the `@string` decorator." category: "decorators" --- -The `@string` decorator can be used with polymorphic variants and the `@as` decorator on *externals* to modify the compiled JavaScript. +The `@string` decorator can be used with polymorphic variants and the `@as` decorator on *externals* to modify the string values used for the variants in the compiled JavaScript. For example: -```res +```re @val external setStatus: @string[ @as("NOT_STARTED") #NotStarted | @as("STARTED") #Started | From f73643ecdb01d889cfd22b186c26f0ad84684a0e Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:40:02 +1100 Subject: [PATCH 34/78] Tweak module decorator syntax --- misc_docs/syntax/decorator_module.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc_docs/syntax/decorator_module.mdx b/misc_docs/syntax/decorator_module.mdx index e0548a578..56665fcae 100644 --- a/misc_docs/syntax/decorator_module.mdx +++ b/misc_docs/syntax/decorator_module.mdx @@ -12,7 +12,7 @@ For example: -```res +```re @module("path") external dirname: string => string = "dirname" @@ -27,4 +27,4 @@ var root = Path.dirname("/User/github"); -See the [Import from JavaScript](/docs/manual/latest/import-from-export-to-js#import-from-javascript) section for full details. +See the [Import from JavaScript](/docs/manual/latest/import-from-export-to-js#import-from-javascript) section for full details, including other variations of how this decorator may be used. From c674341b2a811057bb6ff3e65d6014df38729bfe Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:41:04 +1100 Subject: [PATCH 35/78] Tweak new decorator syntax --- misc_docs/syntax/decorator_new.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_new.mdx b/misc_docs/syntax/decorator_new.mdx index aceb2400e..d2d3f58c8 100644 --- a/misc_docs/syntax/decorator_new.mdx +++ b/misc_docs/syntax/decorator_new.mdx @@ -28,7 +28,7 @@ When the object is not available on the global scope, combine it with `@module`: -```res +```re type t @module @new external book: unit => t = "Book" From 43b6e344bf93c1380b70e5cd91a3cf80fc940fe2 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:41:50 +1100 Subject: [PATCH 36/78] Tweak scope decorator syntax --- misc_docs/syntax/decorator_scope.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_scope.mdx b/misc_docs/syntax/decorator_scope.mdx index d354886a6..ce2b8438c 100644 --- a/misc_docs/syntax/decorator_scope.mdx +++ b/misc_docs/syntax/decorator_scope.mdx @@ -12,7 +12,7 @@ For example: -```res +```re @scope("Math") @val external floor: float => int = "floor" From b6502fb1f74f56f0478a1bfe2ee1979ac407a5ed Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:44:19 +1100 Subject: [PATCH 37/78] Tweak send decorator syntax --- misc_docs/syntax/decorator_send.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_send.mdx b/misc_docs/syntax/decorator_send.mdx index 961f65362..e084931b9 100644 --- a/misc_docs/syntax/decorator_send.mdx +++ b/misc_docs/syntax/decorator_send.mdx @@ -12,7 +12,7 @@ For example: -```res +```re type element @scope("document") @val From 6f53ab3f01516c4fdface437480460fe032e2926 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:45:12 +1100 Subject: [PATCH 38/78] Tweak set index decorator syntax --- misc_docs/syntax/decorator_set_index.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/misc_docs/syntax/decorator_set_index.mdx b/misc_docs/syntax/decorator_set_index.mdx index bc7f7d68b..3e1f2fc9b 100644 --- a/misc_docs/syntax/decorator_set_index.mdx +++ b/misc_docs/syntax/decorator_set_index.mdx @@ -1,6 +1,6 @@ --- id: "set-index-decorator" -keywords: ["set", "decorator", "array", "object"] +keywords: ["set", "decorator", "array", "object", "index"] name: "@set_index" summary: "This is the `@set_index` decorator." category: "decorators" @@ -12,7 +12,7 @@ For example with an Array: -```res +```re type t @new external create: int => t = "Array" @@ -43,7 +43,7 @@ And an example with an object: -```res +```re type t @new external create: unit => t = "Object" From ff5f05e0b94d3500a04f1cdf1de4b1b27e2bf213 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:45:36 +1100 Subject: [PATCH 39/78] Tweak set decorator syntax --- misc_docs/syntax/decorator_set.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_set.mdx b/misc_docs/syntax/decorator_set.mdx index 430608437..7815a0972 100644 --- a/misc_docs/syntax/decorator_set.mdx +++ b/misc_docs/syntax/decorator_set.mdx @@ -12,7 +12,7 @@ For example: -```res +```re type element @scope("document") @val From f424dd0806f575882a58f0317042e153e23b9554 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:45:59 +1100 Subject: [PATCH 40/78] Tweak unwrap decorator syntax --- misc_docs/syntax/decorator_unwrap.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_unwrap.mdx b/misc_docs/syntax/decorator_unwrap.mdx index a488daadf..3078913a4 100644 --- a/misc_docs/syntax/decorator_unwrap.mdx +++ b/misc_docs/syntax/decorator_unwrap.mdx @@ -27,7 +27,7 @@ Here is how you'd bind to this function: -```res +```re @val external padLeft: ( @unwrap [#Int(int) | #Str(string)], string From ae11d2a023a761e5e6f47b2d3d91ae91ae6d19b1 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 13:46:26 +1100 Subject: [PATCH 41/78] Tweak val decorator syntax --- misc_docs/syntax/decorator_val.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_val.mdx b/misc_docs/syntax/decorator_val.mdx index fa13595a5..be6b326c9 100644 --- a/misc_docs/syntax/decorator_val.mdx +++ b/misc_docs/syntax/decorator_val.mdx @@ -12,7 +12,7 @@ For example: -```res +```re type timeoutID @val From 3af0c983ee36bd5a5b4939a95c52b5fc9eda8c74 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 18:01:53 +1100 Subject: [PATCH 42/78] Add deriving decorator syntax --- misc_docs/syntax/decorator_deriving.mdx | 202 ++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 misc_docs/syntax/decorator_deriving.mdx diff --git a/misc_docs/syntax/decorator_deriving.mdx b/misc_docs/syntax/decorator_deriving.mdx new file mode 100644 index 000000000..7987beec3 --- /dev/null +++ b/misc_docs/syntax/decorator_deriving.mdx @@ -0,0 +1,202 @@ +--- +id: "deriving-decorator" +keywords: ["deriving", "decorator", "record", "variant"] +name: "@deriving" +summary: "This is the `@deriving` decorator." +category: "decorators" +--- + +The `@deriving(accessors)` decorator can be used to either: + +* Generate getter functions for a decorated **record** type, or +* Generate creator functions for constructors of a **variant** type. + +The `@deriving(abstract)` decorator creates: + +* An abstract type representing the "abstract record". +* A creator function for the new abstract type, where labeled arguments represent the attributes of the record. +* A set of setter / getter functions for each record attribute + +Note that when using the `@deriving(abstract)` decorator, the original record type will be removed. +You'll need to use the newly created functions to create / get / set values of this type. + +Example of **record** accessors: + + + +```re +@deriving(accessors) +type person = { + name: string, + age: int, +} + +// This generates functions with signatures: +// let name: (person) => string; +// let age: (person) => int; + +let toString = (person): string => { + name(person) ++ " " ++ Belt.Int.toString(age(person)) +} + +let misha = { + name: "Misha", + age: 20, +} + +let result = toString(misha) +``` + +```js +function name(param) { + return param.name; +} + +function age(param) { + return param.age; +} + +function toString(person) { + return person.name + " " + String(person.age); +} + +var misha = { + name: "Misha", + age: 20, +}; + +var result = toString(misha); +``` + + + +Example of **variant** accessors: + + + +```re +@deriving(accessors) +type action = + | SetName(string) + | SetAge(int) + | ClearAll + +// This generates functions with signatures: +// let setName: (string) => action; +// let age: (person) => int; + +let dispatch = action => { + switch action { + | SetName(name) => Js.log2("SetName", name) + | SetAge(age) => Js.log2("SetAge", age) + | ClearAll => Js.log("ClearAll") + } +} + +dispatch(setName("Hello")) +dispatch(setAge(123)) +dispatch(clearAll) +``` + +```js +function setName(param_0) { + return { + TAG: /* SetName */ 0, + _0: param_0, + } +} + +function setAge(param_0) { + return { + TAG: /* SetAge */ 1, + _0: param_0, + } +} + +function dispatch(action) { + if (typeof action === "number") { + console.log("ClearAll") + return + } + if (action.TAG === /* SetName */ 0) { + console.log("SetName", action._0) + return + } + console.log("SetAge", action._0) +} + +dispatch({ + TAG: /* SetName */ 0, + _0: "Hello", +}) + +dispatch({ + TAG: /* SetAge */ 1, + _0: 123, +}) + +dispatch(/* ClearAll */ 0) + +var clearAll = /* ClearAll */ 0 +``` + + + +Example of **abstract record** type: + + + +```re +@deriving(abstract) +type person = { + name: string, + mutable age: int, // Use the mutable keyword for generating setters +} + +// Generates the following: +// +// An abstract type, replacing the original type: +// +// type person +// +// A type constructor: +// +// let person: (~name: string, ~age: int) => person +// +// Getters: +// +// let nameGet: (person) => string; +// let ageGet: (person) => int +// +// Setters (only mutable attributes) +// +// let ageSet: (person, int) => unit + +let friend = person(~name="Misha", ~age=20) + +Js.log(friend->nameGet) // => "Misha" + +// Increase age by 1 via mutation +friend->ageSet(friend->ageGet + 1) + +Js.log(friend->ageGet) // => 21 + +// This will NOT be possible (original type has been removed) +// let misha = {name: "Misha", age: 20} + +``` + +```js +var friend = { + name: "Misha", + age: 20 +}; + +console.log(friend.name); + +friend.age = friend.age + 1 | 0; + +console.log(friend.age); +``` + + \ No newline at end of file From 00e08c88da292d6d3d59fd042b11a98de0f235c8 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 18:08:32 +1100 Subject: [PATCH 43/78] Tweak as decorator syntax --- misc_docs/syntax/decorator_as.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/misc_docs/syntax/decorator_as.mdx b/misc_docs/syntax/decorator_as.mdx index b3ce3386d..8af24b1d9 100644 --- a/misc_docs/syntax/decorator_as.mdx +++ b/misc_docs/syntax/decorator_as.mdx @@ -30,3 +30,4 @@ var action = { +It may also be used when declaring external [polymorphic variants](/docs/manual/latest/polymorphic-variant). See the `@string` and `@int` decorators for more details. From ff607353b004be749e2bdb4eab2cad69e06acfbc Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 18:08:51 +1100 Subject: [PATCH 44/78] Tweak string decorator syntax --- misc_docs/syntax/decorator_string.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_string.mdx b/misc_docs/syntax/decorator_string.mdx index 94b51d79e..9dcfdb2e6 100644 --- a/misc_docs/syntax/decorator_string.mdx +++ b/misc_docs/syntax/decorator_string.mdx @@ -6,7 +6,7 @@ summary: "This is the `@string` decorator." category: "decorators" --- -The `@string` decorator can be used with polymorphic variants and the `@as` decorator on *externals* to modify the string values used for the variants in the compiled JavaScript. +The `@string` decorator can be used with [polymorphic variants](/docs/manual/latest/polymorphic-variant) and the `@as` decorator on *externals* to modify the string values used for the variants in the compiled JavaScript. For example: From 0f08e50ba1f2c23a68fa52c505403f9e434243fd Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 21:51:13 +1100 Subject: [PATCH 45/78] Add variadic decorator syntax --- misc_docs/syntax/decorator_variadic.mdx | 45 +++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 misc_docs/syntax/decorator_variadic.mdx diff --git a/misc_docs/syntax/decorator_variadic.mdx b/misc_docs/syntax/decorator_variadic.mdx new file mode 100644 index 000000000..115471acb --- /dev/null +++ b/misc_docs/syntax/decorator_variadic.mdx @@ -0,0 +1,45 @@ +--- +id: "variadic-decorator" +keywords: ["variadic", "decorator"] +name: "@variadic" +summary: "This is the `@variadic` decorator." +category: "decorators" +--- + +The `@variadic` decorator is used to model JavaScript functions that take a variable number of arguments, where all arguments are of the same type. + +For example: + + + +```re +@val @variadic @scope("Math") +external max: array => int = "max" + +let result = max([5, -2, 6, 1]) +``` + +```js +var result = Math.max(5, -2, 6, 1); +``` + + + +If your function has mandatory arguments, you can use the `@as` decorator to add them: + + + +```re +@val @variadic +external warn: (@as(404) _, @as("NOT_FOUND") _, array) => unit = "log" + +warn([]) +warn(["this", "page", "is", "not", "found"]) +``` + +```js +log(404, "NOT_FOUND"); +log(404, "NOT_FOUND", "this", "page", "is", "not", "found"); +``` + + From a225816b462601492a65101442fafc4175ebee6c Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 22:03:56 +1100 Subject: [PATCH 46/78] Add inline decorator syntax --- misc_docs/syntax/decorator_inline.mdx | 93 +++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 misc_docs/syntax/decorator_inline.mdx diff --git a/misc_docs/syntax/decorator_inline.mdx b/misc_docs/syntax/decorator_inline.mdx new file mode 100644 index 000000000..7d096a0bb --- /dev/null +++ b/misc_docs/syntax/decorator_inline.mdx @@ -0,0 +1,93 @@ +--- +id: "inline-decorator" +keywords: ["inline", "decorator", "constant"] +name: "@inline" +summary: "This is the `@inline` decorator." +category: "decorators" +--- + +The `@inline` decorator tells the compiler to copy (i.e. inline) its value in every place the binding is being used. This is especially useful for cases where string constants can't be used as variables, but need to be present as constant values. + +For example, consider the following code *without* the `@inline` decorator. + + + +```re +module Colors = { + let green = "green" + let red = "red" +} + +let allowedColors = [Colors.green, Colors.red] +``` + +```js +var green = "green"; +var red = "red"; + +var Colors = { + green: green, + red: red +}; + +var allowedColors = [ + green, + red +]; +``` + + + + +And compare *with* the `@inline` decorator. + + + +```re +module Colors = { + @inline + let green = "green" + + @inline + let red = "red" +} + +let allowedColors = [Colors.green, Colors.red] +``` + +```js +var allowedColors = [ + "green", + "red" +]; +``` + + + +A more advanced, but common use-case is to inline the `NODE_ENV` strings: + + + +```re +module NodeEnv = { + @val @scope("process.env") external env: string = "NODE_ENV" + + @inline + let development = "development" + + @inline + let production = "production" +} + +if NodeEnv.env === NodeEnv.development { + Js.log("development") +} +``` + +```js +if (process.env.NODE_ENV === "development") { + console.log("development"); +} +``` + + From 121831930f70d56bc12212a2933899a114de027d Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 22:17:14 +1100 Subject: [PATCH 47/78] Add meth decorator syntax --- misc_docs/syntax/decorator_meth.mdx | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 misc_docs/syntax/decorator_meth.mdx diff --git a/misc_docs/syntax/decorator_meth.mdx b/misc_docs/syntax/decorator_meth.mdx new file mode 100644 index 000000000..6db851873 --- /dev/null +++ b/misc_docs/syntax/decorator_meth.mdx @@ -0,0 +1,45 @@ +--- +id: "meth-decorator" +keywords: ["meth", "decorator", "object", "function"] +name: "@meth" +summary: "This is the `@meth` decorator." +category: "decorators" +--- + +The `@meth` decorator is used to call a function on a JavaScript object, and avoid issues with currying. + +For example, consider the following JavaScript code: + +```js +function say (a, b) { + console.log(a, b); +}; + +var john = { + say +}; +``` + +The shape of the john object could be typed and accessed as follows: + + + +```re +type person = {@meth "say": (string, string) => unit} + +@val external john: person = "john" + +john["say"]("hey", "jude") +``` + +```js +john.say("hey", "jude"); +``` + + + +Note that we are using the object property notation to access the method. + +If you omit the `@meth` decorator in the function signature, the type checker will error, because it is ensured by the compiler to enforce only fully applied functions in JavaScript objects. + + From fc454f59ed3d90c9fc6ea0a95172ae06134cf055 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 22:50:12 +1100 Subject: [PATCH 48/78] Add return decorator syntax --- misc_docs/syntax/decorator_return.mdx | 87 +++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 misc_docs/syntax/decorator_return.mdx diff --git a/misc_docs/syntax/decorator_return.mdx b/misc_docs/syntax/decorator_return.mdx new file mode 100644 index 000000000..0e07ee8e5 --- /dev/null +++ b/misc_docs/syntax/decorator_return.mdx @@ -0,0 +1,87 @@ +--- +id: "return-decorator" +keywords: ["return", "decorator", "null", "undefined"] +name: "@return" +summary: "This is the `@return` decorator." +category: "decorators" +--- + +The `@return` decorator is used to control how `null` and `undefined` values are converted to `option` types in ReScript. + +Consider the following code *without* the `@return` decorator: + + + + +```re +type element +type dom + +@send +external getElementById: (dom, string) => option = "getElementById" + +let test = dom => { + let elem = dom->getElementById("haha") + switch elem { + | None => "None: Only when value is undefined" + | Some(_) => "Some: When value is not undefined or is null" + } +} +``` + +```js +function test(dom) { + var elem = dom.getElementById("haha"); + if (elem !== undefined) { + return "Some: When value is not undefined or is null"; + } else { + return "None: Only when value is undefined"; + } +} +``` + + + +Here, `Some` can include `null` values. + +The `@return` decorator can specify how `null` and `undefined` are handled. + +There are four versions of the decorator: + +1. `@return(nullable)` converts `null` and `undefined` to `None`. +2. `@return(null_to_opt)` converts `null` to `None`. +3. `@return(undefined_to_opt)` converts `undefined` to `None`. +4. `@return(identity)` has the same behaviour as omitting the decorator. It is rarely used, but introduced here for debugging purposes. + +Example with `@return(nullable)`: + + + +```re +type element +type dom + +@send @return(nullable) +external getElementById: (dom, string) => option = "getElementById" + +let test = dom => { + let elem = dom->getElementById("haha") + switch elem { + | None => "None: When value is undefined or null" + | Some(_) => "Some: When value is not undefined and not null" + } +} +``` + +```js +function test(dom) { + var elem = dom.getElementById("haha"); + if (elem == null) { + return "None: When value is undefined or null"; + } else { + return "Some: When value is not undefined and not null"; + } +} +``` + + From 1c4325554a1f27127532831438723d7e20579d69 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 23:06:23 +1100 Subject: [PATCH 49/78] Enable wrapping of tags --- src/components/SyntaxLookupWidget.js | 6 ++++-- src/components/SyntaxLookupWidget.res | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/SyntaxLookupWidget.js b/src/components/SyntaxLookupWidget.js index d492d0f6f..7ce88606a 100644 --- a/src/components/SyntaxLookupWidget.js +++ b/src/components/SyntaxLookupWidget.js @@ -41,7 +41,9 @@ function SyntaxLookupWidget$Category(Props) { var children = Props.children; return React.createElement("div", undefined, React.createElement("h3", { className: "font-sans font-medium text-gray-100 tracking-wide text-14 uppercase mb-2" - }, title), React.createElement("div", undefined, children)); + }, title), React.createElement("div", { + className: "flex flex-wrap" + }, children)); } function toCategory(s) { @@ -275,7 +277,7 @@ function SyntaxLookupWidget(Props) { }; return React.createElement("span", { key: item.name, - className: "first:ml-0 ml-2 cursor-pointer", + className: "mr-2 mb-2 cursor-pointer", onMouseDown: onMouseDown }, React.createElement(SyntaxLookupWidget$Tag, { text: item.name diff --git a/src/components/SyntaxLookupWidget.res b/src/components/SyntaxLookupWidget.res index 7918f3938..ca5c8c3f3 100644 --- a/src/components/SyntaxLookupWidget.res +++ b/src/components/SyntaxLookupWidget.res @@ -49,7 +49,7 @@ module Category = {

{React.string(title)}

-
children
+
children
} } @@ -259,7 +259,7 @@ let make = () => { ReactEvent.Mouse.preventDefault(evt) setState(_ => ShowDetails(item)) } - + }) From 5e51a46b146a591d792ba022f3e8b32d106103dc Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 23:07:42 +1100 Subject: [PATCH 50/78] Update syntax lookup meta --- pages/syntax-lookup.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/syntax-lookup.mdx b/pages/syntax-lookup.mdx index a132ee277..39a5e8da7 100644 --- a/pages/syntax-lookup.mdx +++ b/pages/syntax-lookup.mdx @@ -1,7 +1,7 @@ --- title: "Syntax Lookup" -description: "Discover ReScript syntax constructs with our discovery tool" -canonical: "/docs/manual/latest/syntax-discovery" +description: "Discover ReScript syntax constructs with our lookup tool" +canonical: "/docs/manual/latest/syntax-lookup" --- import { make as SyntaxLookupWidget } from "src/components/SyntaxLookupWidget" From e8c8ba0dca01aa6d5742b5e1e23a768498e1d751 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Fri, 8 Jan 2021 23:54:50 +1100 Subject: [PATCH 51/78] Add unboxed decorator syntax --- misc_docs/syntax/decorator_unboxed.mdx | 58 ++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 misc_docs/syntax/decorator_unboxed.mdx diff --git a/misc_docs/syntax/decorator_unboxed.mdx b/misc_docs/syntax/decorator_unboxed.mdx new file mode 100644 index 000000000..bf49ae7bc --- /dev/null +++ b/misc_docs/syntax/decorator_unboxed.mdx @@ -0,0 +1,58 @@ +--- +id: "unboxed-decorator" +keywords: ["unboxed", "decorator"] +name: "@unboxed" +summary: "This is the `@unboxed` decorator." +category: "decorators" +--- + +The `@unboxed` decorator provides a way to unwrap **variant** constructors that have a *single* argument, or **record** objects that have a *single* field. + +For example, consider the following code: + + + +```re +type name = Name(string) +let studentName = Name("Joe") + +type greeting = {message: string} +let hi = {message: "hello!"} +``` + +```js +var studentName = /* Name */{ + _0: "Joe" +}; + +var hi = { + message: "hello!" +}; +``` + + + +When compiled to JavaScript, these values are represented as objects. + +If we now add the `@unboxed` decorator, the object wrappers are removed from the JavaScript output: + + + +```re +@unboxed +type name = Name(string) +let studentName = Name("Joe") + +@unboxed +type greeting = {message: string} +let hi = {message: "hello!"} +``` + +```js +var studentName = "Joe"; +var hi = "hello!"; +``` + + + +See the [Unboxed](/docs/manual/latest/unboxed) section for more details. From 520155f6234b8f80b4df44079ae29cb4957eb83b Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 07:23:34 +1100 Subject: [PATCH 52/78] Apply suggestions from code review Co-authored-by: Patrick Ecker --- misc_docs/syntax/decorator_as.mdx | 2 +- misc_docs/syntax/decorator_get.mdx | 2 ++ misc_docs/syntax/decorator_get_index.mdx | 3 ++- misc_docs/syntax/decorator_inline.mdx | 4 ++++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/misc_docs/syntax/decorator_as.mdx b/misc_docs/syntax/decorator_as.mdx index 8af24b1d9..cc4cf70ff 100644 --- a/misc_docs/syntax/decorator_as.mdx +++ b/misc_docs/syntax/decorator_as.mdx @@ -14,7 +14,7 @@ For example: -```re +```res type action = { @as("type") type_: string } diff --git a/misc_docs/syntax/decorator_get.mdx b/misc_docs/syntax/decorator_get.mdx index a5715fad6..a1a9bbc5c 100644 --- a/misc_docs/syntax/decorator_get.mdx +++ b/misc_docs/syntax/decorator_get.mdx @@ -32,4 +32,6 @@ var top = div.scrollTop +### References +- [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) diff --git a/misc_docs/syntax/decorator_get_index.mdx b/misc_docs/syntax/decorator_get_index.mdx index 45e27f587..dbcf21b6a 100644 --- a/misc_docs/syntax/decorator_get_index.mdx +++ b/misc_docs/syntax/decorator_get_index.mdx @@ -69,4 +69,5 @@ var value = o["y"]; ``` - +### References +- [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) diff --git a/misc_docs/syntax/decorator_inline.mdx b/misc_docs/syntax/decorator_inline.mdx index 7d096a0bb..541f46910 100644 --- a/misc_docs/syntax/decorator_inline.mdx +++ b/misc_docs/syntax/decorator_inline.mdx @@ -91,3 +91,7 @@ if (process.env.NODE_ENV === "development") { ``` + +### References + +- [Attribute (Decorator)](https://rescript-lang.org/docs/manual/latest/attribute) From 2bb206e04a20c5e90928f1a4ba5954ad146e8b6d Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 07:25:10 +1100 Subject: [PATCH 53/78] Replace "re" with "res" in code snippet types --- misc_docs/syntax/decorator_deriving.mdx | 6 +++--- misc_docs/syntax/decorator_get.mdx | 2 +- misc_docs/syntax/decorator_get_index.mdx | 4 ++-- misc_docs/syntax/decorator_inline.mdx | 6 +++--- misc_docs/syntax/decorator_int.mdx | 2 +- misc_docs/syntax/decorator_meth.mdx | 2 +- misc_docs/syntax/decorator_module.mdx | 2 +- misc_docs/syntax/decorator_new.mdx | 4 ++-- misc_docs/syntax/decorator_return.mdx | 4 ++-- misc_docs/syntax/decorator_scope.mdx | 2 +- misc_docs/syntax/decorator_send.mdx | 2 +- misc_docs/syntax/decorator_set.mdx | 2 +- misc_docs/syntax/decorator_set_index.mdx | 4 ++-- misc_docs/syntax/decorator_string.mdx | 2 +- misc_docs/syntax/decorator_unboxed.mdx | 4 ++-- misc_docs/syntax/decorator_unwrap.mdx | 2 +- misc_docs/syntax/decorator_val.mdx | 2 +- misc_docs/syntax/decorator_variadic.mdx | 4 ++-- 18 files changed, 28 insertions(+), 28 deletions(-) diff --git a/misc_docs/syntax/decorator_deriving.mdx b/misc_docs/syntax/decorator_deriving.mdx index 7987beec3..d32a60315 100644 --- a/misc_docs/syntax/decorator_deriving.mdx +++ b/misc_docs/syntax/decorator_deriving.mdx @@ -24,7 +24,7 @@ Example of **record** accessors: -```re +```res @deriving(accessors) type person = { name: string, @@ -74,7 +74,7 @@ Example of **variant** accessors: -```re +```res @deriving(accessors) type action = | SetName(string) @@ -146,7 +146,7 @@ Example of **abstract record** type: -```re +```res @deriving(abstract) type person = { name: string, diff --git a/misc_docs/syntax/decorator_get.mdx b/misc_docs/syntax/decorator_get.mdx index a1a9bbc5c..26e204017 100644 --- a/misc_docs/syntax/decorator_get.mdx +++ b/misc_docs/syntax/decorator_get.mdx @@ -12,7 +12,7 @@ For example: -```re +```res type element @scope("document") @val diff --git a/misc_docs/syntax/decorator_get_index.mdx b/misc_docs/syntax/decorator_get_index.mdx index dbcf21b6a..ef48a6545 100644 --- a/misc_docs/syntax/decorator_get_index.mdx +++ b/misc_docs/syntax/decorator_get_index.mdx @@ -12,7 +12,7 @@ For example with an Array: -```re +```res type t @new external create: int => t = "Array" @@ -43,7 +43,7 @@ And an example with an object: -```re +```res type t @new external create: unit => t = "Object" diff --git a/misc_docs/syntax/decorator_inline.mdx b/misc_docs/syntax/decorator_inline.mdx index 541f46910..105231d49 100644 --- a/misc_docs/syntax/decorator_inline.mdx +++ b/misc_docs/syntax/decorator_inline.mdx @@ -12,7 +12,7 @@ For example, consider the following code *without* the `@inline` decorator. -```re +```res module Colors = { let green = "green" let red = "red" @@ -43,7 +43,7 @@ And compare *with* the `@inline` decorator. -```re +```res module Colors = { @inline let green = "green" @@ -68,7 +68,7 @@ A more advanced, but common use-case is to inline the `NODE_ENV` strings: -```re +```res module NodeEnv = { @val @scope("process.env") external env: string = "NODE_ENV" diff --git a/misc_docs/syntax/decorator_int.mdx b/misc_docs/syntax/decorator_int.mdx index 6e83bc100..cc677a054 100644 --- a/misc_docs/syntax/decorator_int.mdx +++ b/misc_docs/syntax/decorator_int.mdx @@ -12,7 +12,7 @@ For example: -```re +```res @val external setStatus: @int[ @as(0) #NotStarted | @as(1) #Started | diff --git a/misc_docs/syntax/decorator_meth.mdx b/misc_docs/syntax/decorator_meth.mdx index 6db851873..4dadaa42c 100644 --- a/misc_docs/syntax/decorator_meth.mdx +++ b/misc_docs/syntax/decorator_meth.mdx @@ -24,7 +24,7 @@ The shape of the john object could be typed and accessed as follows: -```re +```res type person = {@meth "say": (string, string) => unit} @val external john: person = "john" diff --git a/misc_docs/syntax/decorator_module.mdx b/misc_docs/syntax/decorator_module.mdx index 56665fcae..d3fe1277b 100644 --- a/misc_docs/syntax/decorator_module.mdx +++ b/misc_docs/syntax/decorator_module.mdx @@ -12,7 +12,7 @@ For example: -```re +```res @module("path") external dirname: string => string = "dirname" diff --git a/misc_docs/syntax/decorator_new.mdx b/misc_docs/syntax/decorator_new.mdx index d2d3f58c8..a93a3b192 100644 --- a/misc_docs/syntax/decorator_new.mdx +++ b/misc_docs/syntax/decorator_new.mdx @@ -10,7 +10,7 @@ The `@new` decorator is used whenever you need to bind to a JavaScript class con -```re +```res type t @new external create: unit => t = "Date" @@ -28,7 +28,7 @@ When the object is not available on the global scope, combine it with `@module`: -```re +```res type t @module @new external book: unit => t = "Book" diff --git a/misc_docs/syntax/decorator_return.mdx b/misc_docs/syntax/decorator_return.mdx index 0e07ee8e5..ea9b77c48 100644 --- a/misc_docs/syntax/decorator_return.mdx +++ b/misc_docs/syntax/decorator_return.mdx @@ -13,7 +13,7 @@ Consider the following code *without* the `@return` decorator: -```re +```res type element type dom @@ -57,7 +57,7 @@ Example with `@return(nullable)`: -```re +```res type element type dom diff --git a/misc_docs/syntax/decorator_scope.mdx b/misc_docs/syntax/decorator_scope.mdx index ce2b8438c..d354886a6 100644 --- a/misc_docs/syntax/decorator_scope.mdx +++ b/misc_docs/syntax/decorator_scope.mdx @@ -12,7 +12,7 @@ For example: -```re +```res @scope("Math") @val external floor: float => int = "floor" diff --git a/misc_docs/syntax/decorator_send.mdx b/misc_docs/syntax/decorator_send.mdx index e084931b9..961f65362 100644 --- a/misc_docs/syntax/decorator_send.mdx +++ b/misc_docs/syntax/decorator_send.mdx @@ -12,7 +12,7 @@ For example: -```re +```res type element @scope("document") @val diff --git a/misc_docs/syntax/decorator_set.mdx b/misc_docs/syntax/decorator_set.mdx index 7815a0972..430608437 100644 --- a/misc_docs/syntax/decorator_set.mdx +++ b/misc_docs/syntax/decorator_set.mdx @@ -12,7 +12,7 @@ For example: -```re +```res type element @scope("document") @val diff --git a/misc_docs/syntax/decorator_set_index.mdx b/misc_docs/syntax/decorator_set_index.mdx index 3e1f2fc9b..c79e71dd2 100644 --- a/misc_docs/syntax/decorator_set_index.mdx +++ b/misc_docs/syntax/decorator_set_index.mdx @@ -12,7 +12,7 @@ For example with an Array: -```re +```res type t @new external create: int => t = "Array" @@ -43,7 +43,7 @@ And an example with an object: -```re +```res type t @new external create: unit => t = "Object" diff --git a/misc_docs/syntax/decorator_string.mdx b/misc_docs/syntax/decorator_string.mdx index 9dcfdb2e6..6594b98c5 100644 --- a/misc_docs/syntax/decorator_string.mdx +++ b/misc_docs/syntax/decorator_string.mdx @@ -12,7 +12,7 @@ For example: -```re +```res @val external setStatus: @string[ @as("NOT_STARTED") #NotStarted | @as("STARTED") #Started | diff --git a/misc_docs/syntax/decorator_unboxed.mdx b/misc_docs/syntax/decorator_unboxed.mdx index bf49ae7bc..5efe495e0 100644 --- a/misc_docs/syntax/decorator_unboxed.mdx +++ b/misc_docs/syntax/decorator_unboxed.mdx @@ -12,7 +12,7 @@ For example, consider the following code: -```re +```res type name = Name(string) let studentName = Name("Joe") @@ -38,7 +38,7 @@ If we now add the `@unboxed` decorator, the object wrappers are removed from the -```re +```res @unboxed type name = Name(string) let studentName = Name("Joe") diff --git a/misc_docs/syntax/decorator_unwrap.mdx b/misc_docs/syntax/decorator_unwrap.mdx index 3078913a4..a488daadf 100644 --- a/misc_docs/syntax/decorator_unwrap.mdx +++ b/misc_docs/syntax/decorator_unwrap.mdx @@ -27,7 +27,7 @@ Here is how you'd bind to this function: -```re +```res @val external padLeft: ( @unwrap [#Int(int) | #Str(string)], string diff --git a/misc_docs/syntax/decorator_val.mdx b/misc_docs/syntax/decorator_val.mdx index be6b326c9..fa13595a5 100644 --- a/misc_docs/syntax/decorator_val.mdx +++ b/misc_docs/syntax/decorator_val.mdx @@ -12,7 +12,7 @@ For example: -```re +```res type timeoutID @val diff --git a/misc_docs/syntax/decorator_variadic.mdx b/misc_docs/syntax/decorator_variadic.mdx index 115471acb..4e9dcc1ae 100644 --- a/misc_docs/syntax/decorator_variadic.mdx +++ b/misc_docs/syntax/decorator_variadic.mdx @@ -12,7 +12,7 @@ For example: -```re +```res @val @variadic @scope("Math") external max: array => int = "max" @@ -29,7 +29,7 @@ If your function has mandatory arguments, you can use the `@as` decorator to add -```re +```res @val @variadic external warn: (@as(404) _, @as("NOT_FOUND") _, array) => unit = "log" From 6cc597eb2eb16ae19a43eb95af9404a9283193ab Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 13:55:14 +1100 Subject: [PATCH 54/78] Tweak as decorator --- misc_docs/syntax/decorator_as.mdx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/misc_docs/syntax/decorator_as.mdx b/misc_docs/syntax/decorator_as.mdx index cc4cf70ff..b888b00c9 100644 --- a/misc_docs/syntax/decorator_as.mdx +++ b/misc_docs/syntax/decorator_as.mdx @@ -6,9 +6,9 @@ summary: "This is the `@as` decorator." category: "decorators" --- -The `@as` decorator may be used on record types to alias record field names to a different JavaScript attribute name. +The `@as` decorator is commonly used on record types to alias record field names to a different JavaScript attribute name. -This is mostly useful to map to JavaScript attribute names that cannot be expressed in ReScript (such as keywords). +This is useful to map to JavaScript attribute names that cannot be expressed in ReScript (such as keywords). For example: @@ -30,4 +30,13 @@ var action = { -It may also be used when declaring external [polymorphic variants](/docs/manual/latest/polymorphic-variant). See the `@string` and `@int` decorators for more details. +### References + +* [Constrain Arguments Better](/docs/manual/latest/bind-to-js-function#constrain-arguments-better) describes aliasing polymorphic variants using the `@as` decorator. +* [Fixed Arguments](/docs/manual/latest/bind-to-js-function#fixed-arguments) describes passing predetermined argument values to JavaScript functions using the `@as` decorator. + +### Related + +* `@int` +* `@string` +* `@variadic` From 037a8a1ac0b3cfb537c53fda61fe8555243153b8 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 13:58:34 +1100 Subject: [PATCH 55/78] Tweak as decorator --- misc_docs/syntax/decorator_as.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc_docs/syntax/decorator_as.mdx b/misc_docs/syntax/decorator_as.mdx index b888b00c9..31b873ee5 100644 --- a/misc_docs/syntax/decorator_as.mdx +++ b/misc_docs/syntax/decorator_as.mdx @@ -32,8 +32,8 @@ var action = { ### References -* [Constrain Arguments Better](/docs/manual/latest/bind-to-js-function#constrain-arguments-better) describes aliasing polymorphic variants using the `@as` decorator. -* [Fixed Arguments](/docs/manual/latest/bind-to-js-function#fixed-arguments) describes passing predetermined argument values to JavaScript functions using the `@as` decorator. +* [Constrain Arguments Better](/docs/manual/latest/bind-to-js-function#constrain-arguments-better) +* [Fixed Arguments](/docs/manual/latest/bind-to-js-function#fixed-arguments) ### Related From bf26f7ec270c871c1aba28293b5fbf87e14b09d9 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 14:30:45 +1100 Subject: [PATCH 56/78] Simplify the deriving decorator --- misc_docs/syntax/decorator_deriving.mdx | 192 +++--------------------- 1 file changed, 21 insertions(+), 171 deletions(-) diff --git a/misc_docs/syntax/decorator_deriving.mdx b/misc_docs/syntax/decorator_deriving.mdx index d32a60315..97dd92ce1 100644 --- a/misc_docs/syntax/decorator_deriving.mdx +++ b/misc_docs/syntax/decorator_deriving.mdx @@ -1,202 +1,52 @@ --- id: "deriving-decorator" -keywords: ["deriving", "decorator", "record", "variant"] +keywords: ["deriving", "decorator", "record"] name: "@deriving" summary: "This is the `@deriving` decorator." category: "decorators" --- -The `@deriving(accessors)` decorator can be used to either: +When the `@deriving` decorator is applied to a **record** type, +it expands the type into a factory function plus a set of +getter/setter functions for it's fields. -* Generate getter functions for a decorated **record** type, or -* Generate creator functions for constructors of a **variant** type. +> Note that this is an outdated decorator and you may no longer need to use it. +> See [Convert Record Type to Abstract Record](/docs/manual/latest/generate-converters-accessors#convert-record-type-to-abstract-record) for more details. -The `@deriving(abstract)` decorator creates: - -* An abstract type representing the "abstract record". -* A creator function for the new abstract type, where labeled arguments represent the attributes of the record. -* A set of setter / getter functions for each record attribute - -Note that when using the `@deriving(abstract)` decorator, the original record type will be removed. -You'll need to use the newly created functions to create / get / set values of this type. - -Example of **record** accessors: +### Example ```res -@deriving(accessors) +@deriving(abstract) type person = { name: string, age: int, + job: string, } -// This generates functions with signatures: -// let name: (person) => string; -// let age: (person) => int; - -let toString = (person): string => { - name(person) ++ " " ++ Belt.Int.toString(age(person)) -} - -let misha = { - name: "Misha", - age: 20, -} +let joe = person(~name="Joe", ~age=20, ~job="teacher") -let result = toString(misha) +let joeName = nameGet(joe) +let joeAge = ageGet(joe) +let joeJob = jobGet(joe) ``` ```js -function name(param) { - return param.name; -} - -function age(param) { - return param.age; -} - -function toString(person) { - return person.name + " " + String(person.age); -} - -var misha = { - name: "Misha", +var joe = { + name: "Joe", age: 20, + job: "teacher" }; -var result = toString(misha); +var joeName = joe.name; +var joeAge = joe.age; +var joeJob = joe.job; ``` -Example of **variant** accessors: - - - -```res -@deriving(accessors) -type action = - | SetName(string) - | SetAge(int) - | ClearAll - -// This generates functions with signatures: -// let setName: (string) => action; -// let age: (person) => int; - -let dispatch = action => { - switch action { - | SetName(name) => Js.log2("SetName", name) - | SetAge(age) => Js.log2("SetAge", age) - | ClearAll => Js.log("ClearAll") - } -} - -dispatch(setName("Hello")) -dispatch(setAge(123)) -dispatch(clearAll) -``` - -```js -function setName(param_0) { - return { - TAG: /* SetName */ 0, - _0: param_0, - } -} - -function setAge(param_0) { - return { - TAG: /* SetAge */ 1, - _0: param_0, - } -} - -function dispatch(action) { - if (typeof action === "number") { - console.log("ClearAll") - return - } - if (action.TAG === /* SetName */ 0) { - console.log("SetName", action._0) - return - } - console.log("SetAge", action._0) -} +### References -dispatch({ - TAG: /* SetName */ 0, - _0: "Hello", -}) - -dispatch({ - TAG: /* SetAge */ 1, - _0: 123, -}) - -dispatch(/* ClearAll */ 0) - -var clearAll = /* ClearAll */ 0 -``` - - - -Example of **abstract record** type: - - - -```res -@deriving(abstract) -type person = { - name: string, - mutable age: int, // Use the mutable keyword for generating setters -} - -// Generates the following: -// -// An abstract type, replacing the original type: -// -// type person -// -// A type constructor: -// -// let person: (~name: string, ~age: int) => person -// -// Getters: -// -// let nameGet: (person) => string; -// let ageGet: (person) => int -// -// Setters (only mutable attributes) -// -// let ageSet: (person, int) => unit - -let friend = person(~name="Misha", ~age=20) - -Js.log(friend->nameGet) // => "Misha" - -// Increase age by 1 via mutation -friend->ageSet(friend->ageGet + 1) - -Js.log(friend->ageGet) // => 21 - -// This will NOT be possible (original type has been removed) -// let misha = {name: "Misha", age: 20} - -``` - -```js -var friend = { - name: "Misha", - age: 20 -}; - -console.log(friend.name); - -friend.age = friend.age + 1 | 0; - -console.log(friend.age); -``` +* [Convert Record Type to Abstract Record](/docs/manual/latest/generate-converters-accessors#convert-record-type-to-abstract-record) - \ No newline at end of file From b5ece0962ebb5f3cdf917845270ffef39c50b50a Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 14:31:45 +1100 Subject: [PATCH 57/78] Tweak as decorator formatting --- misc_docs/syntax/decorator_as.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_as.mdx b/misc_docs/syntax/decorator_as.mdx index 31b873ee5..644be25ea 100644 --- a/misc_docs/syntax/decorator_as.mdx +++ b/misc_docs/syntax/decorator_as.mdx @@ -10,7 +10,7 @@ The `@as` decorator is commonly used on record types to alias record field names This is useful to map to JavaScript attribute names that cannot be expressed in ReScript (such as keywords). -For example: +### Example From 8de8283916007b0c55a2898049a1b266c7b8317c Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:25:55 +1100 Subject: [PATCH 58/78] Update get and set decorators --- misc_docs/syntax/decorator_get.mdx | 8 ++++- misc_docs/syntax/decorator_get_index.mdx | 44 ++++++----------------- misc_docs/syntax/decorator_set.mdx | 8 +++++ misc_docs/syntax/decorator_set_index.mdx | 45 +++++++----------------- 4 files changed, 38 insertions(+), 67 deletions(-) diff --git a/misc_docs/syntax/decorator_get.mdx b/misc_docs/syntax/decorator_get.mdx index 26e204017..c5a572fe6 100644 --- a/misc_docs/syntax/decorator_get.mdx +++ b/misc_docs/syntax/decorator_get.mdx @@ -8,7 +8,7 @@ category: "decorators" The `@get` decorator is used to bind to a property of an object. -For example: +### Example @@ -35,3 +35,9 @@ var top = div.scrollTop ### References - [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) + +### Related + +- `@set` +- `@get_index` +- `@set_index` diff --git a/misc_docs/syntax/decorator_get_index.mdx b/misc_docs/syntax/decorator_get_index.mdx index ef48a6545..205b4be03 100644 --- a/misc_docs/syntax/decorator_get_index.mdx +++ b/misc_docs/syntax/decorator_get_index.mdx @@ -6,40 +6,10 @@ summary: "This is the `@get_index` decorator." category: "decorators" --- -The `@get_index` decorator is used to access a dynamic property or index. +The `@get_index` decorator is used to access a dynamic property on an object, +or an index of an array. -For example with an Array: - - - -```res -type t - -@new external create: int => t = "Array" -@set_index external set: (t, int, string) => unit = "" -@get_index external get: (t, int) => string = "" - -let a = create(3) -a->set(0, "zero") -a->set(1, "one") -a->set(2, "two") - -let value = a->get(1) -``` - -```js -var a = new Array(3); - -a[0] = "zero"; -a[1] = "one"; -a[2] = "two"; - -var value = a[1]; -``` - - - -And an example with an object: +### Example @@ -69,5 +39,13 @@ var value = o["y"]; ``` + ### References + - [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) + +### Related + +- `@get` +- `@set` +- `@set_index` diff --git a/misc_docs/syntax/decorator_set.mdx b/misc_docs/syntax/decorator_set.mdx index 430608437..062aac0ed 100644 --- a/misc_docs/syntax/decorator_set.mdx +++ b/misc_docs/syntax/decorator_set.mdx @@ -33,4 +33,12 @@ div.scrollTop = 100 +### References +- [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) + +### Related + +- `@get` +- `@set_index` +- `@get_index` diff --git a/misc_docs/syntax/decorator_set_index.mdx b/misc_docs/syntax/decorator_set_index.mdx index c79e71dd2..3c1ca386b 100644 --- a/misc_docs/syntax/decorator_set_index.mdx +++ b/misc_docs/syntax/decorator_set_index.mdx @@ -6,40 +6,10 @@ summary: "This is the `@set_index` decorator." category: "decorators" --- -The `@set_index` decorator is used to set a dynamic property or index. +The `@set_index` decorator is used to set a dynamic property on an object, +or an index of an array. -For example with an Array: - - - -```res -type t - -@new external create: int => t = "Array" -@set_index external set: (t, int, string) => unit = "" -@get_index external get: (t, int) => string = "" - -let a = create(3) -a->set(0, "zero") -a->set(1, "one") -a->set(2, "two") - -let value = a->get(1) -``` - -```js -var a = new Array(3); - -a[0] = "zero"; -a[1] = "one"; -a[2] = "two"; - -var value = a[1]; -``` - - - -And an example with an object: +### Example @@ -70,3 +40,12 @@ var value = o["y"]; +### References + +- [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) + +### Related + +- `@get` +- `@set` +- `@get_index` From 3a2f7f48468343633c045aa7a43840b418141c31 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:30:31 +1100 Subject: [PATCH 59/78] Update inline decorator --- misc_docs/syntax/decorator_inline.mdx | 66 ++------------------------- 1 file changed, 4 insertions(+), 62 deletions(-) diff --git a/misc_docs/syntax/decorator_inline.mdx b/misc_docs/syntax/decorator_inline.mdx index 105231d49..4bdab6c34 100644 --- a/misc_docs/syntax/decorator_inline.mdx +++ b/misc_docs/syntax/decorator_inline.mdx @@ -6,40 +6,10 @@ summary: "This is the `@inline` decorator." category: "decorators" --- -The `@inline` decorator tells the compiler to copy (i.e. inline) its value in every place the binding is being used. This is especially useful for cases where string constants can't be used as variables, but need to be present as constant values. +The `@inline` decorator tells the compiler to inline its value +in every place the binding is being used, rather than use a variable. -For example, consider the following code *without* the `@inline` decorator. - - - -```res -module Colors = { - let green = "green" - let red = "red" -} - -let allowedColors = [Colors.green, Colors.red] -``` - -```js -var green = "green"; -var red = "red"; - -var Colors = { - green: green, - red: red -}; - -var allowedColors = [ - green, - red -]; -``` - - - - -And compare *with* the `@inline` decorator. +### Example @@ -64,34 +34,6 @@ var allowedColors = [ -A more advanced, but common use-case is to inline the `NODE_ENV` strings: - - - -```res -module NodeEnv = { - @val @scope("process.env") external env: string = "NODE_ENV" - - @inline - let development = "development" - - @inline - let production = "production" -} - -if NodeEnv.env === NodeEnv.development { - Js.log("development") -} -``` - -```js -if (process.env.NODE_ENV === "development") { - console.log("development"); -} -``` - - - ### References -- [Attribute (Decorator)](https://rescript-lang.org/docs/manual/latest/attribute) +- [Inlining Constants](/docs/manual/latest/inlining-constants) From 06845753f7bb14f9b4e35c4de8d6caf4b09f2f17 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:32:59 +1100 Subject: [PATCH 60/78] Update int decorator --- misc_docs/syntax/decorator_int.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_int.mdx b/misc_docs/syntax/decorator_int.mdx index cc677a054..ec8cf84c3 100644 --- a/misc_docs/syntax/decorator_int.mdx +++ b/misc_docs/syntax/decorator_int.mdx @@ -8,7 +8,7 @@ category: "decorators" The `@int` decorator can be used with [polymorphic variants](/docs/manual/latest/polymorphic-variant) and the `@as` decorator on *externals* to modify the compiled JavaScript to use integers for the values instead of strings. -For example: +### Example @@ -27,3 +27,5 @@ setStatus(2); ``` + + From 98b316d93c8465eb1d90fe4da9e6a58577d96582 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:36:38 +1100 Subject: [PATCH 61/78] Simplify meth decorator --- misc_docs/syntax/decorator_meth.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/misc_docs/syntax/decorator_meth.mdx b/misc_docs/syntax/decorator_meth.mdx index 4dadaa42c..2a054e1d0 100644 --- a/misc_docs/syntax/decorator_meth.mdx +++ b/misc_docs/syntax/decorator_meth.mdx @@ -6,9 +6,12 @@ summary: "This is the `@meth` decorator." category: "decorators" --- -The `@meth` decorator is used to call a function on a JavaScript object, and avoid issues with currying. +The `@meth` decorator is used to call a function on a JavaScript object, +and avoid issues with currying. -For example, consider the following JavaScript code: +### Example + +Suppose we have the following JavaScript: ```js function say (a, b) { @@ -20,7 +23,7 @@ var john = { }; ``` -The shape of the john object could be typed and accessed as follows: +We can model and bind to this object as follows. @@ -38,8 +41,5 @@ john.say("hey", "jude"); -Note that we are using the object property notation to access the method. - -If you omit the `@meth` decorator in the function signature, the type checker will error, because it is ensured by the compiler to enforce only fully applied functions in JavaScript objects. From e248f6dacf498d0ff0a554ac145b77157edbb2db Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:38:00 +1100 Subject: [PATCH 62/78] Update module decorator --- misc_docs/syntax/decorator_module.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/misc_docs/syntax/decorator_module.mdx b/misc_docs/syntax/decorator_module.mdx index d3fe1277b..70bcf7cf0 100644 --- a/misc_docs/syntax/decorator_module.mdx +++ b/misc_docs/syntax/decorator_module.mdx @@ -8,7 +8,7 @@ category: "decorators" The `@module` decorator is used to bind to a JavaScript module. -For example: +### Example @@ -27,4 +27,6 @@ var root = Path.dirname("/User/github"); -See the [Import from JavaScript](/docs/manual/latest/import-from-export-to-js#import-from-javascript) section for full details, including other variations of how this decorator may be used. +### References + +* [Import from JavaScript](/docs/manual/latest/import-from-export-to-js#import-from-javascript) From f634206be9b3ece8d86cc63811e1ed03131fa66c Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:40:08 +1100 Subject: [PATCH 63/78] Simplify new decorator --- misc_docs/syntax/decorator_new.mdx | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/misc_docs/syntax/decorator_new.mdx b/misc_docs/syntax/decorator_new.mdx index a93a3b192..6b57d5d5d 100644 --- a/misc_docs/syntax/decorator_new.mdx +++ b/misc_docs/syntax/decorator_new.mdx @@ -6,7 +6,10 @@ summary: "This is the `@new` decorator." category: "decorators" --- -The `@new` decorator is used whenever you need to bind to a JavaScript class constructor that requires the `new` keword for instantiation. +The `@new` decorator is used whenever you need to bind to a JavaScript +class constructor that requires the `new` keword for instantiation. + +### Example @@ -24,21 +27,6 @@ var now = new Date(); -When the object is not available on the global scope, combine it with `@module`: - - - -```res -type t - -@module @new external book: unit => t = "Book" +### References -let myBook = book() -``` - -```js -var Book = require("Book"); -var myBook = new Book(); -``` - - +* [Bind to a JS Object That's a Class](/docs/manual/latest/bind-to-js-object#bind-to-a-js-object-thats-a-class) \ No newline at end of file From 8d58c6c1fd17399ab31a9dd95bb303be19297f69 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:42:59 +1100 Subject: [PATCH 64/78] Simplify return decorator --- misc_docs/syntax/decorator_return.mdx | 58 +++++---------------------- 1 file changed, 9 insertions(+), 49 deletions(-) diff --git a/misc_docs/syntax/decorator_return.mdx b/misc_docs/syntax/decorator_return.mdx index ea9b77c48..3f9337dca 100644 --- a/misc_docs/syntax/decorator_return.mdx +++ b/misc_docs/syntax/decorator_return.mdx @@ -8,52 +8,8 @@ category: "decorators" The `@return` decorator is used to control how `null` and `undefined` values are converted to `option` types in ReScript. -Consider the following code *without* the `@return` decorator: - - - -```res -type element -type dom - -@send -external getElementById: (dom, string) => option = "getElementById" - -let test = dom => { - let elem = dom->getElementById("haha") - switch elem { - | None => "None: Only when value is undefined" - | Some(_) => "Some: When value is not undefined or is null" - } -} -``` - -```js -function test(dom) { - var elem = dom.getElementById("haha"); - if (elem !== undefined) { - return "Some: When value is not undefined or is null"; - } else { - return "None: Only when value is undefined"; - } -} -``` - - - -Here, `Some` can include `null` values. - -The `@return` decorator can specify how `null` and `undefined` are handled. - -There are four versions of the decorator: - -1. `@return(nullable)` converts `null` and `undefined` to `None`. -2. `@return(null_to_opt)` converts `null` to `None`. -3. `@return(undefined_to_opt)` converts `undefined` to `None`. -4. `@return(identity)` has the same behaviour as omitting the decorator. It is rarely used, but introduced here for debugging purposes. - -Example with `@return(nullable)`: +### Example @@ -67,8 +23,8 @@ external getElementById: (dom, string) => option = "getElementById" let test = dom => { let elem = dom->getElementById("haha") switch elem { - | None => "None: When value is undefined or null" - | Some(_) => "Some: When value is not undefined and not null" + | None => 1 + | Some(_) => 2 } } ``` @@ -77,11 +33,15 @@ let test = dom => { function test(dom) { var elem = dom.getElementById("haha"); if (elem == null) { - return "None: When value is undefined or null"; + return 1; } else { - return "Some: When value is not undefined and not null"; + return 2; } } ``` + +### References + +* [Function Nullable Return Value Wrapping](/docs/manual/latest/bind-to-js-function#function-nullable-return-value-wrapping) \ No newline at end of file From c764884167c6a337e9f04883e691769ddfd3826b Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:49:49 +1100 Subject: [PATCH 65/78] Update scope decorator --- misc_docs/syntax/decorator_scope.mdx | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/misc_docs/syntax/decorator_scope.mdx b/misc_docs/syntax/decorator_scope.mdx index d354886a6..4a9f8af76 100644 --- a/misc_docs/syntax/decorator_scope.mdx +++ b/misc_docs/syntax/decorator_scope.mdx @@ -8,7 +8,7 @@ category: "decorators" The `@scope` decorator is used with other decorators such as `@val` and `@module` to declare a parent scope for the binding. -For example: +### Example @@ -16,25 +16,15 @@ For example: @scope("Math") @val external floor: float => int = "floor" -@scope(("location", "origin")) @val -external originLength: string = "length" - -@module("MyModule") @scope("CONSTANTS") -external initialDays: int = "initialDays" - -Js.log(floor(3.4)) -Js.log(originLength) -Js.log(initialDays) +let result = floor(3.4) ``` ```js -var MyModule = require("MyModule") - -console.log(Math.floor(3.4)) -console.log(location.origin.length) -console.log(MyModule.CONSTANTS.initialDays) +var result = Math.floor(3.4); ``` -Note that the order of the decorators doesn't matter. \ No newline at end of file +### References + +* [Global Modules](/docs/manual/latest/bind-to-global-js-values#global-modules) \ No newline at end of file From 0be53130939f0ed4ff7e58e579c36011cc303601 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:55:11 +1100 Subject: [PATCH 66/78] Update send decorator --- misc_docs/syntax/decorator_send.mdx | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/misc_docs/syntax/decorator_send.mdx b/misc_docs/syntax/decorator_send.mdx index 961f65362..bae452ce5 100644 --- a/misc_docs/syntax/decorator_send.mdx +++ b/misc_docs/syntax/decorator_send.mdx @@ -6,35 +6,26 @@ summary: "This is the `@send` decorator." category: "decorators" --- -The `@send` decorator is used to call a function on an object. +The `@send` decorator is used to bind to a method on an object. -For example: +### Example ```res -type element +type document +@bs.send external getElementById: (document, string) => Dom.element = "getElementById" +@bs.val external doc: document = "document" -@scope("document") @val -external createElement: string => element = "createElement" - -@send -external appendChild: (element, element) => element = "appendChild" - -let div = createElement("div") -let button = createElement("button") - -let _ = appendChild(div, button) +let el = getElementById(doc, "myId") ``` ```js -var div = document.createElement("div"); - -var button = document.createElement("button"); - -div.appendChild(button); +var el = document.getElementById("myId"); ``` +### References +* [Bind to JS Function](/docs/manual/latest/bind-to-js-function) \ No newline at end of file From 7598d8640ecb90599aa376d9f878602bec9eac04 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 15:58:26 +1100 Subject: [PATCH 67/78] Update string and int decorators --- misc_docs/syntax/decorator_int.mdx | 4 ++++ misc_docs/syntax/decorator_string.mdx | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_int.mdx b/misc_docs/syntax/decorator_int.mdx index ec8cf84c3..07031a067 100644 --- a/misc_docs/syntax/decorator_int.mdx +++ b/misc_docs/syntax/decorator_int.mdx @@ -28,4 +28,8 @@ setStatus(2); +### References + +* [Constrain Arguments Better](/docs/manual/latest/bind-to-js-function#constrain-arguments-better) + diff --git a/misc_docs/syntax/decorator_string.mdx b/misc_docs/syntax/decorator_string.mdx index 6594b98c5..1522e66ea 100644 --- a/misc_docs/syntax/decorator_string.mdx +++ b/misc_docs/syntax/decorator_string.mdx @@ -8,7 +8,7 @@ category: "decorators" The `@string` decorator can be used with [polymorphic variants](/docs/manual/latest/polymorphic-variant) and the `@as` decorator on *externals* to modify the string values used for the variants in the compiled JavaScript. -For example: +### Example @@ -27,3 +27,7 @@ setStatus("NOT_STARTED"); ``` + +### References + +* [Constrain Arguments Better](/docs/manual/latest/bind-to-js-function#constrain-arguments-better) \ No newline at end of file From 3a779bfabb24fed35f953cd2d1bfb4ca0248bdac Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 16:00:13 +1100 Subject: [PATCH 68/78] Update unboxed --- misc_docs/syntax/decorator_unboxed.mdx | 35 +++++--------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/misc_docs/syntax/decorator_unboxed.mdx b/misc_docs/syntax/decorator_unboxed.mdx index 5efe495e0..4eb9c7c89 100644 --- a/misc_docs/syntax/decorator_unboxed.mdx +++ b/misc_docs/syntax/decorator_unboxed.mdx @@ -6,35 +6,10 @@ summary: "This is the `@unboxed` decorator." category: "decorators" --- -The `@unboxed` decorator provides a way to unwrap **variant** constructors that have a *single* argument, or **record** objects that have a *single* field. +The `@unboxed` decorator provides a way to unwrap **variant** constructors +that have a *single* argument, or **record** objects that have a *single* field. -For example, consider the following code: - - - -```res -type name = Name(string) -let studentName = Name("Joe") - -type greeting = {message: string} -let hi = {message: "hello!"} -``` - -```js -var studentName = /* Name */{ - _0: "Joe" -}; - -var hi = { - message: "hello!" -}; -``` - - - -When compiled to JavaScript, these values are represented as objects. - -If we now add the `@unboxed` decorator, the object wrappers are removed from the JavaScript output: +### Example @@ -55,4 +30,6 @@ var hi = "hello!"; -See the [Unboxed](/docs/manual/latest/unboxed) section for more details. +### References + +* [Unboxed](/docs/manual/latest/unboxed) \ No newline at end of file From 43e81dc117ceada31a02aa9dd2214a17a7118147 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 16:05:17 +1100 Subject: [PATCH 69/78] Update unwrap decorator --- misc_docs/syntax/decorator_unwrap.mdx | 33 ++++++++------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/misc_docs/syntax/decorator_unwrap.mdx b/misc_docs/syntax/decorator_unwrap.mdx index a488daadf..1b65d7737 100644 --- a/misc_docs/syntax/decorator_unwrap.mdx +++ b/misc_docs/syntax/decorator_unwrap.mdx @@ -6,24 +6,10 @@ summary: "This is the `@unwrap` decorator." category: "decorators" --- -The `@unwrap` decorator may be used when binding to external functions that accept multiple types for an argument. +The `@unwrap` decorator may be used when binding to external functions +that accept multiple types for an argument. -Consider the following JavaScript function: - -```js -function padLeft(padding, str) { - if (typeof padding === "number") { - return " ".repeat(padding) + str; - } - if (typeof padding === "string") { - return padding + str; - } - throw new Error("Expected padding to be number or string"); -} -``` -Note how `padding` can be either a number or a string. - -Here is how you'd bind to this function: +### Example @@ -33,16 +19,17 @@ Here is how you'd bind to this function: string ) => string = "padLeft"; -let _ = padLeft(#Int(7), "eleven"); -let _ = padLeft(#Str("7"), "eleven"); +let result1 = padLeft(#Int(7), "eleven"); +let result2 = padLeft(#Str("7"), "eleven"); ``` ```js -padLeft(7, "eleven"); - -padLeft("7", "eleven"); +var result1 = padLeft(7, "eleven"); +var result2 = padLeft("7", "eleven"); ``` -Review the JavaScript output and note how `@unwrap` simply unwraps the polymorphic variant constructor. +### References + +* [Modeling Polymorphic Function](/docs/manual/latest/bind-to-js-function#modeling-polymorphic-function) \ No newline at end of file From 1d029535d27bc3d068235653b934babd8f6266cf Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 16:08:42 +1100 Subject: [PATCH 70/78] Update val decorator --- misc_docs/syntax/decorator_val.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/misc_docs/syntax/decorator_val.mdx b/misc_docs/syntax/decorator_val.mdx index fa13595a5..71c9babbd 100644 --- a/misc_docs/syntax/decorator_val.mdx +++ b/misc_docs/syntax/decorator_val.mdx @@ -8,7 +8,7 @@ category: "decorators" The `@val` decorator allows you to bind to JavaScript values that are on the global scope. -For example: +### Example @@ -29,5 +29,6 @@ var timeoutID = setTimeout(function (param) { -To access global values on another global object, such as `Date.now` or `location.origin.length` see the `@scope` decorator. +### References +* [Bind to Global JS Values](/docs/manual/latest/bind-to-global-js-values) From 9be40cfd4d053de592c8336a72bed6afa10ff33e Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 16:11:44 +1100 Subject: [PATCH 71/78] Update variadic decorator --- misc_docs/syntax/decorator_variadic.mdx | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/misc_docs/syntax/decorator_variadic.mdx b/misc_docs/syntax/decorator_variadic.mdx index 4e9dcc1ae..78bc14c2d 100644 --- a/misc_docs/syntax/decorator_variadic.mdx +++ b/misc_docs/syntax/decorator_variadic.mdx @@ -8,7 +8,7 @@ category: "decorators" The `@variadic` decorator is used to model JavaScript functions that take a variable number of arguments, where all arguments are of the same type. -For example: +### Example @@ -25,21 +25,6 @@ var result = Math.max(5, -2, 6, 1); -If your function has mandatory arguments, you can use the `@as` decorator to add them: +### References - - -```res -@val @variadic -external warn: (@as(404) _, @as("NOT_FOUND") _, array) => unit = "log" - -warn([]) -warn(["this", "page", "is", "not", "found"]) -``` - -```js -log(404, "NOT_FOUND"); -log(404, "NOT_FOUND", "this", "page", "is", "not", "found"); -``` - - +* [Variadic Function Arguments](/docs/manual/latest/bind-to-js-function#variadic-function-arguments) \ No newline at end of file From 5141b495ed11382c58cb19a0d18fbb0314ff48dc Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 16:24:39 +1100 Subject: [PATCH 72/78] Clean up, standardise, simplify --- misc_docs/syntax/decorator_as.mdx | 8 +------ misc_docs/syntax/decorator_deriving.mdx | 2 +- misc_docs/syntax/decorator_get.mdx | 24 ++++++--------------- misc_docs/syntax/decorator_get_index.mdx | 8 +------ misc_docs/syntax/decorator_inline.mdx | 2 +- misc_docs/syntax/decorator_int.mdx | 2 +- misc_docs/syntax/decorator_meth.mdx | 2 +- misc_docs/syntax/decorator_module.mdx | 2 +- misc_docs/syntax/decorator_new.mdx | 2 +- misc_docs/syntax/decorator_return.mdx | 3 +-- misc_docs/syntax/decorator_scope.mdx | 2 +- misc_docs/syntax/decorator_send.mdx | 2 +- misc_docs/syntax/decorator_set.mdx | 27 ++++++------------------ misc_docs/syntax/decorator_set_index.mdx | 8 +------ misc_docs/syntax/decorator_string.mdx | 2 +- misc_docs/syntax/decorator_unwrap.mdx | 2 +- 16 files changed, 27 insertions(+), 71 deletions(-) diff --git a/misc_docs/syntax/decorator_as.mdx b/misc_docs/syntax/decorator_as.mdx index 644be25ea..85eb5cd29 100644 --- a/misc_docs/syntax/decorator_as.mdx +++ b/misc_docs/syntax/decorator_as.mdx @@ -1,6 +1,6 @@ --- id: "as-decorator" -keywords: ["as", "decorator", "record", "field", "alias", "object"] +keywords: ["as", "decorator"] name: "@as" summary: "This is the `@as` decorator." category: "decorators" @@ -34,9 +34,3 @@ var action = { * [Constrain Arguments Better](/docs/manual/latest/bind-to-js-function#constrain-arguments-better) * [Fixed Arguments](/docs/manual/latest/bind-to-js-function#fixed-arguments) - -### Related - -* `@int` -* `@string` -* `@variadic` diff --git a/misc_docs/syntax/decorator_deriving.mdx b/misc_docs/syntax/decorator_deriving.mdx index 97dd92ce1..ef2a0954f 100644 --- a/misc_docs/syntax/decorator_deriving.mdx +++ b/misc_docs/syntax/decorator_deriving.mdx @@ -1,6 +1,6 @@ --- id: "deriving-decorator" -keywords: ["deriving", "decorator", "record"] +keywords: ["deriving", "decorator"] name: "@deriving" summary: "This is the `@deriving` decorator." category: "decorators" diff --git a/misc_docs/syntax/decorator_get.mdx b/misc_docs/syntax/decorator_get.mdx index c5a572fe6..c3d69e230 100644 --- a/misc_docs/syntax/decorator_get.mdx +++ b/misc_docs/syntax/decorator_get.mdx @@ -1,6 +1,6 @@ --- id: "get-decorator" -keywords: ["get", "decorator", "property", "object", "bind"] +keywords: ["get", "decorator"] name: "@get" summary: "This is the `@get` decorator." category: "decorators" @@ -13,21 +13,15 @@ The `@get` decorator is used to bind to a property of an object. ```res -type element +type window +@bs.val external window: window = "window" +@bs.get external getName: window => string = "name" -@scope("document") @val -external createElement: string => element = "createElement" - -@get -external getScrollTop: element => unit = "scrollTop" - -let div = createElement("div") -let top = getScrollTop(div) +let name = getName(window) ``` ```js -var div = document.createElement("div") -var top = div.scrollTop +var name = window.name; ``` @@ -35,9 +29,3 @@ var top = div.scrollTop ### References - [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) - -### Related - -- `@set` -- `@get_index` -- `@set_index` diff --git a/misc_docs/syntax/decorator_get_index.mdx b/misc_docs/syntax/decorator_get_index.mdx index 205b4be03..8eec67fed 100644 --- a/misc_docs/syntax/decorator_get_index.mdx +++ b/misc_docs/syntax/decorator_get_index.mdx @@ -1,6 +1,6 @@ --- id: "get-index-decorator" -keywords: ["get", "decorator", "array", "object", "index"] +keywords: ["get", "index", "decorator"] name: "@get_index" summary: "This is the `@get_index` decorator." category: "decorators" @@ -43,9 +43,3 @@ var value = o["y"]; ### References - [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) - -### Related - -- `@get` -- `@set` -- `@set_index` diff --git a/misc_docs/syntax/decorator_inline.mdx b/misc_docs/syntax/decorator_inline.mdx index 4bdab6c34..5f630ae19 100644 --- a/misc_docs/syntax/decorator_inline.mdx +++ b/misc_docs/syntax/decorator_inline.mdx @@ -1,6 +1,6 @@ --- id: "inline-decorator" -keywords: ["inline", "decorator", "constant"] +keywords: ["inline", "decorator"] name: "@inline" summary: "This is the `@inline` decorator." category: "decorators" diff --git a/misc_docs/syntax/decorator_int.mdx b/misc_docs/syntax/decorator_int.mdx index 07031a067..8cbd6d4ac 100644 --- a/misc_docs/syntax/decorator_int.mdx +++ b/misc_docs/syntax/decorator_int.mdx @@ -1,6 +1,6 @@ --- id: "int-decorator" -keywords: ["int", "decorator", "polymorphic", "variant", "as", "external"] +keywords: ["int", "decorator"] name: "@int" summary: "This is the `@int` decorator." category: "decorators" diff --git a/misc_docs/syntax/decorator_meth.mdx b/misc_docs/syntax/decorator_meth.mdx index 2a054e1d0..306182d4e 100644 --- a/misc_docs/syntax/decorator_meth.mdx +++ b/misc_docs/syntax/decorator_meth.mdx @@ -1,6 +1,6 @@ --- id: "meth-decorator" -keywords: ["meth", "decorator", "object", "function"] +keywords: ["meth", "decorator"] name: "@meth" summary: "This is the `@meth` decorator." category: "decorators" diff --git a/misc_docs/syntax/decorator_module.mdx b/misc_docs/syntax/decorator_module.mdx index 70bcf7cf0..5847a500a 100644 --- a/misc_docs/syntax/decorator_module.mdx +++ b/misc_docs/syntax/decorator_module.mdx @@ -1,6 +1,6 @@ --- id: "module-decorator" -keywords: ["module", "decorator", "import", "require", "bind"] +keywords: ["module", "decorator"] name: "@module" summary: "This is the `@module` decorator." category: "decorators" diff --git a/misc_docs/syntax/decorator_new.mdx b/misc_docs/syntax/decorator_new.mdx index 6b57d5d5d..056a16fcd 100644 --- a/misc_docs/syntax/decorator_new.mdx +++ b/misc_docs/syntax/decorator_new.mdx @@ -1,6 +1,6 @@ --- id: "new-decorator" -keywords: ["new", "decorator", "object"] +keywords: ["new", "decorator"] name: "@new" summary: "This is the `@new` decorator." category: "decorators" diff --git a/misc_docs/syntax/decorator_return.mdx b/misc_docs/syntax/decorator_return.mdx index 3f9337dca..3c5da1e31 100644 --- a/misc_docs/syntax/decorator_return.mdx +++ b/misc_docs/syntax/decorator_return.mdx @@ -1,6 +1,6 @@ --- id: "return-decorator" -keywords: ["return", "decorator", "null", "undefined"] +keywords: ["return", "decorator"] name: "@return" summary: "This is the `@return` decorator." category: "decorators" @@ -8,7 +8,6 @@ category: "decorators" The `@return` decorator is used to control how `null` and `undefined` values are converted to `option` types in ReScript. - ### Example diff --git a/misc_docs/syntax/decorator_scope.mdx b/misc_docs/syntax/decorator_scope.mdx index 4a9f8af76..548bd8cee 100644 --- a/misc_docs/syntax/decorator_scope.mdx +++ b/misc_docs/syntax/decorator_scope.mdx @@ -1,6 +1,6 @@ --- id: "scope-decorator" -keywords: ["scope", "decorator", "bind", "global"] +keywords: ["scope", "decorator"] name: "@scope" summary: "This is the `@scope` decorator." category: "decorators" diff --git a/misc_docs/syntax/decorator_send.mdx b/misc_docs/syntax/decorator_send.mdx index bae452ce5..74ac8b1b3 100644 --- a/misc_docs/syntax/decorator_send.mdx +++ b/misc_docs/syntax/decorator_send.mdx @@ -1,6 +1,6 @@ --- id: "send-decorator" -keywords: ["send", "decorator", "object"] +keywords: ["send", "decorator"] name: "@send" summary: "This is the `@send` decorator." category: "decorators" diff --git a/misc_docs/syntax/decorator_set.mdx b/misc_docs/syntax/decorator_set.mdx index 062aac0ed..ce2ff896b 100644 --- a/misc_docs/syntax/decorator_set.mdx +++ b/misc_docs/syntax/decorator_set.mdx @@ -1,6 +1,6 @@ --- id: "set-decorator" -keywords: ["set", "property", "object", "bind"] +keywords: ["set", "decorator"] name: "@set" summary: "This is the `@set` decorator." category: "decorators" @@ -8,27 +8,20 @@ category: "decorators" The `@set` decorator is used to set a property of an object. -For example: +### Example ```res -type element +type window +@bs.val external window: window = "window" +@bs.set external setName: (window, string) => unit = "name" -@scope("document") @val -external createElement: string => element = "createElement" - -@set -external setScrollTop: (element, int) => unit = "scrollTop" - -let div = createElement("div") -setScrollTop(div, 100) +setName(window, "MyWindow") ``` ```js -var div = document.createElement("div") - -div.scrollTop = 100 +window.name = "MyWindow"; ``` @@ -36,9 +29,3 @@ div.scrollTop = 100 ### References - [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) - -### Related - -- `@get` -- `@set_index` -- `@get_index` diff --git a/misc_docs/syntax/decorator_set_index.mdx b/misc_docs/syntax/decorator_set_index.mdx index 3c1ca386b..47d27991a 100644 --- a/misc_docs/syntax/decorator_set_index.mdx +++ b/misc_docs/syntax/decorator_set_index.mdx @@ -1,6 +1,6 @@ --- id: "set-index-decorator" -keywords: ["set", "decorator", "array", "object", "index"] +keywords: ["set", "index", decorator"] name: "@set_index" summary: "This is the `@set_index` decorator." category: "decorators" @@ -43,9 +43,3 @@ var value = o["y"]; ### References - [Bind using Special `@bs` Getters & Setters](/docs/manual/latest/bind-to-js-object#bind-using-special-bs-getters--setters) - -### Related - -- `@get` -- `@set` -- `@get_index` diff --git a/misc_docs/syntax/decorator_string.mdx b/misc_docs/syntax/decorator_string.mdx index 1522e66ea..4b24e7b76 100644 --- a/misc_docs/syntax/decorator_string.mdx +++ b/misc_docs/syntax/decorator_string.mdx @@ -1,6 +1,6 @@ --- id: "string-decorator" -keywords: ["string", "decorator", "polymorphic", "variant", "as", "external"] +keywords: ["string", "decorator"] name: "@string" summary: "This is the `@string` decorator." category: "decorators" diff --git a/misc_docs/syntax/decorator_unwrap.mdx b/misc_docs/syntax/decorator_unwrap.mdx index 1b65d7737..89337556f 100644 --- a/misc_docs/syntax/decorator_unwrap.mdx +++ b/misc_docs/syntax/decorator_unwrap.mdx @@ -1,6 +1,6 @@ --- id: "unwrap-decorator" -keywords: ["unwrap", "decorator", "external"] +keywords: ["unwrap", "decorator"] name: "@unwrap" summary: "This is the `@unwrap` decorator." category: "decorators" From f0bc37560aa78fe75925fdf3cef020a2f314d41a Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 16:25:04 +1100 Subject: [PATCH 73/78] Update val decorator --- misc_docs/syntax/decorator_val.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_val.mdx b/misc_docs/syntax/decorator_val.mdx index 71c9babbd..396621b71 100644 --- a/misc_docs/syntax/decorator_val.mdx +++ b/misc_docs/syntax/decorator_val.mdx @@ -1,6 +1,6 @@ --- id: "val-decorator" -keywords: ["val", "decorator", "bind", "global"] +keywords: ["val", "decorator"] name: "@val" summary: "This is the `@val` decorator." category: "decorators" From 97ddb3a0fa1d4623dc965e9257915662989eacfe Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 16:53:36 +1100 Subject: [PATCH 74/78] Add obj decorator --- misc_docs/syntax/decorator_obj.mdx | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 misc_docs/syntax/decorator_obj.mdx diff --git a/misc_docs/syntax/decorator_obj.mdx b/misc_docs/syntax/decorator_obj.mdx new file mode 100644 index 000000000..ae6e14d39 --- /dev/null +++ b/misc_docs/syntax/decorator_obj.mdx @@ -0,0 +1,35 @@ +--- +id: "obj-decorator" +keywords: ["obj", "decorator"] +name: "@obj" +summary: "This is the `@obj` decorator." +category: "decorators" +--- + +The `@obj` decorator is used to create functions that return JavaScript objects +with properties that match the function's parameter labels. + +### Example + + + +```res +@bs.obj +external action: (~name: string, unit) => _ = "" + +let helloAction = action(~name="Hello") +``` + +```js +function helloAction(param) { + return { + name: "Hello", + } +} +``` + + + +### References + +* [Convert External into JS Object Creation Function](/docs/manual/latest/generate-converters-accessors#convert-external-into-js-object-creation-function) \ No newline at end of file From f8b7a7820c2e1bd414769da84c594f63fce46489 Mon Sep 17 00:00:00 2001 From: Kevan Stannard Date: Sat, 9 Jan 2021 17:03:21 +1100 Subject: [PATCH 75/78] Fix deriving typo --- misc_docs/syntax/decorator_deriving.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc_docs/syntax/decorator_deriving.mdx b/misc_docs/syntax/decorator_deriving.mdx index ef2a0954f..a686a3e86 100644 --- a/misc_docs/syntax/decorator_deriving.mdx +++ b/misc_docs/syntax/decorator_deriving.mdx @@ -8,7 +8,7 @@ category: "decorators" When the `@deriving` decorator is applied to a **record** type, it expands the type into a factory function plus a set of -getter/setter functions for it's fields. +getter/setter functions for its fields. > Note that this is an outdated decorator and you may no longer need to use it. > See [Convert Record Type to Abstract Record](/docs/manual/latest/generate-converters-accessors#convert-record-type-to-abstract-record) for more details. From dad22000cc8bd270018fbace972e64a5af61d2e7 Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Sat, 9 Jan 2021 16:48:15 +0100 Subject: [PATCH 76/78] SyntaxLookupWidget -> src/SyntaxLookup The SyntaxLookupWidget is not an isolated component anymore (it also does side-effectual logic to load the data), so it's better to call it a page and put it in the `src` directory instead. --- pages/syntax-lookup.mdx | 4 +- .../SyntaxLookupWidget.js => SyntaxLookup.js} | 44 +++++++++---------- ...yntaxLookupWidget.res => SyntaxLookup.res} | 43 ++++++++++-------- ...taxLookupWidget.resi => SyntaxLookup.resi} | 0 4 files changed, 48 insertions(+), 43 deletions(-) rename src/{components/SyntaxLookupWidget.js => SyntaxLookup.js} (94%) rename src/{components/SyntaxLookupWidget.res => SyntaxLookup.res} (94%) rename src/{components/SyntaxLookupWidget.resi => SyntaxLookup.resi} (100%) diff --git a/pages/syntax-lookup.mdx b/pages/syntax-lookup.mdx index 39a5e8da7..8cc91d9d1 100644 --- a/pages/syntax-lookup.mdx +++ b/pages/syntax-lookup.mdx @@ -4,6 +4,6 @@ description: "Discover ReScript syntax constructs with our lookup tool" canonical: "/docs/manual/latest/syntax-lookup" --- -import { make as SyntaxLookupWidget } from "src/components/SyntaxLookupWidget" +import { make as SyntaxLookup } from "src/SyntaxLookup" - + diff --git a/src/components/SyntaxLookupWidget.js b/src/SyntaxLookup.js similarity index 94% rename from src/components/SyntaxLookupWidget.js rename to src/SyntaxLookup.js index 7ce88606a..3813854f1 100644 --- a/src/components/SyntaxLookupWidget.js +++ b/src/SyntaxLookup.js @@ -1,12 +1,12 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as Next from "../bindings/Next.js"; +import * as Next from "./bindings/Next.js"; import * as Curry from "bs-platform/lib/es6/curry.js"; import * as React from "react"; import * as Js_dict from "bs-platform/lib/es6/js_dict.js"; import FuseJs from "fuse.js"; -import * as Markdown from "./Markdown.js"; -import * as SearchBox from "./SearchBox.js"; +import * as Markdown from "./components/Markdown.js"; +import * as SearchBox from "./components/SearchBox.js"; import * as Belt_Array from "bs-platform/lib/es6/belt_Array.js"; import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; @@ -36,17 +36,7 @@ function toString(t) { } } -function SyntaxLookupWidget$Category(Props) { - var title = Props.title; - var children = Props.children; - return React.createElement("div", undefined, React.createElement("h3", { - className: "font-sans font-medium text-gray-100 tracking-wide text-14 uppercase mb-2" - }, title), React.createElement("div", { - className: "flex flex-wrap" - }, children)); -} - -function toCategory(s) { +function fromString(s) { switch (s) { case "controlflow" : return /* ControlFlow */1; @@ -59,6 +49,16 @@ function toCategory(s) { } } +function SyntaxLookup$Category(Props) { + var title = Props.title; + var children = Props.children; + return React.createElement("div", undefined, React.createElement("h3", { + className: "font-sans font-medium text-gray-100 tracking-wide text-14 uppercase mb-2" + }, title), React.createElement("div", { + className: "flex flex-wrap" + }, children)); +} + function toItem(syntaxData) { var file = syntaxData.file; var id = syntaxData.id; @@ -71,7 +71,7 @@ function toItem(syntaxData) { keywords: keywords, name: name, summary: summary, - category: toCategory(category), + category: fromString(category), component: requireSyntaxFile(file) }; } @@ -102,14 +102,14 @@ function getAnchor(path) { } } -function SyntaxLookupWidget$Tag(Props) { +function SyntaxLookup$Tag(Props) { var text = Props.text; return React.createElement("span", { className: "bg-fire-10-tr py-1 px-3 rounded text-fire text-16" }, text); } -function SyntaxLookupWidget$DetailBox(Props) { +function SyntaxLookup$DetailBox(Props) { var summary = Props.summary; var children = Props.children; var more = summary.split("`"); @@ -142,7 +142,7 @@ function SyntaxLookupWidget$DetailBox(Props) { }, children)); } -function SyntaxLookupWidget(Props) { +function SyntaxLookup(Props) { var router = Next.Router.useRouter(undefined); var match = React.useState(function () { return /* ShowAll */0; @@ -231,7 +231,7 @@ function SyntaxLookupWidget(Props) { var item = state._0; details = React.createElement("div", { className: "mb-16" - }, React.createElement(SyntaxLookupWidget$DetailBox, { + }, React.createElement(SyntaxLookup$DetailBox, { summary: item.summary, children: render(item.component) })); @@ -279,14 +279,14 @@ function SyntaxLookupWidget(Props) { key: item.name, className: "mr-2 mb-2 cursor-pointer", onMouseDown: onMouseDown - }, React.createElement(SyntaxLookupWidget$Tag, { + }, React.createElement(SyntaxLookup$Tag, { text: item.name })); })); var el = React.createElement("div", { key: title, className: "first:mt-0 mt-12" - }, React.createElement(SyntaxLookupWidget$Category, { + }, React.createElement(SyntaxLookup$Category, { title: title, children: children })); @@ -345,7 +345,7 @@ function SyntaxLookupWidget(Props) { }, details, categories)); } -var make = SyntaxLookupWidget; +var make = SyntaxLookup; export { make , diff --git a/src/components/SyntaxLookupWidget.res b/src/SyntaxLookup.res similarity index 94% rename from src/components/SyntaxLookupWidget.res rename to src/SyntaxLookup.res index ca5c8c3f3..ed94b856d 100644 --- a/src/components/SyntaxLookupWidget.res +++ b/src/SyntaxLookup.res @@ -14,13 +14,11 @@ module MdxComp = { type props type t = Js.t => React.element - let render: t => React.element = %raw( - ` + let render: t => React.element = %raw(` function(c) { return React.createElement(c, {}); } - ` - ) + `) /* @bs.get */ /* external frontmatter: t => Js.Json.t = "frontmatter" */ @@ -43,6 +41,15 @@ module Category = { | Other => "Other" } + let fromString = (s: string): t => { + switch s { + | "decorators" => Decorators + | "controlflow" => ControlFlow + | "operators" => Operators + | _ => Other + } + } + @react.component let make = (~title, ~children) => {
@@ -54,6 +61,8 @@ module Category = { } } +// The data representing a syntax construct +// handled in the widget type item = { id: string, keywords: array, @@ -63,15 +72,6 @@ type item = { component: MdxComp.t, } -let toCategory = (s: string): Category.t => { - switch s { - | "decorators" => Decorators - | "controlflow" => ControlFlow - | "operators" => Operators - | _ => Other - } -} - let toItem = (syntaxData: syntaxData): item => { let file = syntaxData["file"] let id = syntaxData["id"] @@ -84,8 +84,8 @@ let toItem = (syntaxData: syntaxData): item => { keywords: keywords, name: name, summary: summary, - category: toCategory(category), - component: requireSyntaxFile(file) + category: Category.fromString(category), + component: requireSyntaxFile(file), } item } @@ -200,9 +200,12 @@ let make = () => { switch value { | "" => ShowAll | search => - let filtered = fuse->Fuse.search(search)->Belt.Array.map(m => { - m["item"] - }) + let filtered = + fuse + ->Fuse.search(search) + ->Belt.Array.map(m => { + m["item"] + }) if Js.Array.length(filtered) === 1 { let item = Belt.Array.getExn(filtered, 0) @@ -249,7 +252,9 @@ let make = () => { Js.Dict.set(acc, key, items) acc }) - })->Js.Dict.entries->Belt.Array.reduce([], (acc, entry) => { + }) + ->Js.Dict.entries + ->Belt.Array.reduce([], (acc, entry) => { let (title, items) = entry if Js.Array.length(items) === 0 { acc diff --git a/src/components/SyntaxLookupWidget.resi b/src/SyntaxLookup.resi similarity index 100% rename from src/components/SyntaxLookupWidget.resi rename to src/SyntaxLookup.resi From 913892262ea5166446b32087fe6e5f6edb58064a Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Sat, 9 Jan 2021 16:53:23 +0100 Subject: [PATCH 77/78] Activate href checks for misc_docs --- scripts/test-hrefs.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/test-hrefs.js b/scripts/test-hrefs.js index 61c50c0bd..fa1cab264 100644 --- a/scripts/test-hrefs.js +++ b/scripts/test-hrefs.js @@ -206,8 +206,10 @@ const testFile = (pageMap, test) => { const main = () => { const [, , pattern] = process.argv; const cwd = path.join(__dirname, ".."); + + // All files that are going to be tested for broken links const files = glob.sync( - pattern ? pattern : `./{pages,_blogposts}/**/*.md?(x)`, + pattern ? pattern : `./{pages,_blogposts,misc_docs}/**/*.md?(x)`, { cwd } ); From 41861222b32a83eac162261d31482853f1d2771d Mon Sep 17 00:00:00 2001 From: Patrick Stapfer Date: Sat, 9 Jan 2021 17:03:32 +0100 Subject: [PATCH 78/78] Add hover behavior for item tags --- src/SyntaxLookup.js | 2 +- src/SyntaxLookup.res | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SyntaxLookup.js b/src/SyntaxLookup.js index 3813854f1..015e83e4e 100644 --- a/src/SyntaxLookup.js +++ b/src/SyntaxLookup.js @@ -105,7 +105,7 @@ function getAnchor(path) { function SyntaxLookup$Tag(Props) { var text = Props.text; return React.createElement("span", { - className: "bg-fire-10-tr py-1 px-3 rounded text-fire text-16" + className: "hover:bg-fire hover:text-white bg-fire-10-tr py-1 px-3 rounded text-fire text-16" }, text); } diff --git a/src/SyntaxLookup.res b/src/SyntaxLookup.res index ed94b856d..204be7be8 100644 --- a/src/SyntaxLookup.res +++ b/src/SyntaxLookup.res @@ -115,7 +115,7 @@ let getAnchor = path => { module Tag = { @react.component let make = (~text: string) => { - + {React.string(text)} }