let symbolSubstitutions: Dict.t = Dict.fromArray([ ("&&", "∧"), ("||", "∨"), ("not", "¬"), ("->", "→"), ("<->", "↔"), ("all", "∀"), ("exists", "∃"), ("top", "⊤"), ("bot", "⊥"), ]) let trailingDigitsRE = %re("/^([\s\S]*[^\d])(\^)?(\d+)$/") let renderTokens = (s: string): array => { let re = %re("/(§\p{L}+)|(\p{L}+)|(\p{N}+)|([^\p{L}\p{N}§]+)/gu") let out = [] let rec loop = i => switch RegExp.exec(re, s) { | None => () | Some(res) => let matches = RegExp.Result.matches(res) let bold = matches[0]->Option.getOr("") let letters = matches[1]->Option.getOr("") let digits = matches[2]->Option.getOr("") let other = matches[3]->Option.getOr("") let substOrPlain = (token, cls) => switch symbolSubstitutions->Dict.get(token) { | Some(sym) => {React.string(sym)} | None => {React.string(token)} } let el = if bold != "" { {React.string(String.sliceToEnd(bold, ~start=1))} } else if letters != "" { substOrPlain(letters, "ident-letters") } else if digits != "" { {React.string(digits)} } else if other != "" { substOrPlain(other, "ident-letters") } else { React.null } out->Array.push(el) loop(i + 1) } loop(0) out } let renderPiece = (piece: string, key: int): React.element => switch RegExp.exec(trailingDigitsRE, piece) { | Some(res) => let matches = RegExp.Result.matches(res) let base = matches[0]->Option.getOr("") let caret = matches[1]->Option.getOr("") let digits = matches[2]->Option.getOr("") let digitsEl = caret != "" ? {React.string(digits)} : {React.string(digits)} {renderTokens(base)->React.array} {digitsEl} | None => {renderTokens(piece)->React.array} } @react.component let make = (~identifier: string) => { let pieces = identifier->String.split("_") {pieces ->Array.mapWithIndex((piece, i) => i == 0 ? [renderPiece(piece, i)] : [ {React.string("␣")} , renderPiece(piece, i), ] ) ->Belt.Array.concatMany ->React.array} }