diff --git a/compilers/package-lock.json b/compilers/package-lock.json index 026e96b43..c884d0f87 100644 --- a/compilers/package-lock.json +++ b/compilers/package-lock.json @@ -10,9 +10,11 @@ "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", + "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" @@ -26,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", @@ -80,6 +134,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", @@ -104,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": { @@ -113,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", @@ -134,6 +252,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", @@ -148,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 4534cb2e8..7d9531278 100644 --- a/compilers/package.json +++ b/compilers/package.json @@ -6,9 +6,11 @@ "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", + "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" diff --git a/compilers/rescript.json b/compilers/rescript.json index 53fd7f5ef..2b29c743a 100644 --- a/compilers/rescript.json +++ b/compilers/rescript.json @@ -1,11 +1,13 @@ { "name": "dummy", + "jsx": { "version": 4 }, "sources": { "dir": "dummy", "subdirs": true }, "bs-dependencies": [ - "@rescript/core" + "@rescript/core", + "@rescript/react" ], "bsc-flags": [ "-open RescriptCore" 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/misc_docs/syntax/decorator_taggedTemplate.mdx b/misc_docs/syntax/decorator_taggedTemplate.mdx new file mode 100644 index 000000000..c6edd9690 --- /dev/null +++ b/misc_docs/syntax/decorator_taggedTemplate.mdx @@ -0,0 +1,36 @@ +--- +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 +// see https://bun.sh/docs/runtime/shell +type result = {exitCode: int} +@module("bun") @taggedTemplate +external sh: (array, array) => promise = "$" + +let filename = "index.res" +let result = await sh`ls ${filename}` +``` + +```js +import * as $$Bun from "bun"; +var filename = "index.res"; +var result = 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/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/pages/docs/manual/latest/bind-to-js-function.mdx b/pages/docs/manual/latest/bind-to-js-function.mdx index 2c8e60b03..012ffbd6c 100644 --- a/pages/docs/manual/latest/bind-to-js-function.mdx +++ b/pages/docs/manual/latest/bind-to-js-function.mdx @@ -421,3 +421,39 @@ 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](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, +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 +// see https://bun.sh/docs/runtime/shell +type result = {exitCode: int} +@module("bun") @taggedTemplate +external sh: (array, array) => promise = "$" + +let filename = "index.res" +let result = await sh`ls ${filename}` +``` + +```js +import * as $$Bun from "bun"; +var filename = "index.res"; +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 diff --git a/pages/docs/manual/latest/interop-cheatsheet.mdx b/pages/docs/manual/latest/interop-cheatsheet.mdx index 54b2b14b3..ecbe369dd 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,28 @@ external join: array => string = "join" +### Tagged template functions + + + +```res example +// see https://bun.sh/docs/runtime/shell +type result = {exitCode: int} +@module("bun") @taggedTemplate +external sh: (array, array) => promise = "$" + +let filename = "index.res" +let result = await sh`ls ${filename}` +``` + +```js +import * as $$Bun from "bun"; +var filename = "index.res"; +var result = 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 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 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/scripts/test-examples.mjs b/scripts/test-examples.mjs index 7e01509f7..dc68c9c5a 100644 --- a/scripts/test-examples.mjs +++ b/scripts/test-examples.mjs @@ -14,9 +14,10 @@ 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'); +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', 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/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"), 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, ()) => {