@@ -133,238 +133,6 @@ let editorShellStyle = (activeLine, scrollTop, scrollLeft) => {
133133 ` --active-line-top: ${activeLineTop-> Int.toString}px; --editor-scroll-y: -${scrollTop-> Int.toString}px; --editor-scroll-x: -${scrollLeft-> Int.toString}px;`
134134}
135135
136- type tokenKind =
137- | TokenPlain
138- | TokenKeyword
139- | TokenBuiltin
140- | TokenConstructor
141- | TokenString
142- | TokenNumber
143- | TokenComment
144- | TokenAttribute
145- | TokenOperator
146-
147- type highlightToken = {
148- kind : tokenKind ,
149- text : string ,
150- }
151-
152- let syntaxKeywords = [
153- "and" ,
154- "as" ,
155- "async" ,
156- "await" ,
157- "catch" ,
158- "constraint" ,
159- "else" ,
160- "exception" ,
161- "external" ,
162- "false" ,
163- "for" ,
164- "if" ,
165- "in" ,
166- "include" ,
167- "let" ,
168- "module" ,
169- "mutable" ,
170- "open" ,
171- "private" ,
172- "rec" ,
173- "switch" ,
174- "to" ,
175- "true" ,
176- "try" ,
177- "type" ,
178- "when" ,
179- "while" ,
180- ]
181-
182- let syntaxBuiltins = [
183- "array" ,
184- "bigint" ,
185- "bool" ,
186- "dict" ,
187- "float" ,
188- "int" ,
189- "list" ,
190- "option" ,
191- "promise" ,
192- "result" ,
193- "string" ,
194- "unit" ,
195- ]
196-
197- let charAt = (source , index ) => source -> String .charAt (index )
198-
199- let isLower = char => char >= "a" && char <= "z"
200- let isUpper = char => char >= "A" && char <= "Z"
201- let isDigit = char => char >= "0" && char <= "9"
202- let isAlpha = char => isLower (char ) || isUpper (char )
203- let isIdentStart = char => isAlpha (char ) || char === "_"
204- let isIdentPart = char => isIdentStart (char ) || isDigit (char ) || char === "'"
205-
206- let isOperatorChar = char =>
207- switch char {
208- | "="
209- | ">"
210- | "<"
211- | "+"
212- | "-"
213- | "*"
214- | "/"
215- | "|"
216- | "&"
217- | "!"
218- | "?"
219- | ":"
220- | "."
221- | "~"
222- | "^"
223- | "%"
224- | "#" => true
225- | _ => false
226- }
227-
228- let startsWithAt = (source , index , prefix ) =>
229- source -> String .slice (~start = index , ~end = index + String .length (prefix )) === prefix
230-
231- let rec findLineEnd = (source , index , length ) =>
232- if index >= length || charAt (source , index ) === "\n " {
233- index
234- } else {
235- findLineEnd (source , index + 1 , length )
236- }
237-
238- let rec findBlockEnd = (source , index , length , closing ) =>
239- if index >= length {
240- length
241- } else if startsWithAt (source , index , closing ) {
242- index + String .length (closing )
243- } else {
244- findBlockEnd (source , index + 1 , length , closing )
245- }
246-
247- let rec findStringEnd = (source , index , length , delimiter , escaped ) =>
248- if index >= length {
249- length
250- } else {
251- let char = charAt (source , index )
252- if escaped {
253- findStringEnd (source , index + 1 , length , delimiter , false )
254- } else if char === "\\ " {
255- findStringEnd (source , index + 1 , length , delimiter , true )
256- } else if char === delimiter {
257- index + 1
258- } else {
259- findStringEnd (source , index + 1 , length , delimiter , false )
260- }
261- }
262-
263- let rec findIdentEnd = (source , index , length ) =>
264- if index < length && isIdentPart (charAt (source , index )) {
265- findIdentEnd (source , index + 1 , length )
266- } else {
267- index
268- }
269-
270- let rec findAttributeEnd = (source , index , length ) =>
271- if index < length {
272- let char = charAt (source , index )
273- if isIdentPart (char ) || char === "." || char === "@" {
274- findAttributeEnd (source , index + 1 , length )
275- } else {
276- index
277- }
278- } else {
279- index
280- }
281-
282- let rec findNumberEnd = (source , index , length ) =>
283- if index < length {
284- let char = charAt (source , index )
285- if isDigit (char ) || isAlpha (char ) || char === "_" || char === "." {
286- findNumberEnd (source , index + 1 , length )
287- } else {
288- index
289- }
290- } else {
291- index
292- }
293-
294- let rec findOperatorEnd = (source , index , length ) =>
295- if index < length && isOperatorChar (charAt (source , index )) {
296- findOperatorEnd (source , index + 1 , length )
297- } else {
298- index
299- }
300-
301- let tokenKindForIdent = word =>
302- if syntaxKeywords -> Array .includes (word ) {
303- TokenKeyword
304- } else if syntaxBuiltins -> Array .includes (word ) {
305- TokenBuiltin
306- } else if String .length (word ) > 0 && isUpper (charAt (word , 0 )) {
307- TokenConstructor
308- } else {
309- TokenPlain
310- }
311-
312- let tokenizeRescript = source => {
313- let tokens : array <highlightToken > = []
314- let length = String .length (source )
315- let index = ref (0 )
316-
317- while index .contents < length {
318- let start = index .contents
319- let char = charAt (source , start )
320- let (next , kind ) = if startsWithAt (source , start , "//" ) {
321- (findLineEnd (source , start , length ), TokenComment )
322- } else if startsWithAt (source , start , "/*" ) {
323- (findBlockEnd (source , start + 2 , length , "*/" ), TokenComment )
324- } else if char === "\" " || char === "`" {
325- (findStringEnd (source , start + 1 , length , char , false ), TokenString )
326- } else if char === "@" {
327- (findAttributeEnd (source , start + 1 , length ), TokenAttribute )
328- } else if isDigit (char ) {
329- (findNumberEnd (source , start + 1 , length ), TokenNumber )
330- } else if isIdentStart (char ) {
331- let next = findIdentEnd (source , start + 1 , length )
332- let word = source -> String .slice (~start , ~end = next )
333- (next , tokenKindForIdent (word ))
334- } else if isOperatorChar (char ) {
335- (findOperatorEnd (source , start + 1 , length ), TokenOperator )
336- } else {
337- (start + 1 , TokenPlain )
338- }
339-
340- tokens -> Array .push ({
341- kind ,
342- text : source -> String .slice (~start , ~end = next ),
343- })
344- index := next
345- }
346-
347- tokens
348- }
349-
350- let tokenClass = kind =>
351- switch kind {
352- | TokenPlain => "syntax-token"
353- | TokenKeyword => "syntax-token syntax-keyword"
354- | TokenBuiltin => "syntax-token syntax-builtin"
355- | TokenConstructor => "syntax-token syntax-constructor"
356- | TokenString => "syntax-token syntax-string"
357- | TokenNumber => "syntax-token syntax-number"
358- | TokenComment => "syntax-token syntax-comment"
359- | TokenAttribute => "syntax-token syntax-attribute"
360- | TokenOperator => "syntax-token syntax-operator"
361- }
362-
363- let highlightNodes = source =>
364- tokenizeRescript (source )-> Array .map (token =>
365- <span class = {tokenClass (token .kind )}> {Node .text (token .text )} </span >
366- )
367-
368136let hasFeature = (features : array <experimentalFeature >, feature : experimentalFeature ) =>
369137 features -> Array .includes (feature )
370138
@@ -604,7 +372,7 @@ module App = {
604372 let editorScrollTop = Signal .make (0 )
605373 let editorScrollLeft = Signal .make (0 )
606374 let highlightedSource : Signal .t <array <Node .node >> = Obj .magic (
607- Computed .make (() => highlightNodes (Signal .get (source ))),
375+ Computed .make (() => SourceHighlight . render (Signal .get (source ))),
608376 )
609377 let timerId : ref <option <int >> = ref (None )
610378 let urlTimerId : ref <option <int >> = ref (None )
0 commit comments