From 2fd10438d56739031ba592b8317be5172c498802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 25 Jan 2024 17:03:47 +0100 Subject: [PATCH 01/13] mark latest version as v11 instead of v11.0 --- src/common/Constants.res | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/Constants.res b/src/common/Constants.res index 21d492af3..6a15c7116 100644 --- a/src/common/Constants.res +++ b/src/common/Constants.res @@ -1,6 +1,6 @@ // This is used for the version dropdown in the manual layouts let allManualVersions = [ - ("latest", "v11.0"), + ("latest", "v11"), ("v10.0.0", "v9.1 - v10.1"), ("v9.0.0", "v8.2 - v9.0"), ("v8.0.0", "v6.0 - v8.2"), From afa3e0c836da12ef405e1aee0ae9fec610176f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 25 Jan 2024 17:04:37 +0100 Subject: [PATCH 02/13] document tagged templates from rescript-lang/rescript-compiler#6250 --- misc_docs/syntax/decorator_taggedTemplate.mdx | 35 +++++++++++++++++++ .../manual/latest/bind-to-js-function.mdx | 31 ++++++++++++++++ .../docs/manual/latest/interop-cheatsheet.mdx | 22 ++++++++++++ pages/docs/manual/latest/overview.mdx | 13 +++---- 4 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 misc_docs/syntax/decorator_taggedTemplate.mdx diff --git a/misc_docs/syntax/decorator_taggedTemplate.mdx b/misc_docs/syntax/decorator_taggedTemplate.mdx new file mode 100644 index 000000000..ce63f5a59 --- /dev/null +++ b/misc_docs/syntax/decorator_taggedTemplate.mdx @@ -0,0 +1,35 @@ +--- +id: "taggedTemplate-decorator" +keywords: ["taggedTemplate", "tagged", "template", "decorator"] +name: "@taggedTemplate" +summary: "This is the `@taggedTemplate` decorator." +category: "decorators" +--- +**Since 11.1** + +The `@taggedTemplate` decorator is used to bind to JavaScript tag functions. + +### Example + + + +```res example +type res +@module("bun") @taggedTemplate +external sh: (array, array) => promise = "$" + +let filename = "index.res" +let res = await sh`ls ${filename}` +``` + +```js +import * as $$Bun from "bun"; +var filename = "index.res" +var res = await $$Bun.$`ls ${filename}` +``` + + + +### References + +* [Tagged template functions](/docs/manual/latest/bind-to-js-function#tagged_template-functions) \ No newline at end of file diff --git a/pages/docs/manual/latest/bind-to-js-function.mdx b/pages/docs/manual/latest/bind-to-js-function.mdx index 2c8e60b03..34ee8c782 100644 --- a/pages/docs/manual/latest/bind-to-js-function.mdx +++ b/pages/docs/manual/latest/bind-to-js-function.mdx @@ -421,3 +421,34 @@ Currently 4 directives are supported: `null_to_opt`, `undefined_to_opt`, `nullab `identity` will make sure that compiler will do nothing about the returned value. It is rarely used, but introduced here for debugging purpose. + +## Tagged template functions + +**Since 11.1** + +**Experimental** You can easily bind to JS tagged template functions. +All you need to do is defining a binding to a function that has two arrays as arguments, +the first one being an array of strings and the second can be an array of anything. +You add the `@taggedTemplate` annotation and you're good to go! + + + +```res example +type res +@module("bun") @taggedTemplate +external sh: (array, array) => promise = "$" + +let filename = "index.res" +let res = await sh`ls ${filename}` +``` + +```js +import * as $$Bun from "bun"; +var filename = "index.res" +var res = await $$Bun.$`ls ${filename}` +``` + + + +Notice that it gets compiled to tagged template literals in JS, which allows +to use JS tools that only work on the literals and not by calling directly the tag function. diff --git a/pages/docs/manual/latest/interop-cheatsheet.mdx b/pages/docs/manual/latest/interop-cheatsheet.mdx index 54b2b14b3..6af4a28eb 100644 --- a/pages/docs/manual/latest/interop-cheatsheet.mdx +++ b/pages/docs/manual/latest/interop-cheatsheet.mdx @@ -38,6 +38,7 @@ This is a glossary with examples. All the features are described by later pages. - [`@uncurry`](bind-to-js-function#extra-solution) - [`@unwrap`](bind-to-js-function#trick-2-polymorphic-variant--bsunwrap) - [`@val`](bind-to-global-js-values#global-modules) +- [`@taggedTemplate`](bind-to-js-function#tagged_template-functions) - [`@deprecated`](attribute#usage) - [`genType`](https://github.com/reason-association/genType) @@ -193,6 +194,27 @@ external join: array => string = "join" +### Tagged template functions + + + +```res example +type res +@module("bun") @taggedTemplate +external sh: (array, array) => promise = "$" + +let filename = "index.res" +let res = await sh`ls ${filename}` +``` + +```js +import * as $$Bun from "bun"; +var filename = "index.res" +var res = await $$Bun.$`ls ${filename}` +``` + + + ### Polymorphic Function diff --git a/pages/docs/manual/latest/overview.mdx b/pages/docs/manual/latest/overview.mdx index 849b1575b..cf0307e01 100644 --- a/pages/docs/manual/latest/overview.mdx +++ b/pages/docs/manual/latest/overview.mdx @@ -34,12 +34,13 @@ canonical: "/docs/manual/latest/overview" ### String & Character -| JavaScript | ReScript | -| --------------------------| --------------------- | -| `"Hello world!"` | Same | -| `'Hello world!'` | Strings must use `"` | -| `"hello " + "world"` | `"hello " ++ "world"` | -| `` `hello ${message}` `` | Same | +| JavaScript | ReScript | +| ----------------------------- | --------------------- | +| `"Hello world!"` | Same | +| `'Hello world!'` | Strings must use `"` | +| `"hello " + "world"` | `"hello " ++ "world"` | +| `` `hello ${message}` `` | Same | +| `` sql`select ${fnName};` `` | Same | ### Boolean From c796a71ccf3caf83817df6b1f308e56ea6390970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Wed, 31 Jan 2024 15:52:37 +0100 Subject: [PATCH 03/13] better document JS tagged templates --- pages/docs/manual/latest/bind-to-js-function.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pages/docs/manual/latest/bind-to-js-function.mdx b/pages/docs/manual/latest/bind-to-js-function.mdx index 34ee8c782..9ead2453a 100644 --- a/pages/docs/manual/latest/bind-to-js-function.mdx +++ b/pages/docs/manual/latest/bind-to-js-function.mdx @@ -426,8 +426,9 @@ Currently 4 directives are supported: `null_to_opt`, `undefined_to_opt`, `nullab **Since 11.1** -**Experimental** You can easily bind to JS tagged template functions. -All you need to do is defining a binding to a function that has two arrays as arguments, +**Experimental** You can easily bind to [JS tagged template functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates). +Tag functions in JS expect as input an array of strings and variadic parameters for the arguments of the interpolation. +To bind to those functions in rescript, write bindings that have two arrays as arguments, the first one being an array of strings and the second can be an array of anything. You add the `@taggedTemplate` annotation and you're good to go! From ef7828bc3aa17cef9c2b8fcb1efeb5806c0c9f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Wed, 31 Jan 2024 16:00:36 +0100 Subject: [PATCH 04/13] improve Bun shell example --- misc_docs/syntax/decorator_taggedTemplate.mdx | 13 +++++++------ pages/docs/manual/latest/bind-to-js-function.mdx | 13 +++++++------ pages/docs/manual/latest/interop-cheatsheet.mdx | 13 +++++++------ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/misc_docs/syntax/decorator_taggedTemplate.mdx b/misc_docs/syntax/decorator_taggedTemplate.mdx index ce63f5a59..c6edd9690 100644 --- a/misc_docs/syntax/decorator_taggedTemplate.mdx +++ b/misc_docs/syntax/decorator_taggedTemplate.mdx @@ -14,18 +14,19 @@ The `@taggedTemplate` decorator is used to bind to JavaScript tag functions. ```res example -type res -@module("bun") @taggedTemplate -external sh: (array, array) => promise = "$" +// see https://bun.sh/docs/runtime/shell +type result = {exitCode: int} +@module("bun") @taggedTemplate +external sh: (array, array) => promise = "$" let filename = "index.res" -let res = await sh`ls ${filename}` +let result = await sh`ls ${filename}` ``` ```js import * as $$Bun from "bun"; -var filename = "index.res" -var res = await $$Bun.$`ls ${filename}` +var filename = "index.res"; +var result = await $$Bun.$`ls ${filename}`; ``` diff --git a/pages/docs/manual/latest/bind-to-js-function.mdx b/pages/docs/manual/latest/bind-to-js-function.mdx index 9ead2453a..6868d03c7 100644 --- a/pages/docs/manual/latest/bind-to-js-function.mdx +++ b/pages/docs/manual/latest/bind-to-js-function.mdx @@ -435,18 +435,19 @@ You add the `@taggedTemplate` annotation and you're good to go! ```res example -type res -@module("bun") @taggedTemplate -external sh: (array, array) => promise = "$" +// see https://bun.sh/docs/runtime/shell +type result = {exitCode: int} +@module("bun") @taggedTemplate +external sh: (array, array) => promise = "$" let filename = "index.res" -let res = await sh`ls ${filename}` +let result = await sh`ls ${filename}` ``` ```js import * as $$Bun from "bun"; -var filename = "index.res" -var res = await $$Bun.$`ls ${filename}` +var filename = "index.res"; +var result = await $$Bun.$`ls ${filename}`; ``` diff --git a/pages/docs/manual/latest/interop-cheatsheet.mdx b/pages/docs/manual/latest/interop-cheatsheet.mdx index 6af4a28eb..ecbe369dd 100644 --- a/pages/docs/manual/latest/interop-cheatsheet.mdx +++ b/pages/docs/manual/latest/interop-cheatsheet.mdx @@ -199,18 +199,19 @@ external join: array => string = "join" ```res example -type res -@module("bun") @taggedTemplate -external sh: (array, array) => promise = "$" +// see https://bun.sh/docs/runtime/shell +type result = {exitCode: int} +@module("bun") @taggedTemplate +external sh: (array, array) => promise = "$" let filename = "index.res" -let res = await sh`ls ${filename}` +let result = await sh`ls ${filename}` ``` ```js import * as $$Bun from "bun"; -var filename = "index.res" -var res = await $$Bun.$`ls ${filename}` +var filename = "index.res"; +var result = await $$Bun.$`ls ${filename}`; ``` From 380a8605c0eacc6bdc821e244b080e2a71515db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Wed, 31 Jan 2024 16:28:51 +0100 Subject: [PATCH 05/13] link to other JS tagged template functions --- pages/docs/manual/latest/bind-to-js-function.mdx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pages/docs/manual/latest/bind-to-js-function.mdx b/pages/docs/manual/latest/bind-to-js-function.mdx index 6868d03c7..9fbe21b99 100644 --- a/pages/docs/manual/latest/bind-to-js-function.mdx +++ b/pages/docs/manual/latest/bind-to-js-function.mdx @@ -454,3 +454,6 @@ var result = await $$Bun.$`ls ${filename}`; Notice that it gets compiled to tagged template literals in JS, which allows to use JS tools that only work on the literals and not by calling directly the tag function. + +There are plenty of useful JS tools you can bind to, like [`gql`](https://github.com/apollographql/graphql-tag), +[`sql`](https://github.com/porsager/postgres), [`css`](https://github.com/mayank99/ecsstatic) and a lot others! \ No newline at end of file From 37fcc8f13ad16303b8d48ccb3ef98be8654af9fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 1 Feb 2024 10:56:55 +0100 Subject: [PATCH 06/13] document how to define tag functions in rescript --- data/sidebar_manual_latest.json | 1 + pages/docs/manual/latest/tagged-templates.mdx | 124 ++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 pages/docs/manual/latest/tagged-templates.mdx diff --git a/data/sidebar_manual_latest.json b/data/sidebar_manual_latest.json index 43a78c47a..debff5ca2 100644 --- a/data/sidebar_manual_latest.json +++ b/data/sidebar_manual_latest.json @@ -28,6 +28,7 @@ "lazy-values", "promise", "async-await", + "tagged-templates", "module", "import-export", "attribute", diff --git a/pages/docs/manual/latest/tagged-templates.mdx b/pages/docs/manual/latest/tagged-templates.mdx new file mode 100644 index 000000000..f3dabb194 --- /dev/null +++ b/pages/docs/manual/latest/tagged-templates.mdx @@ -0,0 +1,124 @@ +--- +title: "Tagged templates" +description: "Using tagged templates in ReScript" +canonical: "/docs/manual/latest/tagged-templates" +--- + +# Tagged templates + +**Since 11.1** + +Tagged templates provide a special form of string interpolation, enabling the creation of template literals +where placeholders aren't restricted to strings. Moreover, the resulting output isn't confined solely to +strings either. You can take a look at the [JS documentation +about tagged templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates) +to learn more about them. + +## Define a tag function + +Tag functions in ReScript have the following signature: +```res +let myTagFunction : (array, array<'param>) => 'output +``` +As you can see, you can have any type you want both for the placeholder array and for the output. + +Given how string interpolation works, you'll always have the following invariant: +```res +Array.length(strings) == Array.length(placeholder) + 1 +``` + +Let's say you want to interpolate strings with all kind of builtin types and make it work inside React components, +you can define the following tag function: + + + +```res prelude +type params = + | I(int) + | F(float) + | S(string) + | Bool(bool) + +let s = (strings, parameters) => { + let text = Array.reduceWithIndex(parameters, Array.getUnsafe(strings, 0), ( + acc, + param, + i, + ) => { + let s = Array.getUnsafe(strings, i + 1) + let p = switch param { + | I(i) => Int.toString(i) + | F(f) => Float.toString(f) + | S(s) => s + | Bool(true) => "true" + | Bool(false) => "false" + } + acc ++ p ++ s + }) + React.string(text) +} +``` +```js +import * as Core__Array from "./stdlib/core__Array.js"; + +function s(strings, parameters) { + return Core__Array.reduceWithIndex(parameters, strings[0], (function (acc, param, i) { + var s = strings[i + 1 | 0]; + var p; + switch (param.TAG) { + case "I" : + case "F" : + p = param._0.toString(); + break; + case "S" : + p = param._0; + break; + case "Bool" : + p = param._0 ? "true" : "false"; + break; + + } + return acc + p + s; + })); +} +``` + + + +## Write tagged template literals + +Now that you have defined your tag function, you can use it this way: + + + +```res example +module Greetings = { + @react.component + let make = (~name, ~age) => { +
{s`hello ${S(name)} you're ${I(age)} year old!`}
+ } +} +``` +```js +function Greetings(props) { + return React.createElement("div", undefined, s([ + "hello ", + " you're ", + " year old!" + ], [ + { + TAG: "S", + _0: props.name + }, + { + TAG: "I", + _0: props.age + } + ])); +} +``` + +
+ +Pretty neat, isn't it? As you can see, it looks like any regular template literal but it accepts placeholders that are not strings +and it outputs something that is not a string either, a `React.element` in this case. \ No newline at end of file From 4949dfef1c5a2ecc9327cf854dc5c5700daa66d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 1 Feb 2024 10:58:16 +0100 Subject: [PATCH 07/13] reword bindings to JS tag functions --- pages/docs/manual/latest/bind-to-js-function.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/docs/manual/latest/bind-to-js-function.mdx b/pages/docs/manual/latest/bind-to-js-function.mdx index 9fbe21b99..ae165208f 100644 --- a/pages/docs/manual/latest/bind-to-js-function.mdx +++ b/pages/docs/manual/latest/bind-to-js-function.mdx @@ -428,7 +428,7 @@ Currently 4 directives are supported: `null_to_opt`, `undefined_to_opt`, `nullab **Experimental** You can easily bind to [JS tagged template functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates). Tag functions in JS expect as input an array of strings and variadic parameters for the arguments of the interpolation. -To bind to those functions in rescript, write bindings that have two arrays as arguments, +To bind to those functions in rescript, the binding signature must have two arrays as arguments, the first one being an array of strings and the second can be an array of anything. You add the `@taggedTemplate` annotation and you're good to go! From c0cc9dd75ad13a6138e5966fbb03c4cf48912dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 1 Feb 2024 11:23:20 +0100 Subject: [PATCH 08/13] upgrade highlightjs to v11 and use tsnobip/higlightjs-rescript --- package-lock.json | 27 ++- package.json | 5 +- plugins/rescript-highlightjs.js | 365 -------------------------------- src/common/App.res | 2 +- src/common/HighlightJs.res | 2 +- 5 files changed, 24 insertions(+), 377 deletions(-) delete mode 100644 plugins/rescript-highlightjs.js diff --git a/package-lock.json b/package-lock.json index 39fec9072..c2cbe01ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,8 @@ "gentype": "^3.44.0", "glob": "^7.1.4", "gray-matter": "^4.0.3", - "highlight.js": "^10.5.0", + "highlight.js": "^11.9.0", + "highlightjs-rescript": "^0.1.2", "lz-string": "^1.4.4", "next": "^13.1.1", "next-mdx-remote": "^4.4.1", @@ -4777,13 +4778,18 @@ } }, "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", + "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", "engines": { - "node": "*" + "node": ">=12.0.0" } }, + "node_modules/highlightjs-rescript": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/highlightjs-rescript/-/highlightjs-rescript-0.1.2.tgz", + "integrity": "sha512-d2S9tlszrh9iTHjruZum0tV2WlDmGl+l5QqvhyE+KpgRn2uH01a2MWuwFuCqyDieVVO+QOVUQp0yYI5FXvhBKw==" + }, "node_modules/html-url-attributes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.0.tgz", @@ -16976,9 +16982,14 @@ } }, "highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", + "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==" + }, + "highlightjs-rescript": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/highlightjs-rescript/-/highlightjs-rescript-0.1.2.tgz", + "integrity": "sha512-d2S9tlszrh9iTHjruZum0tV2WlDmGl+l5QqvhyE+KpgRn2uH01a2MWuwFuCqyDieVVO+QOVUQp0yYI5FXvhBKw==" }, "html-url-attributes": { "version": "3.0.0", diff --git a/package.json b/package.json index 3d0f25962..bf577d0d7 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "gentype": "^3.44.0", "glob": "^7.1.4", "gray-matter": "^4.0.3", - "highlight.js": "^10.5.0", + "highlight.js": "^11.9.0", + "highlightjs-rescript": "^0.1.2", "lz-string": "^1.4.4", "next": "^13.1.1", "next-mdx-remote": "^4.4.1", @@ -42,8 +43,8 @@ "remark-parse": "^10.0.2", "remark-slug": "^5.1.2", "remark-stringify": "^7.0.3", - "rescript": "^11.0.0", "request": "^2.88.0", + "rescript": "^11.0.0", "stringify-object": "^3.3.0", "unified": "^8.4.0" }, diff --git a/plugins/rescript-highlightjs.js b/plugins/rescript-highlightjs.js deleted file mode 100644 index 9646b26d8..000000000 --- a/plugins/rescript-highlightjs.js +++ /dev/null @@ -1,365 +0,0 @@ -/* -Language: ReScript -Author: Gidi Meir Morris , Cheng Lou, Patrick Ecker -Category: common -*/ - -// Note: Extracted and adapted from the reason-highlightjs package: -// https://github.com/reasonml-editor/reason-highlightjs -export default function(hljs) { - function orReValues(ops){ - return ops - .map(function(op) { - return op - .split('') - .map(function(char) { - return '\\' + char; - }) - .join(''); - }) - .join('|'); - } - - var RE_IDENT = '[a-z_][0-9a-zA-Z_]*'; - var RE_ATTRIBUTE = '[A-Za-z_][A-Za-z0-9_\\.]*'; - var RE_MODULE_IDENT = '[A-Z_][0-9a-zA-Z_]*'; - - var KEYWORDS = { - // See: https://github.com/rescript-lang/syntax/blob/4872b983eb023f78a972063eb367339e6897bf16/src/res_token.ml#L166 - keyword: - 'and as assert catch constraint downto else exception export external false for ' + - 'if import in include lazy let module mutable of open private rec switch ' + - 'to true try type when while with async await', - // not reliable - //built_in: - //'array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 ref string unit', - literal: - 'true false' - }; - - const STRING_MODE = { - className: 'string', - variants: [ - { - begin: '"', - end: '"', - contains: [hljs.BACKSLASH_ESCAPE], - }, - // {foo|bla|foo} - { - begin: '\\{(' + RE_IDENT + ')?\\|', - end: '\\|(' + RE_IDENT + ')?\\}', - }, - { - begin: '(' + RE_IDENT + ')?`', - end: '`', - }, - ] - }; - - const FUNCTION_MODE = { - className: 'function', - begin: '=>', - }; - - const CHARACTER_MODE = { - className: 'character', - begin: '\'[\\x00-\\x7F]\'', - relevance: 0 - }; - - const NUMBER_MODE = { - className: 'number', - relevance: 0, - begin: '\\b(0[xX][a-fA-F0-9_]+[Lln]?|' + - '0[oO][0-7_]+[Lln]?|' + - '0[bB][01_]+[Lln]?|' + - '[0-9][0-9_]*([Lln]|(\\.[0-9_]+)?([eE][-+]?[0-9_]+)?)?)\\b' - }; - - const OPERATOR_MODE = { - className: 'operator', - relevance: 0, - begin: "("+ orReValues([ - '->', '||', '&&', '++', '**', '+.', '+', '-.', '-', - '*.', '*', '/.', '/', '...', '..', '|>', '===', '==', '^', - ':=', '!', '>=', '<=', - ]) + ")" - }; - - const ASSIGNMENT_MODE = { - className: 'operator', - begin: '=' - }; - - // as in variant constructor - const CONSTRUCTOR_MODE = { - className: 'constructor', - begin: '\\b([A-Z][0-9a-zA-Z_]*)|(`[a-zA-Z][0-9a-zA-Z_]*)|(#[a-zA-Z][0-9a-zA-Z_]*)\\b', - }; - - const ARRAY_MODES = { - className: 'literal', - variants: [ - { - begin: '\\[\\|', - }, - { - begin: '\\|\\]', - }, - ] - }; - - const LIST_MODES = { - className: 'literal', - variants: [ - { - begin: 'list\\{', - }, - { - begin: '\\{', - }, - { - begin: '\\}', - }, - ] - }; - - const OBJECT_ACCESS_MODE = { - className: 'object-access', - variants: [ - { - begin: RE_IDENT + '\\[', - end: '\\]', - contains: [ - // hljs.BACKSLASH_ESCAPE - STRING_MODE - ], - }, - ] - }; - - const MODULE_ACCESS_MODE = { - begin: "\\b" + RE_MODULE_IDENT + "\\.", - returnBegin: true, - contains: [ - { - begin: RE_MODULE_IDENT, - className: 'module-identifier', - }, - ] - }; - - const JSX_MODE = { - variants: [ - { - begin: "<>||/>", - }, - { - begin: " ... - { - begin: "\\s*:\\s*", - contains: [ - { - begin: RE_MODULE_IDENT, - className: "module-identifier", - }, - MODULE_MODE, - { - begin: "\\s*,\\s*", - } - ] - }, - MODULE_MODE, - ] - }, - MODULE_MODE, - { - begin: "\\s*=>\\s*" - } - ] - }, - ] - }; - MODULE_MODE.contains.unshift(MODULE_DECLARATION_MODE); - OPEN_OR_INCLUDE_MODULE_MODE.contains.push(MODULE_MODE) - - return { - aliases: ['res', 'resi'], - keywords: KEYWORDS, - illegal: '(:\\-|:=|\\${|\\+=)', - // lol beautiful - contains: MODULE_MODE.contains, - }; -} diff --git a/src/common/App.res b/src/common/App.res index 335148b62..d22b802ee 100644 --- a/src/common/App.res +++ b/src/common/App.res @@ -12,7 +12,7 @@ import css from 'highlight.js/lib/languages/css' import ocaml from 'highlight.js/lib/languages/ocaml' import reason from 'plugins/reason-highlightjs' - import rescript from 'plugins/rescript-highlightjs' + import rescript from 'highlightjs-rescript' import bash from 'highlight.js/lib/languages/bash' import json from 'highlight.js/lib/languages/json' import html from 'highlight.js/lib/languages/xml' diff --git a/src/common/HighlightJs.res b/src/common/HighlightJs.res index 70c97ac49..5ad29453e 100644 --- a/src/common/HighlightJs.res +++ b/src/common/HighlightJs.res @@ -3,7 +3,7 @@ type options = {language: string} @deriving(abstract) type highlightResult = {value: string} -@module("highlight.js/lib/core") +@module("highlight.js/lib/core") @scope("default") external highlight: (~code: string, ~options: options) => highlightResult = "highlight" let renderHLJS = (~highlightedLines=[], ~darkmode=false, ~code: string, ~lang: string, ()) => { From 8dea5b02cbc9c1ea8390cd11b29417295d15c5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 1 Feb 2024 14:59:45 +0100 Subject: [PATCH 09/13] add rescript v11.1-rc.1 to compiler dependencies --- compilers/package-lock.json | 21 +++++++++++++++++++++ compilers/package.json | 1 + 2 files changed, 22 insertions(+) diff --git a/compilers/package-lock.json b/compilers/package-lock.json index 026e96b43..00b72fd22 100644 --- a/compilers/package-lock.json +++ b/compilers/package-lock.json @@ -13,6 +13,7 @@ "rescript-1000": "npm:rescript@10.0.0", "rescript-1010": "npm:rescript@10.1.0", "rescript-1100": "npm:rescript@11.0.0", + "rescript-1110": "npm:rescript@11.1.0-rc.1", "rescript-820": "npm:bs-platform@8.2.0", "rescript-902": "npm:bs-platform@9.0.2", "rescript-912": "npm:rescript@9.1.2" @@ -80,6 +81,21 @@ "node": ">=10" } }, + "node_modules/rescript-1110": { + "name": "rescript", + "version": "11.1.0-rc.1", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.1.0-rc.1.tgz", + "integrity": "sha512-EGm6Es+Cbrpct0sDnHY2oRTsrtVzKmuCio9EEIFnznSlLIt3ZmJvFQiZ94m0CwHQP68tS0YRO7HlR/HS/nZJRw==", + "hasInstallScript": true, + "bin": { + "bsc": "bsc", + "bstracing": "lib/bstracing", + "rescript": "rescript" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/rescript-820": { "name": "bs-platform", "version": "8.2.0", @@ -134,6 +150,11 @@ "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.0.0.tgz", "integrity": "sha512-uIUwDZZmDUb7ymGkBiiGioxMg8hXh1mze/2k/qhYQcZGgi7PrLHQIW9AksM7gb9WnpjCAvFsA8U2VgC0nA468w==" }, + "rescript-1110": { + "version": "npm:rescript@11.1.0-rc.1", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.1.0-rc.1.tgz", + "integrity": "sha512-EGm6Es+Cbrpct0sDnHY2oRTsrtVzKmuCio9EEIFnznSlLIt3ZmJvFQiZ94m0CwHQP68tS0YRO7HlR/HS/nZJRw==" + }, "rescript-820": { "version": "npm:bs-platform@8.2.0", "resolved": "https://registry.npmjs.org/bs-platform/-/bs-platform-8.2.0.tgz", diff --git a/compilers/package.json b/compilers/package.json index 4534cb2e8..bd8776b74 100644 --- a/compilers/package.json +++ b/compilers/package.json @@ -9,6 +9,7 @@ "rescript-1000": "npm:rescript@10.0.0", "rescript-1010": "npm:rescript@10.1.0", "rescript-1100": "npm:rescript@11.0.0", + "rescript-1110": "npm:rescript@11.1.0-rc.1", "rescript-820": "npm:bs-platform@8.2.0", "rescript-902": "npm:bs-platform@9.0.2", "rescript-912": "npm:rescript@9.1.2" From 068915d1bd634408d89476745333c2653c34f536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 1 Feb 2024 15:27:47 +0100 Subject: [PATCH 10/13] capitalize correctly ReScript --- pages/docs/manual/latest/bind-to-js-function.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/docs/manual/latest/bind-to-js-function.mdx b/pages/docs/manual/latest/bind-to-js-function.mdx index ae165208f..012ffbd6c 100644 --- a/pages/docs/manual/latest/bind-to-js-function.mdx +++ b/pages/docs/manual/latest/bind-to-js-function.mdx @@ -428,7 +428,7 @@ Currently 4 directives are supported: `null_to_opt`, `undefined_to_opt`, `nullab **Experimental** You can easily bind to [JS tagged template functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates). Tag functions in JS expect as input an array of strings and variadic parameters for the arguments of the interpolation. -To bind to those functions in rescript, the binding signature must have two arrays as arguments, +To bind to those functions in ReScript, the binding signature must have two arrays as arguments, the first one being an array of strings and the second can be an array of anything. You add the `@taggedTemplate` annotation and you're good to go! From 7bf0c59b258ebc6f3bf7c56147a993ccddb1fa6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 1 Feb 2024 16:25:11 +0100 Subject: [PATCH 11/13] run the examples with rescript 11.1 --- scripts/test-examples.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test-examples.mjs b/scripts/test-examples.mjs index 7e01509f7..e91bad7b2 100644 --- a/scripts/test-examples.mjs +++ b/scripts/test-examples.mjs @@ -14,8 +14,8 @@ let tempFileNameRegex = /_tempFile\.res/g // see the package.json on how to define another rescript version let compilersDir = path.join(__dirname, "..", "compilers") -let bsc = path.join(compilersDir, 'node_modules', 'rescript-1100', process.platform, 'bsc.exe'); -let rescriptBin = path.join(compilersDir, 'node_modules', 'rescript-1100', 'rescript'); +let bsc = path.join(compilersDir, 'node_modules', 'rescript-1110', process.platform, 'bsc.exe'); +let rescriptBin = path.join(compilersDir, 'node_modules', 'rescript-1110', 'rescript'); let rescriptCoreCompiled = path.join(compilersDir, 'node_modules', '@rescript', 'core', 'lib', 'ocaml'); const prepareCompilers = () => { From 34ca0672964cf5f413caf731f6a6f367dc1cce54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 1 Feb 2024 16:30:06 +0100 Subject: [PATCH 12/13] add @rescript/react as a dependency for examples --- compilers/package-lock.json | 111 ++++++++++++++++++++++++++++++++++++ compilers/package.json | 1 + compilers/rescript.json | 3 +- 3 files changed, 114 insertions(+), 1 deletion(-) diff --git a/compilers/package-lock.json b/compilers/package-lock.json index 00b72fd22..c884d0f87 100644 --- a/compilers/package-lock.json +++ b/compilers/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "@rescript/core": "^0.6.0", + "@rescript/react": "^0.12.0", "rescript-1000": "npm:rescript@10.0.0", "rescript-1010": "npm:rescript@10.1.0", "rescript-1100": "npm:rescript@11.0.0", @@ -27,6 +28,58 @@ "rescript": "^10.1.0 || ^11.0.0-alpha.0 || next" } }, + "node_modules/@rescript/react": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@rescript/react/-/react-0.12.0.tgz", + "integrity": "sha512-EBLsf5rD7sJOjgfLLGwuLw/hONszc3UtYnIVgv7OdTyUNR41/m4deVm62PI0agvr3kWakXz4KchKRSd+19/bRA==", + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "peer": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/rescript": { "version": "10.1.4", "resolved": "https://registry.npmjs.org/rescript/-/rescript-10.1.4.tgz", @@ -120,6 +173,15 @@ "bstracing": "lib/bstracing", "rescript": "rescript" } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } } }, "dependencies": { @@ -129,6 +191,46 @@ "integrity": "sha512-D4ykxSpbmxbQa99kCg6/DztwCNt1tV3t11BLSOvJPHNLSIuQxfAU3ddgRruaH9LQSKOrMUjxQS9z6RdG5iFPoA==", "requires": {} }, + "@rescript/react": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@rescript/react/-/react-0.12.0.tgz", + "integrity": "sha512-EBLsf5rD7sJOjgfLLGwuLw/hONszc3UtYnIVgv7OdTyUNR41/m4deVm62PI0agvr3kWakXz4KchKRSd+19/bRA==", + "requires": {} + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "peer": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, + "react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + } + }, "rescript": { "version": "10.1.4", "resolved": "https://registry.npmjs.org/rescript/-/rescript-10.1.4.tgz", @@ -169,6 +271,15 @@ "version": "npm:rescript@9.1.2", "resolved": "https://registry.npmjs.org/rescript/-/rescript-9.1.2.tgz", "integrity": "sha512-4wHvTDv3nyYnAPJHcg1RGG8z7u3HDiBf6RN3P/dITDv859Qo35aKOzJWQtfBzbAs0EKNafLqei3TnUqiAv6BwQ==" + }, + "scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } } } } diff --git a/compilers/package.json b/compilers/package.json index bd8776b74..7d9531278 100644 --- a/compilers/package.json +++ b/compilers/package.json @@ -6,6 +6,7 @@ "license": "MIT", "dependencies": { "@rescript/core": "^0.6.0", + "@rescript/react": "^0.12.0", "rescript-1000": "npm:rescript@10.0.0", "rescript-1010": "npm:rescript@10.1.0", "rescript-1100": "npm:rescript@11.0.0", diff --git a/compilers/rescript.json b/compilers/rescript.json index 53fd7f5ef..ef3b45e6c 100644 --- a/compilers/rescript.json +++ b/compilers/rescript.json @@ -5,7 +5,8 @@ "subdirs": true }, "bs-dependencies": [ - "@rescript/core" + "@rescript/core", + "@rescript/react" ], "bsc-flags": [ "-open RescriptCore" From 137e18d11f7071f60d5cc43f6eea0aeda3fc7bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20Tsnobiladz=C3=A9?= Date: Thu, 1 Feb 2024 16:45:34 +0100 Subject: [PATCH 13/13] configure react and jsx when building examples --- compilers/rescript.json | 1 + scripts/test-examples.mjs | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/compilers/rescript.json b/compilers/rescript.json index ef3b45e6c..2b29c743a 100644 --- a/compilers/rescript.json +++ b/compilers/rescript.json @@ -1,5 +1,6 @@ { "name": "dummy", + "jsx": { "version": 4 }, "sources": { "dir": "dummy", "subdirs": true diff --git a/scripts/test-examples.mjs b/scripts/test-examples.mjs index e91bad7b2..dc68c9c5a 100644 --- a/scripts/test-examples.mjs +++ b/scripts/test-examples.mjs @@ -17,6 +17,7 @@ let compilersDir = path.join(__dirname, "..", "compilers") let bsc = path.join(compilersDir, 'node_modules', 'rescript-1110', process.platform, 'bsc.exe'); let rescriptBin = path.join(compilersDir, 'node_modules', 'rescript-1110', 'rescript'); let rescriptCoreCompiled = path.join(compilersDir, 'node_modules', '@rescript', 'core', 'lib', 'ocaml'); +let rescriptReactCompiled = path.join(compilersDir, 'node_modules', '@rescript', 'react', 'lib', 'ocaml'); const prepareCompilers = () => { if (fs.existsSync(bsc)) { @@ -26,11 +27,11 @@ const prepareCompilers = () => { child_process.execFileSync("npm", ['install'], {cwd: compilersDir}) } -const prepareRescriptCore = () => { - if (fs.existsSync(rescriptCoreCompiled)) { +const prepareDependencies = () => { + if (fs.existsSync(rescriptCoreCompiled) && fs.existsSync(rescriptReactCompiled)) { return; } - console.log("Rescript Core not installed. Installing..."); + console.log("Dependencies not installed. Installing..."); child_process.execFileSync(rescriptBin, [], {cwd: compilersDir}) } @@ -79,7 +80,7 @@ let postprocessOutput = (file, error) => { prepareCompilers(); -prepareRescriptCore(); +prepareDependencies(); console.log("Running tests...") fs.writeFileSync(tempFileName, '') @@ -100,6 +101,10 @@ glob.sync(__dirname + '/../pages/docs/manual/latest/**/*.mdx').forEach((file) => tempFileName, '-I', rescriptCoreCompiled, + '-I', + rescriptReactCompiled, + '-bs-jsx', + '4', '-w', '-109', '-uncurried',