diff --git a/docs/languages.md b/docs/languages.md index 097de693b..3fb7767ed 100644 --- a/docs/languages.md +++ b/docs/languages.md @@ -177,6 +177,7 @@ export type Lang = | 'r' | 'raku' | 'perl6' | 'razor' + | 'reason' | 'reg' | 'rel' | 'riscv' diff --git a/packages/shiki/languages/reason.tmLanguage.json b/packages/shiki/languages/reason.tmLanguage.json new file mode 100644 index 000000000..f37db3046 --- /dev/null +++ b/packages/shiki/languages/reason.tmLanguage.json @@ -0,0 +1,3395 @@ +{ + "name": "reason", + "scopeName": "source.reason", + "fileTypes": ["re", "rei"], + "patterns": [ + { + "include": "#structure-expression-block-item" + }, + { + "include": "#value-expression" + } + ], + "repository": { + "attribute": { + "begin": "(?=\\[(@{1,3})[[:space:]]*[[:alpha:]])", + "end": "\\]", + "patterns": [ + { + "begin": "\\[(@{1,3})", + "end": "(?=[^_\\.'[:word:]])", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#attribute-identifier" + } + ] + }, + { + "include": "#attribute-payload" + } + ] + }, + "attribute-identifier": { + "patterns": [ + { + "match": "\\b([[:alpha:]][[:word:]]*)\\b[[:space:]]*(?:(\\.))", + "captures": { + "1": { + "name": "support.class entity.name.class" + }, + "2": { + "name": "keyword.control.less" + } + } + }, + { + "match": "\\b([[:alpha:]][[:word:]]*)\\b", + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + ] + }, + "attribute-payload": { + "patterns": [ + { + "begin": "(:)", + "end": "(?=\\])", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#structure-expression" + }, + { + "include": "#module-item-type" + }, + { + "include": "#type-expression" + } + ] + }, + { + "begin": "([\\?])", + "end": "(?=\\])", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#pattern-guard" + }, + { + "include": "#pattern" + } + ] + }, + { + "include": "#structure-expression-block-item" + }, + { + "include": "#value-expression" + } + ] + }, + "class-item-inherit": { + "begin": "\\b(inherit)\\b", + "end": "(;)|(?=}|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.other" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#value-expression" + } + ] + }, + "class-item-method": { + "begin": "\\b(method)\\b", + "end": "(;)|(?=}|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "storage.type" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#module-item-let-value-bind-name-params-type-body" + } + ] + }, + "comment": { + "name": "comment", + "patterns": [ + { + "include": "#comment-line" + }, + { + "include": "#comment-block-doc" + }, + { + "include": "#comment-block" + } + ] + }, + "comment-line": { + "name": "comment.line", + "begin": "(^[ \\t]+)?((//))", + "end": "(?=^)" + }, + "comment-block": { + "begin": "/\\*", + "end": "\\*/", + "name": "comment.block", + "patterns": [ + { + "include": "#comment-block-doc" + }, + { + "include": "#comment-block" + } + ] + }, + "comment-block-doc": { + "begin": "/\\*\\*(?!/)", + "end": "\\*/", + "name": "comment.block.documentation", + "patterns": [ + { + "include": "#comment-block-doc" + }, + { + "include": "#comment-block" + } + ] + }, + "condition-lhs": { + "begin": "(?|~$\\\\])([\\?])(?![#\\-:!?.@*/&%^+<=>|~$\\\\])", + "end": "(?=[\\)])", + "beginCaptures": { + "1": { + "name": "keyword.control message.error variable.interpolation" + } + }, + "patterns": [ + { + "match": "(?:\\b|[[:space:]]+)([?])(?:\\b|[[:space:]]+)", + "name": "keyword.control message.error variable.interpolation" + }, + { + "include": "#value-expression" + } + ] + }, + "extension-node": { + "begin": "(?=\\[(%{1,3})[[:space:]]*[[:alpha:]])", + "end": "\\]", + "patterns": [ + { + "begin": "\\[(%{1,3})", + "end": "(?=[^_\\.'[:word:]])\\:?", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#attribute-identifier" + } + ] + }, + { + "include": "#attribute-payload" + } + ] + }, + "jsx": { + "patterns": [ + { + "include": "#jsx-head" + }, + { + "include": "#jsx-tail" + } + ] + }, + "jsx-attributes": { + "patterns": [ + { + "begin": "\\b([[:lower:]][[:word:]]*)\\b[[:space:]]*(=)", + "end": "(?[:lower:]])", + "comment": "meta.separator", + "beginCaptures": { + "1": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + }, + "2": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#value-expression-atomic-with-paths" + } + ] + }, + { + "match": "(\\b([[:lower:]][[:word:]]*)\\b[[:space:]]*+)", + "captures": { + "1": { + "comment": "meta.separator" + }, + "2": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + } + } + } + ] + }, + "jsx-body": { + "begin": "((>))", + "end": "(?=))|(?=])[[:space:]]*+", + "comment": "meta.separator", + "patterns": [ + { + "include": "#module-path-simple" + }, + { + "match": "\\b[[:lower:]][[:word:]]*\\b", + "name": "entity.name.tag.inline.any.html" + } + ] + }, + { + "include": "#jsx-attributes" + }, + { + "include": "#jsx-body" + }, + { + "include": "#comment" + } + ] + }, + "jsx-tail": { + "begin": "\\G(/>)|()", + "applyEndPatternLast": true, + "comment": "meta.separator", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.end.js" + }, + "2": { + "name": "punctuation.definition.tag.begin.js" + } + }, + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.end.js" + } + }, + "patterns": [ + { + "include": "#module-path-simple" + }, + { + "match": "\\b[[:lower:]][[:word:]]*\\b", + "name": "entity.name.tag.inline.any.html" + } + ] + }, + "module-name-extended": { + "patterns": [ + { + "include": "#module-name-simple" + }, + { + "begin": "([\\(])", + "end": "([\\)])", + "captures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + }, + "patterns": [ + { + "include": "#module-path-extended" + } + ] + } + ] + }, + "module-name-simple": { + "match": "\\b[[:upper:]][[:word:]]*\\b", + "name": "support.class entity.name.class" + }, + "module-path-extended": { + "patterns": [ + { + "include": "#module-name-extended" + }, + { + "include": "#comment" + }, + { + "comment": "NOTE: end early to avoid too much reparsing", + "begin": "([\\.])", + "end": "(?<=[[:word:]\\)])|(?=[^\\.[:upper:]/])", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "begin": "(?<=[\\.])", + "end": "(?<=[[:word:]\\)])|(?=[^\\.[:upper:]/])", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-name-extended" + } + ] + } + ] + } + ] + }, + "module-path-extended-prefix": { + "begin": "(?=\\b[[:upper:]])", + "end": "([\\.])|(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#module-path-extended" + } + ] + }, + "module-path-simple": { + "patterns": [ + { + "include": "#module-name-simple" + }, + { + "include": "#comment" + }, + { + "comment": "NOTE: end early to avoid too much reparsing", + "begin": "([\\.])", + "end": "(?<=[[:word:]\\)])|(?=[^\\.[:upper:]/])", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "begin": "(?<=[\\.])", + "end": "(?<=[[:word:]\\)])|(?=[^\\.[:upper:]/])", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-name-simple" + } + ] + } + ] + } + ] + }, + "module-path-simple-prefix": { + "begin": "(?=\\b[[:upper:]])", + "end": "([\\.])|(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#module-path-simple" + } + ] + }, + "module-item-class-type": { + "comment": "FIXME: proper parsing", + "begin": "\\b(class)\\b", + "end": "(;)|(?=}|\\b(and|class|constraint|exception|external|include|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.other" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "begin": "(?:\\G|^)[[:space:]]*\\b(type)\\b", + "end": "(?==)", + "beginCaptures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + }, + "patterns": [ + { + "include": "#module-item-type-bind-name-tyvars" + } + ] + }, + { + "begin": "(=)", + "end": "(?=;)", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#attribute" + }, + { + "include": "#comment" + }, + { + "include": "#class-item-inherit" + }, + { + "include": "#class-item-method" + } + ] + } + ] + }, + "module-item-exception": { + "begin": "\\b(exception)\\b", + "end": "(;)|(?=}|\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.other" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#module-item-type-bind-body-item" + } + ] + }, + "module-item-external": { + "begin": "\\b(external)\\b", + "end": "(;)|(?=}|\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "storage.type" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#module-item-let-value-bind-name-or-pattern" + }, + { + "include": "#module-item-let-value-bind-type" + }, + { + "begin": "(=)", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#attribute" + }, + { + "begin": "\"", + "end": "\"", + "name": "string.double string.regexp", + "patterns": [ + { + "include": "#value-literal-string-escape" + }, + { + "match": "(?:(%)(.*?)|(caml.*?))(?=\"|(?:[^\\\\\\n]$))", + "captures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + }, + "2": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "3": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + } + } + ] + } + ] + } + ] + }, + "module-item-include": { + "begin": "\\b(include)\\b", + "end": "(;)|(?=}|\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.include" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#signature-expression" + } + ] + }, + "module-item-let": { + "begin": "\\b(let)((%)([[:word:]\\.]+))?\\b", + "end": "(;)|(?=}|\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "storage.type" + }, + "3": { + "name": "keyword.control.less" + }, + "4": { + "name": "entity.name.class" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#module-item-let-module" + }, + { + "include": "#module-item-let-value" + } + ] + }, + "module-item-let-module": { + "begin": "(?:\\G|^)[[:space:]]*\\b(module)\\b", + "end": "(?=[;}]|\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.control storage.type message.error" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-item-let-module-and" + }, + { + "include": "#module-item-let-module-rec" + }, + { + "include": "#module-item-let-module-bind-name-params-type-body" + } + ] + }, + "module-item-let-module-and": { + "begin": "\\b(and)\\b", + "end": "(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "storage.type" + } + }, + "patterns": [ + { + "include": "#module-item-let-module-bind-name-params-type-body" + } + ] + }, + "module-item-let-module-bind-body": { + "begin": "(=>?)", + "end": "(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#structure-expression" + }, + { + "include": "#extension-node" + } + ] + }, + "module-item-let-module-bind-name-params": { + "begin": "\\b([[:upper:]][[:word:]]*)\\b", + "end": "(?=[;:}=]|\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "support.class entity.name.class" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-item-let-module-param" + } + ] + }, + "module-item-let-module-bind-name-params-type-body": { + "begin": "(?:\\G|^)", + "end": "(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-item-let-module-bind-name-params" + }, + { + "include": "#module-item-let-module-bind-type" + }, + { + "include": "#module-item-let-module-bind-body" + } + ] + }, + "module-item-let-module-bind-type": { + "begin": "(:)", + "end": "(?=[;}=]|\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#signature-expression" + } + ] + }, + "module-item-let-module-param": { + "begin": "(?=\\()", + "end": "\\)", + "patterns": [ + { + "begin": "\\(", + "end": "(?=[:])", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-name-simple" + } + ] + }, + { + "begin": "(:)", + "end": "(?=\\))", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#signature-expression" + } + ] + } + ] + }, + "module-item-let-module-rec": { + "begin": "(?:\\G|^)[[:space:]]*\\b(rec)\\b", + "end": "(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control storage.modifier.rec" + } + }, + "patterns": [ + { + "include": "#module-item-let-module-bind-name-params-type-body" + } + ] + }, + "module-item-let-value": { + "patterns": [ + { + "include": "#module-item-let-value-and" + }, + { + "include": "#module-item-let-value-rec" + }, + { + "include": "#module-item-let-value-bind-name-params-type-body" + } + ] + }, + "module-item-let-value-and": { + "begin": "\\b(and)\\b", + "end": "(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "storage.type" + } + }, + "patterns": [ + { + "include": "#module-item-let-value-bind-name-params-type-body" + } + ] + }, + "module-item-let-value-bind-body": { + "begin": "(=>?)", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#value-expression" + } + ] + }, + "module-item-let-value-bind-name-or-pattern": { + "end": "(?<=[^[:space:]])|(?=[[:space:]]|[;:}=]|\\b(and|as|class|constraint|exception|external|for|include|inherit|let|method|module|nonrec|open|private|rec|switch|try|type|val|while|with)\\b)", + "patterns": [ + { + "include": "#comment" + }, + { + "match": "\\b(?:([_][[:word:]]+)|([[:lower:]][[:word:]]*))\\b", + "captures": { + "1": { + "name": "comment" + }, + "2": { + "name": "entity.name.function" + } + } + }, + { + "include": "#module-item-let-value-bind-parens-params" + }, + { + "include": "#pattern" + } + ] + }, + "module-item-let-value-bind-name-params-type-body": { + "end": "(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "patterns": [ + { + "include": "#module-item-let-value-bind-name-or-pattern" + }, + { + "include": "#module-item-let-value-bind-params-type" + }, + { + "include": "#module-item-let-value-bind-type" + }, + { + "include": "#module-item-let-value-bind-body" + } + ] + }, + "module-item-let-value-bind-params-type": { + "begin": "(?=[^[:space:]:=])", + "end": "(?=[;}=]|\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-item-let-value-param" + }, + { + "begin": "(?]|[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "begin": "\\b(type)\\b", + "end": "([\\.])", + "beginCaptures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + }, + "endCaptures": { + "1": { + "name": "entity.name.function" + } + }, + "patterns": [ + { + "include": "#pattern-variable" + } + ] + }, + { + "include": "#type-expression" + } + ] + }, + "module-item-let-value-param": { + "patterns": [ + { + "include": "#module-item-let-value-param-label" + }, + { + "include": "#module-item-let-value-param-type" + }, + { + "include": "#module-item-let-value-param-module" + }, + { + "include": "#pattern" + } + ] + }, + "module-item-let-value-param-label": { + "patterns": [ + { + "begin": "(\\b[[:lower:]][[:word:]]*\\b)?[[:space:]]*(::)", + "end": "(?<=[[:space:]])", + "beginCaptures": { + "1": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + }, + "2": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#pattern" + }, + { + "begin": "(=)", + "end": "(\\?)|(?<=[^[:space:]=][[:space:]])(?=[[:space:]]*+[^\\.])", + "beginCaptures": { + "1": { + "name": "markup.inserted keyword.control.less message.error" + } + }, + "endCaptures": { + "1": { + "name": "storage.type" + } + }, + "patterns": [ + { + "include": "#value-expression-atomic-with-paths" + } + ] + } + ] + } + ] + }, + "module-item-let-value-param-module": { + "comment": "FIXME: merge with pattern-parens", + "begin": "\\([[:space:]]*(?=\\b(module)\\b)", + "end": "\\)", + "patterns": [ + { + "begin": "\\b(module)\\b", + "end": "(?=\\))", + "beginCaptures": { + "1": { + "name": "keyword.other message.error" + } + }, + "patterns": [ + { + "match": "\\b[[:upper:]][[:word:]]*\\b", + "name": "support.class entity.name.class" + } + ] + } + ] + }, + "module-item-let-value-param-type": { + "comment": "FIXME: merge with pattern-parens", + "begin": "\\((?=\\b(type)\\b)", + "end": "\\)", + "patterns": [ + { + "begin": "\\b(type)\\b", + "end": "(?=\\))", + "beginCaptures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + }, + "patterns": [ + { + "include": "#pattern-variable" + } + ] + } + ] + }, + "module-item-let-value-rec": { + "begin": "(?:\\G|^)[[:space:]]*\\b(rec)\\b", + "end": "(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control storage.modifier message.error" + } + }, + "patterns": [ + { + "include": "#module-item-let-value-bind-name-params-type-body" + } + ] + }, + "module-item-module": { + "comment": "NOTE: this is to support the let-module case without the let prefix", + "begin": "\\b(module)\\b[[:space:]]*(?!\\b(type)\\b|$)", + "end": "(;)|(?=}|\\b(class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "storage.type message.error" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#module-item-let-module-and" + }, + { + "include": "#module-item-let-module-rec" + }, + { + "include": "#module-item-let-module-bind-name-params-type-body" + } + ] + }, + "module-item-module-type": { + "begin": "\\b(module)\\b[[:space:]]*(?=\\b(type)\\b|$)", + "end": "(;)|(?=}|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control message.error" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "begin": "(?:\\G|^)[[:space:]]*\\b(type)\\b", + "end": "(?==)", + "beginCaptures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "match": "([[:upper:]][[:word:]]*)", + "captures": { + "1": { + "name": "support.class entity.name.class" + } + } + } + ] + }, + { + "begin": "(=)", + "end": "(?=;)", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#signature-expression" + } + ] + } + ] + }, + "module-item-open": { + "begin": "\\b(open)\\b", + "end": "(;)|(?=}|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.open" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-path-simple" + } + ] + }, + "module-item-type": { + "comment": "FIXME: the semi-colon is optional so we can re-use this for hover, which does not print the trailing ;", + "begin": "\\b(type)\\b", + "end": "(;)|(?=[\\)}]|\\b(class|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.other" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#module-item-type-and" + }, + { + "include": "#module-item-type-constraint" + }, + { + "include": "#module-item-type-bind" + } + ] + }, + "module-item-type-and": { + "comment": "FIXME: the optional `type` is for module constraints", + "begin": "\\b(and)\\b([[:space:]]*type)?", + "end": "(?=[;\\)}]|\\b(class|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.other" + }, + "2": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + }, + "patterns": [ + { + "include": "#module-item-type-bind-name-tyvars-body" + } + ] + }, + "module-item-type-bind": { + "comment": "FIXME: only allow module paths before type variables", + "patterns": [ + { + "include": "#module-item-type-bind-nonrec" + }, + { + "include": "#module-item-type-bind-name-tyvars-body" + } + ] + }, + "module-item-type-bind-body": { + "comment": "FIXME: parsing", + "begin": "(\\+?=)", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#module-item-type-bind-body-item" + } + ] + }, + "module-item-type-bind-body-item": { + "patterns": [ + { + "match": "(=)(?!>)|\\b(private)\\b", + "captures": { + "1": { + "name": "keyword.control.less" + }, + "2": { + "name": "variable.other.class.js variable.interpolation storage.modifier message.error" + } + } + }, + { + "comment": "FIXME: specialized version of variant rule that also scans for (", + "match": "\\b([[:upper:]][[:word:]]*)\\b(?![[:space:]]*[\\.\\(])", + "captures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + } + }, + { + "begin": "(\\.\\.)", + "end": "(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + } + }, + { + "begin": "(\\|)(?![#\\-:!?.@*/&%^+<=>|~$\\\\])[[:space:]]*", + "end": "(?=[;\\)}]|\\|(?![#\\-:!?.@*/&%^+<=>|~$\\\\])|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#value-expression-constructor" + }, + { + "match": "([:])|\\b(of)\\b", + "captures": { + "1": { + "name": "keyword.control.less" + }, + "2": { + "name": "keyword.other" + } + } + }, + { + "include": "#type-expression" + } + ] + }, + { + "comment": "FIXME: remove this once the pretty printer no longer outputs 'of'", + "match": "(:)|(\\|(?![#\\-:!?.@*/&%^+<=>|~$\\\\]))|\\b(of)\\b", + "captures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "2": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "3": { + "name": "keyword.other" + } + } + }, + { + "include": "#type-expression" + } + ] + }, + "module-item-type-bind-name-tyvars": { + "begin": "(?<=\\G|^|\\.)[[:space:]]*\\b([[:lower:]][[:word:]]*)\\b", + "end": "(?=\\+?=|[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "entity.name.function" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#attribute" + }, + { + "match": "_", + "name": "comment" + }, + { + "comment": "FIXME: add separate type-variable rule", + "match": "([+\\-])?(?:(_)|(')([[:lower:]][[:word:]]*)\\b)(?!\\.[[:upper:]])", + "captures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "2": { + "name": "comment" + }, + "3": { + "name": "comment" + }, + "4": { + "name": "variable.parameter string.other.link variable.language" + } + } + } + ] + }, + "module-item-type-bind-name-tyvars-body": { + "begin": "(?=(\\G|^)[[:space:]]*\\b[[:alpha:]])", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "patterns": [ + { + "include": "#module-path-simple-prefix" + }, + { + "include": "#module-item-type-bind-name-tyvars" + }, + { + "include": "#module-item-type-bind-body" + } + ] + }, + "module-item-type-bind-nonrec": { + "begin": "(?:\\G|^)[[:space:]]*\\b(nonrec)\\b", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control storage.modifier message.error" + } + }, + "patterns": [ + { + "include": "#module-item-type-bind-name-tyvars-body" + } + ] + }, + "module-item-type-constraint": { + "comment": "FIXME: proper parsing", + "begin": "\\b(constraint)\\b", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation storage.modifier message.error" + } + }, + "patterns": [ + { + "comment": "FIXME: add separate type-variable rule", + "match": "([+\\-])?(')([_[:lower:]][[:word:]]*)\\b(?!\\.[[:upper:]])", + "captures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "2": { + "name": "comment" + }, + "3": { + "name": "variable.parameter string.other.link variable.language" + } + } + }, + { + "match": "=", + "name": "keyword.control.less" + }, + { + "include": "#type-expression" + } + ] + }, + "object-item": { + "begin": "\\G|(;)", + "end": "(?=[;}]|\\b(class|constraint|exception|external|include|let|module|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#class-item-method" + } + ] + }, + "operator": { + "patterns": [ + { + "include": "#operator-infix" + }, + { + "include": "#operator-prefix" + } + ] + }, + "operator-infix": { + "patterns": [ + { + "match": ";", + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + { + "include": "#operator-infix-assign" + }, + { + "include": "#operator-infix-builtin" + }, + { + "include": "#operator-infix-custom" + }, + { + "comment": "#operator-infix-custom-hash" + } + ] + }, + "operator-infix-assign": { + "match": "(?|~$\\\\])(=)(?![#\\-:!?.@*/&%^+<=>|~$\\\\])", + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control.less message.error" + }, + "operator-infix-builtin": { + "match": ":=", + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control.less message.error" + }, + "operator-infix-custom": { + "match": "(?:(?|~$\\\\])((<>))(?![#\\-:!?.@*/&%^+<=>|~$\\\\]))|([#\\-@*/&%^+<=>$\\\\][#\\-:!?.@*/&%^+<=>|~$\\\\]*|[|][#\\-:!?.@*/&%^+<=>|~$\\\\]+)", + "captures": { + "1": { + "comment": "meta.separator" + }, + "2": { + "name": "punctuation.definition.tag.begin.js" + }, + "3": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + } + }, + "operator-infix-custom-hash": { + "match": "#[\\-:!?.@*/&%^+<=>|~$]+", + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "operator-prefix": { + "patterns": [ + { + "include": "#operator-prefix-bang" + }, + { + "include": "#operator-prefix-label-token" + } + ] + }, + "operator-prefix-bang": { + "match": "![\\-:!?.@*/&%^+<=>|~$]*", + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "operator-prefix-label-token": { + "match": "[?~][\\-:!?.@*/&%^+<=>|~$]+", + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "pattern": { + "patterns": [ + { + "include": "#attribute" + }, + { + "include": "#comment" + }, + { + "include": "#pattern-atomic" + }, + { + "match": "[[:space:]]*+(?:(\\|(?![#\\-:!?.@*/&%^+<=>|~$\\\\]))|\\b(as)\\b|(\\.\\.\\.?))[[:space:]]*+", + "captures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "2": { + "name": "keyword.other" + }, + "3": { + "name": "keyword.control" + } + } + } + ] + }, + "pattern-atomic": { + "patterns": [ + { + "match": "\\b(exception)\\b", + "name": "keyword.other" + }, + { + "include": "#value-expression-literal" + }, + { + "include": "#module-path-simple-prefix" + }, + { + "include": "#pattern-list-or-array" + }, + { + "include": "#pattern-record" + }, + { + "include": "#pattern-variable" + }, + { + "include": "#pattern-parens" + } + ] + }, + "pattern-guard": { + "begin": "\\b(when)\\b", + "end": "(?==>)", + "beginCaptures": { + "1": { + "name": "keyword.other" + } + }, + "patterns": [ + { + "include": "#value-expression" + } + ] + }, + "pattern-list-or-array": { + "begin": "(\\[\\|?)(?![@%])", + "end": "(\\|?\\])", + "beginCaptures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + }, + "endCaptures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + }, + "patterns": [ + { + "include": "#value-expression-literal-list-or-array-separator" + }, + { + "include": "#pattern" + } + ] + }, + "pattern-parens": { + "begin": "(?=\\()", + "end": "\\)|(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "patterns": [ + { + "include": "#pattern-parens-lhs" + }, + { + "include": "#type-annotation-rhs" + } + ] + }, + "pattern-parens-lhs": { + "begin": "\\(|(,)", + "end": "(?=(?:[,:\\)]))|(?=[;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#pattern" + } + ] + }, + "record-path": { + "begin": "\\b[[:lower:]][[:word:]]*\\b", + "end": "(?=[^[:space:]\\.])(?!/\\*)", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#record-path-suffix" + } + ] + }, + "record-path-suffix": { + "begin": "(\\.)", + "end": "(\\))|\\b([[:upper:]][[:word:]]*)\\b|\\b([[:lower:]][[:word:]]*)\\b|(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "endCaptures": { + "1": { + "name": "keyword.control" + }, + "2": { + "name": "support.class entity.name.class" + }, + "3": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "([\\(])", + "end": "(?=[\\)])", + "beginCaptures": { + "1": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "match": "\\b([[:lower:]][[:word:]]*)\\b(?=[^\\)]*([\\.]))", + "captures": { + "1": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + }, + "2": { + "name": "keyword.other" + } + } + }, + { + "match": "([\\.])", + "name": "keyword.control.less" + }, + { + "match": "\\b([[:lower:]][[:word:]]*)\\b[[:space:]]*", + "captures": { + "1": { + "name": "variable.parameter string.other.link variable.language" + } + } + }, + { + "include": "#value-expression" + } + ] + } + ] + }, + "pattern-record": { + "begin": "{", + "end": "}", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pattern-record-item" + } + ] + }, + "pattern-record-field": { + "begin": "\\b([_][[:word:]]*)\\b|\\b([[:lower:]][[:word:]]*)\\b", + "end": "(,)|(?=})", + "beginCaptures": { + "1": { + "name": "comment" + }, + "2": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "\\G(:)", + "end": "(?=[,}])", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#pattern" + } + ] + } + ] + }, + "pattern-record-item": { + "patterns": [ + { + "include": "#module-path-simple-prefix" + }, + { + "include": "#pattern-record-field" + } + ] + }, + "pattern-variable": { + "patterns": [ + { + "match": "\\b(_(?:[[:lower:]][[:word:]]*)?)\\b(?!\\.[[:upper:]])", + "captures": { + "1": { + "name": "comment" + } + } + }, + { + "match": "\\b([[:lower:]][[:word:]]*)\\b(?!\\.[[:upper:]])", + "captures": { + "1": { + "name": "variable.language string.other.link" + } + } + } + ] + }, + "signature-expression": { + "patterns": [ + { + "comment": "FIXME: scan for :upper: to disambiguate type/signature in hover", + "begin": "(?=\\([[:space:]]*[[:upper:]][[:word:]]*[[:space:]]*:)", + "end": "(?=[;])", + "patterns": [ + { + "begin": "(?=\\()", + "end": "(?=[;]|=>)", + "patterns": [ + { + "include": "#module-item-let-module-param" + } + ] + }, + { + "begin": "(=>)", + "end": "(?=[;\\(])", + "beginCaptures": { + "1": { + "name": "markup.inserted keyword.control.less" + } + }, + "patterns": [ + { + "include": "#structure-expression" + } + ] + } + ] + }, + { + "begin": "\\b(module)\\b[[:space:]]*\\b(type)\\b([[:space:]]*\\b(of)\\b)?", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "markup.inserted keyword.other variable.other.readwrite.instance" + }, + "2": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + }, + "3": { + "name": "markup.inserted keyword.other variable.other.readwrite.instance" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-path-simple" + }, + { + "match": "\\b([[:upper:]][[:word:]]*)\\b", + "name": "support.class entity.name.class" + } + ] + }, + { + "include": "#signature-expression-constraints" + }, + { + "include": "#structure-expression" + } + ] + }, + "signature-expression-constraints": { + "begin": "(?=\\b(with))", + "end": "(?=[;\\)}]|\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val)\\b)", + "patterns": [ + { + "begin": "\\b(and|with)\\b", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation storage.modifier message.error" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "comment": "FIXME: special version of #module-item-type with non-consuming `;`. Atom seems to need this to work.", + "begin": "\\b(type)\\b", + "end": "(?=[;\\)}]|\\b(class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + }, + "patterns": [ + { + "include": "#module-item-type-and" + }, + { + "include": "#module-item-type-constraint" + }, + { + "include": "#module-item-type-bind" + } + ] + }, + { + "begin": "(?=\\b(module)\\b)", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|val|with)\\b)", + "patterns": [ + { + "begin": "\\b(module)\\b", + "end": "(?=:?=|[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "markup.inserted keyword.control storage.type variable.other.readwrite.instance" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-path-simple" + }, + { + "match": "[[:upper:]][[:word:]]*", + "name": "support.class entity.name.class" + } + ] + }, + { + "begin": "(:=)|(=)", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "markup.inserted keyword.control.less message.error" + }, + "2": { + "name": "markup.inserted keyword.control.less" + } + }, + "patterns": [ + { + "include": "#structure-expression" + } + ] + } + ] + } + ] + } + ] + }, + "structure-expression": { + "patterns": [ + { + "include": "#comment" + }, + { + "comment": "FIXME: scan for :upper: or `val` to disambiguate types from signatures for hover", + "begin": "\\((?=[[:space:]]*(\\b(val)\\b|[^'\\[<[:lower:]]))", + "end": "\\)|(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|with)\\b)", + "patterns": [ + { + "include": "#comment" + }, + { + "comment": "FIXME: might need to refactor this or include more expressions", + "include": "#structure-expression-block" + }, + { + "begin": "\\b(val)\\b", + "end": "(?=\\))|(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.other" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "match": "\\b([[:lower:]][[:word:]]*)\\b", + "name": "support.class entity.name.class" + } + ] + }, + { + "include": "#module-path-simple" + }, + { + "begin": "(:)", + "end": "(?=[\\)])|(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#signature-expression" + } + ] + } + ] + }, + { + "include": "#module-path-simple" + }, + { + "include": "#structure-expression-block" + } + ] + }, + "structure-expression-block": { + "begin": "{", + "end": "}", + "patterns": [ + { + "include": "#structure-expression-block-item" + } + ] + }, + "structure-expression-block-item": { + "patterns": [ + { + "include": "#attribute" + }, + { + "include": "#comment" + }, + { + "include": "#module-item-exception" + }, + { + "include": "#module-item-external" + }, + { + "include": "#module-item-include" + }, + { + "include": "#module-item-let" + }, + { + "include": "#module-item-class-type" + }, + { + "include": "#module-item-module-type" + }, + { + "include": "#module-item-module" + }, + { + "include": "#module-item-open" + }, + { + "include": "#module-item-type" + } + ] + }, + "type-annotation-rhs": { + "begin": "(?|~$\\\\])([:])(?![#\\-:!?.@*/&%^+<=>|~$\\\\])", + "end": "(?=\\))|(?=[,;}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#type-expression" + } + ] + }, + "type-expression": { + "patterns": [ + { + "match": "([\\.])", + "name": "entity.name.function" + }, + { + "include": "#type-expression-atomic" + }, + { + "include": "#type-expression-arrow" + } + ] + }, + "type-expression-atomic": { + "patterns": [ + { + "include": "#attribute" + }, + { + "include": "#comment" + }, + { + "include": "#module-path-extended-prefix" + }, + { + "include": "#type-expression-label" + }, + { + "match": "\\b(as)\\b", + "name": "variable.other.class.js variable.interpolation storage.modifier message.error" + }, + { + "include": "#type-expression-constructor" + }, + { + "include": "#type-expression-object" + }, + { + "include": "#type-expression-parens" + }, + { + "include": "#type-expression-polymorphic-variant" + }, + { + "include": "#type-expression-record" + }, + { + "include": "#type-expression-variable" + } + ] + }, + "type-expression-arrow": { + "match": "=>", + "name": "markup.inserted keyword.control.less" + }, + "type-expression-constructor": { + "match": "(_)(?![[:alnum:]])|\\b([_[:lower:]][[:word:]]*)\\b(?!\\.[[:upper:]])", + "captures": { + "1": { + "name": "comment" + }, + "2": { + "name": "support.type string.regexp" + } + } + }, + "type-expression-label": { + "begin": "\\b([_[:lower:]][[:word:]]*)\\b(::)", + "end": "(?<==>)", + "beginCaptures": { + "1": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + }, + "2": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#type-expression" + }, + { + "match": "(\\?)", + "captures": { + "1": { + "name": "keyword.control.less" + } + } + } + ] + }, + "type-expression-object": { + "comment": "FIXME: separate sub-rules", + "begin": "(<)", + "end": "(>)", + "captures": { + "1": { + "name": "entity.name.function" + } + }, + "patterns": [ + { + "begin": "(\\.\\.)", + "end": "(?=>)", + "beginCaptures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + } + }, + { + "comment": "FIXME: method item", + "begin": "(?=[_[:lower:]])", + "end": "(,)|(?=>)", + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "comment": "FIXME: method name", + "begin": "(?=[_[:lower:]])", + "end": "(?=:)", + "patterns": [ + { + "match": "\\b([_[:lower:]][[:word:]]*)\\b", + "captures": { + "1": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + } + } + } + ] + }, + { + "comment": "FIXME: method type", + "begin": "(:)", + "end": "(?=[,>])", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#type-expression" + } + ] + } + ] + } + ] + }, + "type-expression-parens": { + "comment": "FIXME: proper tuple types", + "begin": "\\(", + "end": "\\)", + "patterns": [ + { + "begin": "\\b(module)\\b", + "end": "(?=[\\)])", + "beginCaptures": { + "1": { + "name": "keyword.other message.error" + } + }, + "patterns": [ + { + "include": "#module-path-extended" + }, + { + "include": "#signature-expression-constraints" + } + ] + }, + { + "match": ",", + "name": "keyword.control.less" + }, + { + "include": "#type-expression" + } + ] + }, + "type-expression-polymorphic-variant": { + "comment": "FIXME: proper parsing", + "begin": "(\\[)([<>])?", + "end": "(\\])", + "captures": { + "1": { + "name": "entity.name.function" + }, + "2": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "begin": "(\\|)?(?![#\\-:!?.@*/&%^+<=>|~$\\\\])[[:space:]]*", + "end": "(?=[;)}\\]]|\\|(?![#\\-:!?.@*/&%^+<=>|~$\\\\])|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#value-expression-constructor" + }, + { + "match": "([:])|\\b(of)\\b|([&])", + "captures": { + "1": { + "name": "keyword.control.less" + }, + "2": { + "name": "keyword.other" + }, + "3": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + } + }, + { + "include": "#value-expression-constructor-polymorphic" + }, + { + "include": "#type-expression" + } + ] + } + ] + }, + "type-expression-record": { + "begin": "{", + "end": "}", + "patterns": [ + { + "include": "#type-expression-record-item" + } + ] + }, + "type-expression-record-field-sans-modifier": { + "begin": "\\b([_[:lower:]][[:word:]]*)\\b", + "end": "(,)|(?=[,}])", + "beginCaptures": { + "1": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "(:)", + "end": "(?=[,}])", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#type-expression" + } + ] + } + ] + }, + "type-expression-record-field": { + "patterns": [ + { + "begin": "\\b(mutable)\\b", + "end": "(?<=[,])|(?=})", + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation storage.modifier message.error" + } + }, + "patterns": [ + { + "include": "#type-expression-record-field-sans-modifier" + } + ] + }, + { + "include": "#type-expression-record-field-sans-modifier" + } + ] + }, + "type-expression-record-item": { + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-path-simple-prefix" + }, + { + "include": "#type-expression-record-field" + } + ] + }, + "type-expression-variable": { + "match": "(')([_[:lower:]][[:word:]]*)\\b(?!\\.[[:upper:]])", + "captures": { + "1": { + "name": "comment" + }, + "2": { + "name": "variable.parameter string.other.link variable.language" + } + } + }, + "value-expression": { + "patterns": [ + { + "include": "#attribute" + }, + { + "include": "#comment" + }, + { + "include": "#extension-node" + }, + { + "include": "#jsx" + }, + { + "include": "#operator" + }, + { + "include": "#value-expression-builtin" + }, + { + "include": "#value-expression-if-then-else" + }, + { + "include": "#value-expression-atomic" + }, + { + "include": "#module-path-simple-prefix" + }, + { + "match": "[:?]", + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + { + "include": "#record-path" + } + ] + }, + "value-expression-atomic": { + "patterns": [ + { + "include": "#value-expression-literal" + }, + { + "include": "#value-expression-literal-list-or-array" + }, + { + "include": "#value-expression-for" + }, + { + "include": "#value-expression-fun" + }, + { + "include": "#value-expression-block-or-record-or-object" + }, + { + "include": "#value-expression-label" + }, + { + "include": "#value-expression-parens" + }, + { + "include": "#value-expression-switch" + }, + { + "include": "#value-expression-try" + }, + { + "include": "#value-expression-while" + } + ] + }, + "value-expression-atomic-with-paths": { + "patterns": [ + { + "include": "#value-expression-atomic" + }, + { + "include": "#module-path-simple-prefix" + }, + { + "include": "#record-path-suffix" + } + ] + }, + "value-expression-block": { + "begin": "{", + "end": "}", + "patterns": [ + { + "include": "#value-expression-block-item" + } + ] + }, + "value-expression-block-item": { + "patterns": [ + { + "include": "#module-item-let" + }, + { + "include": "#module-item-open" + }, + { + "include": "#value-expression" + } + ] + }, + "value-expression-block-look": { + "begin": "(?![[:space:]]*($|\\.\\.\\.|([[:upper:]][[:word:]]*\\.)*([[:lower:]][[:word:]]*)[[:space:]]*(?:,|:(?![=]))))", + "end": "(?=})", + "patterns": [ + { + "include": "#value-expression-block-item" + } + ] + }, + "value-expression-block-or-record-or-object": { + "begin": "{", + "end": "}", + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#module-path-simple-prefix" + }, + { + "include": "#value-expression-object-look" + }, + { + "include": "#value-expression-record-look" + }, + { + "include": "#value-expression-block-look" + } + ] + }, + "value-expression-builtin": { + "match": "\\b(assert|decr|failwith|fprintf|ignore|incr|land|lazy|lor|lsl|lsr|lxor|mod|new|not|printf|ref)\\b|\\b(raise)\\b", + "captures": { + "1": { + "name": "keyword.control message.error" + }, + "2": { + "name": "keyword.control.trycatch" + } + } + }, + "value-expression-constructor": { + "match": "\\b([[:upper:]][[:word:]]*)\\b(?![[:space:]]*[\\.])", + "captures": { + "1": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + } + }, + "value-expression-constructor-polymorphic": { + "match": "(`)([[:alpha:]][[:word:]]*)\\b(?!\\.)", + "captures": { + "1": { + "name": "constant.other.symbol keyword.control.less variable.parameter" + }, + "2": { + "name": "entity.other.attribute-name.css constant.language constant.numeric" + } + } + }, + "value-expression-for": { + "begin": "(?=\\b(for)\\b)", + "end": "(?<=})|(?=[;]|\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\b)", + "patterns": [ + { + "include": "#value-expression-for-head" + }, + { + "include": "#value-expression-block" + } + ] + }, + "value-expression-for-head": { + "begin": "(?=\\b(for)\\b)", + "end": "(?={)|(?=[;]|\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\b)", + "patterns": [ + { + "begin": "\\b(for)\\b", + "end": "(?=\\b(in)\\b)|(?=[;]|\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.loop" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#pattern-variable" + } + ] + }, + { + "begin": "\\b(in)\\b", + "end": "(?=\\b(to)\\b)|(?=[;]|\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.loop" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#value-expression-atomic-with-paths" + } + ] + }, + { + "begin": "\\b(to)\\b", + "end": "(?={)|(?=[;]|\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.loop" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "include": "#value-expression-atomic-with-paths" + } + ] + }, + { + "include": "#value-expression-block" + } + ] + }, + "value-expression-fun": { + "begin": "\\b(fun)\\b", + "end": "(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control" + } + }, + "patterns": [ + { + "include": "#value-expression-fun-pattern-match-rule-lhs" + }, + { + "include": "#value-expression-fun-pattern-match-rule-rhs" + } + ] + }, + "value-expression-fun-pattern-match-rule-lhs": { + "begin": "(?=\\|(?![#\\-:!?.@*/&%^+<=>|~$\\\\]))|(?<=fun)", + "end": "(\\|(?![#\\-:!?.@*/&%^+<=>|~$\\\\]))|(?==>)|(?=[;\\)}]|\\b(and|class|constraint|exception|external|include|inherit|let|method|module|nonrec|open|private|rec|type|val|with)\\b)", + "applyEndPatternLast": true, + "beginCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "endCaptures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + } + }, + "patterns": [ + { + "include": "#module-item-let-value-param" + } + ] + }, + "value-expression-fun-pattern-match-rule-rhs": { + "begin": "(=>)", + "end": "(?=[;\\)}]|\\|(?![#\\-:!?.@*/&%^+<=>|~$\\\\])|\\b(and)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#value-expression" + } + ] + }, + "value-expression-if-then-else": { + "begin": "\\b(if)\\b", + "end": "(?=[;\\)\\]}])", + "applyEndPatternLast": true, + "beginCaptures": { + "1": { + "name": "keyword.control.conditional" + } + }, + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "\\b(else)\\b", + "end": "(?=[;\\)\\]}])", + "beginCaptures": { + "1": { + "name": "keyword.control.conditional" + } + }, + "patterns": [ + { + "include": "#value-expression" + } + ] + }, + { + "include": "#value-expression-atomic-with-paths" + } + ] + }, + "value-expression-lazy": { + "comment": "FIXME", + "match": "\\b(lazy)\\b", + "captures": { + "1": { + "name": "keyword.other" + } + } + }, + "value-expression-label": { + "begin": "\\b([_[:lower:]][[:word:]]*)\\b[[:space:]]*(::)(\\?)?", + "end": "(?![[:space:]])", + "beginCaptures": { + "1": { + "name": "markup.inserted constant.language support.property-value entity.name.filename" + }, + "2": { + "name": "keyword.control" + }, + "3": { + "name": "storage.type" + } + }, + "patterns": [ + { + "include": "#value-expression" + } + ] + }, + "value-expression-literal": { + "patterns": [ + { + "include": "#value-expression-literal-boolean" + }, + { + "include": "#value-expression-literal-character" + }, + { + "include": "#value-expression-constructor" + }, + { + "include": "#value-expression-constructor-polymorphic" + }, + { + "include": "#value-expression-lazy" + }, + { + "include": "#value-expression-literal-numeric" + }, + { + "include": "#value-expression-literal-string" + }, + { + "include": "#value-expression-literal-unit" + } + ] + }, + "value-expression-literal-boolean": { + "match": "\\b(false|true)\\b", + "name": "entity.other.attribute-name.css constant.language constant.numeric" + }, + "value-expression-literal-character": { + "match": "(')([[:space:]]|[[:graph:]]|\\\\[\\\\\"'ntbr]|\\\\[[:digit:]][[:digit:]][[:digit:]]|\\\\x[[:xdigit:]][[:xdigit:]]|\\\\o[0-3][0-7][0-7])(')", + "name": "constant.character" + }, + "value-expression-literal-list-or-array": { + "begin": "(\\[\\|?)(?![@%])", + "end": "(\\|?\\])", + "beginCaptures": { + "1": { + "name": "constant.language.list" + } + }, + "endCaptures": { + "1": { + "name": "constant.language.list" + } + }, + "patterns": [ + { + "include": "#value-expression-literal-list-or-array-separator" + }, + { + "include": "#value-expression" + }, + { + "include": "#value-expression-literal-list-or-array" + } + ] + }, + "value-expression-literal-list-or-array-separator": { + "match": "(,)|(\\.\\.\\.)", + "captures": { + "1": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "2": { + "name": "keyword.control" + } + } + }, + "value-expression-literal-numeric": { + "patterns": [ + { + "match": "([-])?([[:digit:]][_[:digit:]]*)(?:(\\.)([_[:digit:]]*))?(?:([eE])([\\-\\+])?([[:digit:]][_[:digit:]]*))?(?![bBoOxX])", + "captures": { + "1": { + "name": "keyword.control.less" + }, + "2": { + "name": "constant.numeric" + }, + "3": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "4": { + "name": "constant.numeric" + }, + "5": { + "name": "keyword.control.less" + }, + "6": { + "name": "keyword.control.less" + }, + "7": { + "name": "constant.numeric" + } + } + }, + { + "match": "([-])?(0[xX])([[:xdigit:]][_[:xdigit:]]*)(?:(\\.)([_[:xdigit:]]*))?(?:([pP])([\\-\\+])?([[:digit:]][_[:digit:]]*))?", + "captures": { + "1": { + "name": "keyword.control.less" + }, + "2": { + "name": "keyword.control.less" + }, + "3": { + "name": "constant.numeric" + }, + "4": { + "name": "variable.other.class.js variable.interpolation keyword.operator keyword.control message.error" + }, + "5": { + "name": "constant.numeric" + }, + "6": { + "name": "keyword.control.less" + }, + "7": { + "name": "keyword.control.less" + }, + "8": { + "name": "constant.numeric" + } + } + }, + { + "match": "([-])?(0[oO])([0-7][_0-7]*)", + "captures": { + "1": { + "name": "keyword.control.less" + }, + "2": { + "name": "keyword.control.less" + }, + "3": { + "name": "constant.numeric" + } + } + }, + { + "match": "([-])?(0[bB])([0-1][_0-1]*)", + "captures": { + "1": { + "name": "keyword.control.less" + }, + "2": { + "name": "keyword.control.less" + }, + "3": { + "name": "constant.numeric" + } + } + } + ] + }, + "value-expression-literal-string": { + "patterns": [ + { + "begin": "(?|~$\\\\]))", + "end": "(?==>|[;\\)}])", + "patterns": [ + { + "include": "#pattern-guard" + }, + { + "include": "#pattern" + } + ] + }, + "value-expression-switch-pattern-match-rule-rhs": { + "begin": "(=>)", + "end": "(?=}|\\|(?![#\\-:!?.@*/&%^+<=>|~$\\\\]))", + "beginCaptures": { + "1": { + "name": "keyword.control.less" + } + }, + "patterns": [ + { + "include": "#value-expression-block-item" + } + ] + }, + "value-expression-try": { + "begin": "\\b(try)\\b", + "end": "(?<=})|(?=[;\\)]|\\b(and|as|class|constraint|exception|external|include|inherit|let|method|nonrec|open|private|rec|type|val|with)\\b)", + "beginCaptures": { + "1": { + "name": "keyword.control.trycatch" + } + }, + "patterns": [ + { + "include": "#value-expression-try-head" + }, + { + "include": "#value-expression-switch-body" + } + ] + }, + "value-expression-try-head": { + "begin": "(?<=try)", + "end": "(?( + ReactDOM.Style.combine(ReactDOM.Style.make(~width="32px", ())) + ); + + let activeButton = + button->( + ReactDOM.Style.combine( + ReactDOM.Style.make( + ~backgroundColor=Color.blue, + ~color=Color.white, + (), + ), + ) + ); + + let middleSection = + ReactDOM.Style.make( + ~display="flex", + ~flex="1", + ~justifyContent="center", + (), + ); + + let rightSection = ReactDOM.Style.make(~display="flex", ()); + }; + + [@react.component] + let make = + ( + ~isSidebarHidden: bool, + ~responsiveMode: responsiveMode, + ~onRightSidebarToggle: unit => unit, + ~onSetResponsiveMode: (responsiveMode => responsiveMode) => unit, + ) => +
+
+
+ +
+ + +
+
+
+
+ +
+ +
+
+
+
; +}; + +let rightSidebarId = "rightSidebar"; + +module Link = { + [@react.component] + let make = (~href, ~text: React.element, ~style=?, ~activeStyle=?) => { + let url = ReasonReactRouter.useUrl(); + let path = String.concat("/", url.path); + let isActive = (path ++ "?" ++ url.search)->(Js.String2.endsWith(href)); + + switch ( + ReactEvent.Mouse.metaKey(event), + ReactEvent.Mouse.ctrlKey(event), + ) { + | (false, false) => + ReactEvent.Mouse.preventDefault(event); + ReasonReactRouter.push(href); + | _ => () + } + } + style=?{ + switch (style, activeStyle, isActive) { + | (Some(style), _, false) => Some(style) + | (Some(style), None, true) => Some(style) + | (Some(style), Some(activeStyle), true) => + Some(ReactDOM.Style.combine(style, activeStyle)) + | (_, Some(activeStyle), true) => Some(activeStyle) + | _ => None + } + }> + text + ; + }; +}; + +module DemoListSidebar = { + module Styles = { + let categoryName = + ReactDOM.Style.make( + ~padding=(Gap.xs ++ {js| |js}) ++ Gap.xxs, + ~fontSize=FontSize.md, + ~fontWeight="500", + (), + ); + + let link = + ReactDOM.Style.make( + ~textDecoration="none", + ~color=Color.blue, + ~display="block", + ~padding=(Gap.xs ++ {js| |js}) ++ Gap.md, + ~borderRadius=BorderRadius.default, + ~fontSize=FontSize.md, + ~fontWeight="500", + (), + ); + + let activeLink = ReactDOM.Style.make(~backgroundColor=Color.midGray, ()); + }; + + module SearchInput = { + module Styles = { + let clearButton = + ReactDOM.Style.make( + ~position="absolute", + ~right="7px", + ~display="flex", + ~cursor="pointer", + ~border="none", + ~padding="0", + ~backgroundColor=Color.transparent, + ~top="50%", + ~transform="translateY(-50%)", + ~margin="0", + (), + ); + + let inputWrapper = + ReactDOM.Style.make( + ~position="relative", + ~display="flex", + ~alignItems="center", + ~backgroundColor=Color.midGray, + ~borderRadius=BorderRadius.default, + (), + ); + + let input = + ReactDOM.Style.make( + ~padding=(Gap.xs ++ {js| |js}) ++ Gap.md, + ~width="100%", + ~margin="0", + ~height="32px", + ~boxSizing="border-box", + ~fontFamily="inherit", + ~fontSize=FontSize.md, + ~border="none", + ~backgroundColor=Color.transparent, + ~borderRadius=BorderRadius.default, + (), + ); + }; + + module ClearButton = { + [@react.component] + let make = (~onClear) => + ; + }; + + [@react.component] + let make = (~value, ~onChange, ~onClear) => +
+ + {if (value == "") { + React.null; + } else { + ; + }} +
; + }; + + let renderMenu = + ( + ~isCategoriesCollapsedByDefault: bool, + ~urlSearchParams: URLSearchParams.t, + ~searchString, + demos: Demos.t, + ) => { + let rec renderMenu = + ( + ~parentCategoryMatchedSearch: bool, + ~nestingLevel, + ~categoryQuery, + demos: Demos.t, + ) => { + let demos = demos->Js.Dict.entries; + demos + ->( + Array.map(((entityName, entity)) => { + let searchMatchingTerms = + HighlightTerms.getMatchingTerms(~searchString, ~entityName); + + let isEntityNameMatchSearch = + searchString == "" || searchMatchingTerms->Belt.Array.size > 0; + + switch (entity) { + | Demo(_) => + if (isEntityNameMatchSearch || parentCategoryMatchedSearch) { + + + {renderMenu( + ~parentCategoryMatchedSearch= + isEntityNameMatchSearch + || parentCategoryMatchedSearch, + ~nestingLevel=nestingLevel + 1, + ~categoryQuery= + ( + (({js|&category|js} ++ levelStr) ++ {js|=|js}) + ++ entityName->Js.Global.encodeURIComponent + ) + ++ categoryQuery, + demos, + )} + + + ; + } else { + React.null; + } + }; + }) + ) + ->React.array; + }; + + renderMenu( + ~parentCategoryMatchedSearch=false, + ~nestingLevel=0, + ~categoryQuery="", + demos: Demos.t, + ); + }; + + [@react.component] + let make = + ( + ~urlSearchParams: URLSearchParams.t, + ~demos: Demos.t, + ~isCategoriesCollapsedByDefault: bool, + ~onToggleCollapsedCategoriesByDefault: unit => unit, + ) => { + let (filterValue, setFilterValue) = React.useState(() => None); + + +
+ + (Option.getWithDefault(""))} + onChange={event => { + let value = event->ReactEvent.Form.target##value; + + setFilterValue(_ => + if (value->Js.String2.trim == "") { + None; + } else { + Some(value); + } + ); + }} + onClear={() => setFilterValue(_ => None)} + /> +
+
+ + {renderMenu( + ~isCategoriesCollapsedByDefault, + ~searchString= + filterValue->(Option.mapWithDefault("", Js.String2.toLowerCase)), + ~urlSearchParams, + demos, + )} + +
; + }; +}; + +module DemoUnitSidebar = { + module Styles = { + let label = + ReactDOM.Style.make( + ~display="block", + ~backgroundColor=Color.white, + ~borderRadius=BorderRadius.default, + ~boxShadow="0 5px 10px rgba(0, 0, 0, 0.07)", + (), + ); + + let labelText = + ReactDOM.Style.make(~fontSize=FontSize.md, ~textAlign="center", ()); + + let textInput = + ReactDOM.Style.make( + ~fontSize=FontSize.md, + ~width="100%", + ~boxSizing="border-box", + ~backgroundColor=Color.lightGray, + ~boxShadow="inset 0 0 0 1px rgba(0, 0, 0, 0.1)", + ~border="none", + ~padding=Gap.md, + ~borderRadius=BorderRadius.default, + (), + ); + + let select = + ReactDOM.Style.make( + ~fontSize=FontSize.md, + ~width="100%", + ~boxSizing="border-box", + ~backgroundColor=Color.lightGray, + ~boxShadow="inset 0 0 0 1px rgba(0, 0, 0, 0.1)", + ~border="none", + ~padding=Gap.md, + ~borderRadius=BorderRadius.default, + ~appearance="none", + ~paddingRight="30px", + ~backgroundImage= + {js|url("data:image/svg+xml,%3Csvg width='36' height='36' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='%2342484E' stroke-width='2' d='M12.246 14.847l5.826 5.826 5.827-5.826' fill='none' fill-rule='evenodd' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")|js}, + ~backgroundPosition="center right", + ~backgroundSize="contain", + ~backgroundRepeat="no-repeat", + (), + ) + ->(ReactDOM.Style.unsafeAddProp("WebkitAppearance", "none")); + + let checkbox = + ReactDOM.Style.make( + ~fontSize=FontSize.md, + ~margin="0 auto", + ~display="block", + (), + ); + }; + + module PropBox = { + [@react.component] + let make = (~propName: string, ~children) => + ; + }; + + [@react.component] + let make = + ( + ~strings: + Map.String.t( + ( + Configs.stringConfig, + string, + option(array((string, string))), + ), + ), + ~ints: Map.String.t((Configs.numberConfig(int), int)), + ~floats: Map.String.t((Configs.numberConfig(float), float)), + ~bools: Map.String.t((Configs.boolConfig, bool)), + ~onStringChange, + ~onIntChange, + ~onFloatChange, + ~onBoolChange, + ) => + + + {strings + ->Map.String.toArray + ->( + Array.map(((propName, (_config, value, options))) => + + {switch (options) { + | None => + + onStringChange( + propName, + event->ReactEvent.Form.target##value, + ) + } + /> + | Some(options) => + + }} + + ) + ) + ->React.array} + {ints + ->Map.String.toArray + ->( + Array.map(((propName, ({min, max, _}, value))) => + + + onIntChange( + propName, + event->ReactEvent.Form.target##value->int_of_string, + ) + } + /> + + ) + ) + ->React.array} + {floats + ->Map.String.toArray + ->( + Array.map(((propName, ({min, max, _}, value))) => + + + onFloatChange( + propName, + event->ReactEvent.Form.target##value->float_of_string, + ) + } + /> + + ) + ) + ->React.array} + {bools + ->Map.String.toArray + ->( + Array.map(((propName, (_config, checked))) => + + + onBoolChange( + propName, + event->ReactEvent.Form.target##checked, + ) + } + /> + + ) + ) + ->React.array} + + ; +}; + +module DemoUnit = { + type state = { + strings: + Map.String.t( + (Configs.stringConfig, string, option(array((string, string)))), + ), + ints: Map.String.t((Configs.numberConfig(int), int)), + floats: Map.String.t((Configs.numberConfig(float), float)), + bools: Map.String.t((Configs.boolConfig, bool)), + }; + + type action = + | SetString(string, string) + | SetInt(string, int) + | SetFloat(string, float) + | SetBool(string, bool); + + module Styles = { + let container = + ReactDOM.Style.make( + ~flexGrow="1", + ~display="flex", + ~alignItems="stretch", + ~flexDirection="row", + (), + ); + + let contents = + ReactDOM.Style.make( + ~flexGrow="1", + ~overflowY="auto", + ~display="flex", + ~flexDirection="column", + ~alignItems="center", + ~justifyContent="center", + (), + ) + ->(ReactDOM.Style.unsafeAddProp("WebkitOverflowScrolling", "touch")); + }; + + let getRightSidebarElement = (): option(Dom.element) => + Window.window##parent##document##getElementById(rightSidebarId) + ->Js.Nullable.toOption; + + [@react.component] + let make = (~demoUnit: Configs.demoUnitProps => React.element) => { + let (parentWindowRightSidebarElem, setParentWindowRightSidebarElem) = + React.useState(() => None); + + React.useEffect0(() => { + switch (getRightSidebarElement()) { + | Some(elem) => setParentWindowRightSidebarElem(_ => Some(elem)) + | None => () + }; + None; + }); + React.useEffect0(() => { + Window.addMessageListener(event => + if (Window.window##parent === event##source) { + let message: string = event##data; + switch (message->Window.Message.fromStringOpt) { + | Some(RightSidebarDisplayed) => + switch (getRightSidebarElement()) { + | Some(elem) => setParentWindowRightSidebarElem(_ => Some(elem)) + | None => () + } + | None => Js.Console.error("Unexpected message received") + }; + } + ); + None; + }); + let (state, dispatch) = + React.useReducer( + (state, action) => + switch (action) { + | SetString(name, newValue) => { + ...state, + strings: + state.strings + ->( + Map.String.update(name, value => + value->( + Option.map(((config, _value, options)) => + (config, newValue, options) + ) + ) + ) + ), + } + | SetInt(name, newValue) => { + ...state, + ints: + state.ints + ->( + Map.String.update(name, value => + value->( + Option.map(((config, _value)) => + (config, newValue) + ) + ) + ) + ), + } + | SetFloat(name, newValue) => { + ...state, + floats: + state.floats + ->( + Map.String.update(name, value => + value->( + Option.map(((config, _value)) => + (config, newValue) + ) + ) + ) + ), + } + | SetBool(name, newValue) => { + ...state, + bools: + state.bools + ->( + Map.String.update(name, value => + value->( + Option.map(((config, _value)) => + (config, newValue) + ) + ) + ) + ), + } + }, + { + let strings = ref(Map.String.empty); + let ints = ref(Map.String.empty); + let floats = ref(Map.String.empty); + let bools = ref(Map.String.empty); + let props: Configs.demoUnitProps = { + string: (name, ~options=?, config) => { + strings := + strings.contents + ->(Map.String.set(name, (config, config, options))); + config; + }, + int: (name, config) => { + ints := + ints.contents + ->(Map.String.set(name, (config, config.initial))); + config.initial; + }, + float: (name, config) => { + floats := + floats.contents + ->(Map.String.set(name, (config, config.initial))); + config.initial; + }, + bool: (name, config) => { + bools := + bools.contents->(Map.String.set(name, (config, config))); + config; + }, + }; + + let _ = demoUnit(props); + { + strings: strings.contents, + ints: ints.contents, + floats: floats.contents, + bools: bools.contents, + }; + }, + ); + + let props: Configs.demoUnitProps = { + string: (name, ~options as _=?, _config) => { + let (_, value, _) = state.strings->(Map.String.getExn(name)); + value; + }, + int: (name, _config) => { + let (_, value) = state.ints->(Map.String.getExn(name)); + value; + }, + float: (name, _config) => { + let (_, value) = state.floats->(Map.String.getExn(name)); + value; + }, + bool: (name, _config) => { + let (_, value) = state.bools->(Map.String.getExn(name)); + value; + }, + }; + +
+
{demoUnit(props)}
+ {switch (parentWindowRightSidebarElem) { + | None => React.null + | Some(element) => + ReactDOM.createPortal( + + dispatch(SetString(name, value)) + } + onIntChange={(name, value) => dispatch(SetInt(name, value))} + onFloatChange={(name, value) => + dispatch(SetFloat(name, value)) + } + onBoolChange={(name, value) => dispatch(SetBool(name, value))} + />, + element, + ) + }} +
; + }; +}; + +module DemoUnitFrame = { + let container = responsiveMode => + ReactDOM.Style.make( + ~flex="1", + ~display="flex", + ~justifyContent="center", + ~alignItems="center", + ~backgroundColor= + switch (responsiveMode) { + | Mobile => Color.midGray + | Desktop => Color.white + }, + ~height="1px", + ~overflowY="auto", + (), + ); + + let useFullframeUrl: bool = [%mel.raw + {js|typeof USE_FULL_IFRAME_URL === "boolean" ? USE_FULL_IFRAME_URL : false|js} + ]; + + [@react.component] + let make = + (~queryString: string, ~responsiveMode, ~onLoad: Js.t('a) => unit) => { + let iframePath = if (useFullframeUrl) {"demo/index.html"} else {"demo"}; +
+