@softwarefactory-project/re-ansi 0.6.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -28,7 +28,7 @@ Or using yarn:
28
28
  yarn add @softwarefactory-project/re-ansi
29
29
  ```
30
30
 
31
- Add to your `bsconfig.json`:
31
+ Add to your `rescript.json`:
32
32
 
33
33
  ```diff
34
34
  "bs-dependencies": [
@@ -43,7 +43,7 @@ In reason:
43
43
  ```reason
44
44
  let log = "green color: \x1b[01m\x1b[01;32mOK\x1b[00m";
45
45
 
46
- [@react.component]
46
+ @react.component
47
47
  let make = () => {
48
48
  <Ansi log />
49
49
  }
@@ -71,8 +71,8 @@ Get started by running:
71
71
  ```sh
72
72
  git clone https://github.com/softwarefactory-project/re-ansi
73
73
  cd re-ansi
74
- yarn install
75
- yarn start
74
+ npm install
75
+ npm run test
76
76
  ```
77
77
 
78
78
  Then build and run tests with `yarn test`.
@@ -81,6 +81,14 @@ Make sure to read about [React][reason-react] and [Reason][rescript-lang] too.
81
81
 
82
82
  ## Changes
83
83
 
84
+ ### 0.7.1
85
+
86
+ - Use @rescript/std instead of rescript.
87
+
88
+ ### 0.7.0
89
+
90
+ - Update to rescript version 11.
91
+
84
92
  ### 0.6.0
85
93
 
86
94
  - Fix support for bright colors.
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@softwarefactory-project/re-ansi",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "ANSI code to HTML",
5
- "files": ["README.md", "LICENSE", "bsconfig.json", "src"],
6
- "main": "./src/Ansi.bs.js",
5
+ "files": [
6
+ "README.md",
7
+ "LICENSE",
8
+ "rescript.json",
9
+ "src"
10
+ ],
11
+ "main": "./src/Ansi.res.js",
7
12
  "license": "Apache-2.0",
8
13
  "homepage": "https://github.com/softwarefactory-project/re-ansi",
9
14
  "repository": {
@@ -11,24 +16,22 @@
11
16
  "url": "git+https://softwarefactory-project.io/r/software-factory/re-ansi.git"
12
17
  },
13
18
  "scripts": {
14
- "build": "bsb -make-world",
15
- "start": "bsb -make-world -w",
16
- "test": "npm run build && node tests/Spec.bs.js"
19
+ "build": "rescript",
20
+ "clean": "rescript clean",
21
+ "dev": "rescript -w",
22
+ "test": "npm run build && node tests/Spec.res.js"
17
23
  },
18
24
  "keywords": [
19
- "ReasonReact",
20
25
  "ansi",
21
- "reason",
22
- "reason-react",
23
- "reasonml",
24
26
  "rescript",
25
- "bucklescript"
27
+ "react"
26
28
  ],
27
29
  "dependencies": {
28
- "reason-react": "^0.9.1",
29
- "bs-platform": "^8.2.0"
30
+ "@rescript/core": "^1.3.0",
31
+ "@rescript/react": "^0.12.1",
32
+ "@rescript/std": "^11.1.0"
30
33
  },
31
34
  "devDependencies": {
32
- "react": "^16.14.0"
35
+ "rescript": "^11.1.0"
33
36
  }
34
37
  }
@@ -1,18 +1,17 @@
1
1
  {
2
2
  "name": "@softwarefactory-project/re-ansi",
3
- "reason": {
4
- "react-jsx": 3
3
+ "jsx": {
4
+ "version": 4
5
5
  },
6
6
  "sources": ["src", { "dir": "tests", "type": "dev" }],
7
- "bsc-flags": ["-bs-super-errors", "-bs-no-version-header"],
7
+ "bsc-flags": ["-open RescriptCore"],
8
8
  "package-specs": [
9
9
  {
10
10
  "module": "commonjs",
11
11
  "in-source": true
12
12
  }
13
13
  ],
14
- "suffix": ".bs.js",
15
- "bs-dependencies": ["reason-react"],
16
- "bs-dev-dependencies": [],
17
- "refmt": 3
14
+ "suffix": ".res.js",
15
+ "bs-dependencies": ["@rescript/react", "@rescript/core"],
16
+ "external-stdlib" : "@rescript/std"
18
17
  }
@@ -15,16 +15,14 @@
15
15
  // Ansi renders a log ANSI code to a React component
16
16
 
17
17
  // Document type
18
- type document = list(atom)
18
+ type rec document = list<atom>
19
19
  and atom =
20
20
  | Text(string)
21
21
  | Link(string)
22
22
  | LineBreak
23
23
  | DocStyle(ReactDOM.Style.t, document);
24
24
 
25
- type parser('a) = (int, option('a));
26
-
27
- open Belt;
25
+ type parser<'a> = (int, option<'a>);
28
26
 
29
27
  module AnsiCode = {
30
28
  type code =
@@ -35,7 +33,7 @@ module AnsiCode = {
35
33
  | Style(ReactDOM.Style.t);
36
34
 
37
35
  // Convert a 4 bits color code to its css color: https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit
38
- let fourBitColors = (code: int): option(string) =>
36
+ let fourBitColors = (code: int): option<string> =>
39
37
  switch (code) {
40
38
  | 00 => "black"->Some
41
39
  | 01 => "red"->Some
@@ -59,7 +57,7 @@ module AnsiCode = {
59
57
  None;
60
58
  };
61
59
 
62
- let threeBitColors = (code: int): option(string) =>
60
+ let threeBitColors = (code: int): option<string> =>
63
61
  switch (code) {
64
62
  | 00 => "grey"->Some
65
63
  | 01 => "red"->Some
@@ -87,7 +85,7 @@ module AnsiCode = {
87
85
  | Foreground(int)
88
86
  | BrightForeground(int)
89
87
  | Background(int);
90
- let getColorStyle = (colorMode: int, colorValue: int): option(t) =>
88
+ let getColorStyle = (colorMode: int, colorValue: int): option<t> =>
91
89
  switch (colorMode) {
92
90
  | 3 => colorValue->Foreground->Some
93
91
  | 9 => colorValue->BrightForeground->Some
@@ -98,7 +96,7 @@ module AnsiCode = {
98
96
  None;
99
97
  };
100
98
 
101
- let getColorStyleCss = (color: t): option(ReactDOM.Style.t) =>
99
+ let getColorStyleCss = (color: t): option<ReactDOM.Style.t> =>
102
100
  switch (color) {
103
101
  | Foreground(v) =>
104
102
  v
@@ -116,7 +114,7 @@ module AnsiCode = {
116
114
  )
117
115
  };
118
116
 
119
- let get = (colorMode: int, colorValue: int): option(ReactDOM.Style.t) =>
117
+ let get = (colorMode: int, colorValue: int): option<ReactDOM.Style.t> =>
120
118
  colorMode
121
119
  ->int_of_cp
122
120
  ->getColorStyle(colorValue->int_of_cp)
@@ -129,7 +127,7 @@ module AnsiCode = {
129
127
  | Regular
130
128
  | FontStyle(ReactDOM.Style.t);
131
129
 
132
- let getFontStyle = (fontMode: int): option(t) =>
130
+ let getFontStyle = (fontMode: int): option<t> =>
133
131
  switch (fontMode) {
134
132
  | 0 => Regular->Some
135
133
  | 1 => "bold"->addWeight->FontStyle->Some
@@ -143,61 +141,66 @@ module AnsiCode = {
143
141
  | _ => None
144
142
  };
145
143
 
146
- let getFontStyleCss = (font: t): option(ReactDOM.Style.t) =>
144
+ let getFontStyleCss = (font: t): option<ReactDOM.Style.t> =>
147
145
  switch (font) {
148
146
  | Regular => None
149
147
  | FontStyle(css) => css->Some
150
148
  };
151
149
 
152
- let get = (fontMode: int): option(ReactDOM.Style.t) =>
150
+ let get = (fontMode: int): option<ReactDOM.Style.t> =>
153
151
  fontMode->int_of_cp->getFontStyle->Option.flatMap(getFontStyleCss);
154
152
  };
155
153
 
156
154
  // Link management
157
155
  module HttpLink = {
158
- let linkRe = [%re "/^(http(s)?:\\/\\/[^\s]+)/"];
156
+ let linkRe = RegExp.fromString("^(http(s)?:\\/\\/[^\\s]+)");
159
157
 
160
- let get = (txt: string): parser(code) =>
158
+ let get = (txt: string): parser<code> =>
161
159
  linkRe
162
- ->Js.Re.exec_(txt)
163
- ->Option.flatMap(res =>
164
- (
165
- switch (res->Js.Re.captures) {
166
- | [|url, _, _|] => url->Js.Nullable.toOption
167
- | _ => None
168
- }
169
- )
160
+ ->RegExp.exec(txt)
161
+ ->Option.flatMap(res => res->Array.get(0)
170
162
  ->Option.flatMap(url =>
171
163
  (url->Js.String.length, url->HRef->Some)->Some
172
164
  )
173
165
  )
174
- ->Option.getWithDefault((1, None));
166
+ ->Option.getOr((1, None));
175
167
  };
176
168
 
177
169
  // Parse an ANSI code, returning the length of the sequence
178
- let parse = (txt: string, pos: int): parser(code) =>
170
+ let parse = (txt: string, pos: int): parser<code> =>
179
171
  switch (Js.String.codePointAt(pos, txt)) {
180
172
  | Some(0x68) => HttpLink.get(txt->Js.String.slice(~from=pos, ~to_=512))
181
173
  | Some(0x0a) => (1, CarriageReturn->Some)
182
174
  | Some(0x0d)
183
175
  | Some(0x1b) =>
184
176
  // escape sequence begin
185
- let rec cps = (idx: int, acc: list(int)): list(int) =>
177
+ let codePoints = [];
178
+
179
+ let rec readCodePoints = (idx: int) =>
186
180
  switch (idx > 10, Js.String.codePointAt(pos + idx, txt)) {
187
- | (false, Some(109)) => acc
188
- | (false, Some(n)) => cps(idx + 1, acc->List.add(n))
189
- | _ => acc
181
+ | (false, Some(109)) => ()
182
+ | (false, Some(n)) => {
183
+ codePoints->Array.push(n);
184
+ readCodePoints(idx + 1)
185
+ }
186
+ | _ => ()
190
187
  };
188
+ readCodePoints(1);
189
+
190
+ // use get for pattern match value, it's fine to use 'getUnsafe' because we'll get undefined value.
191
+ let get = (idx) => codePoints->Array.getUnsafe(idx)
191
192
 
192
- let codePoints = 1->cps([])->List.reverse;
193
- let length = codePoints->List.length + 2;
193
+ // Add 2 to take the 0x1b and 109 into account
194
+ let length = codePoints->Array.length + 2;
194
195
  switch (codePoints) {
195
196
  // \n\x0d[1A\x0d[J
196
- | [10, 27, 91, 49, 65, 27, 91, 74, ..._] => (9, EraseLine->Some)
197
+ | _ when
198
+ get(0) == 10 && get(1) == 27 && get(2) == 91 && get(3) == 49 &&
199
+ get(4) == 65 && get(5) == 27 && get(6) == 91 && get(7) == 74 => (9, EraseLine->Some)
197
200
  // [_K
198
- | [91, _, 75, ..._] => (4, EraseLine->Some)
201
+ | _ when get(0) == 91 && get(2) == 75 => (4, EraseLine->Some)
199
202
  // [K
200
- | [91, 75, ..._] => (3, EraseLine->Some)
203
+ | _ when get(0) == 91 && get(1) == 75 => (3, EraseLine->Some)
201
204
  // [00m
202
205
  | [91, 48, 48]
203
206
  // [0m
@@ -216,7 +219,7 @@ module AnsiCode = {
216
219
  length,
217
220
  ColorCss.get(
218
221
  colorMode,
219
- colorValue + (xs->List.length == 4 ? 10 : 0),
222
+ colorValue + (xs->Array.length == 4 ? 10 : 0),
220
223
  )
221
224
  ->Option.flatMap(colorCss => colorCss->Style->Some),
222
225
  )
@@ -246,7 +249,7 @@ module AnsiCode = {
246
249
  length,
247
250
  ColorCss.get(cm1, cv1)
248
251
  ->Option.flatMap(colorCss1 =>
249
- ColorCss.get(cm2, cv2 + (xs->List.length == 9 ? 10 : 0))
252
+ ColorCss.get(cm2, cv2 + (xs->Array.length == 9 ? 10 : 0))
250
253
  ->Option.flatMap(colorCss2 => {
251
254
  let css = combine(colorCss1, colorCss2);
252
255
  switch (style->FontCss.get) {
@@ -270,26 +273,26 @@ module Document = {
270
273
  txt->Js.String.slice(~from, ~to_)->Text;
271
274
 
272
275
  // Parse a document
273
- let parse = (txt: string, length: int, pos: int): parser(document) => {
276
+ let parse = (txt: string, length: int, pos: int): parser<document> => {
274
277
  let rec go = (pos: int, prev: int) =>
275
278
  switch (pos == length, txt->AnsiCode.parse(pos)) {
276
279
  // we reached the end of the txt
277
- | (true, _) => (pos, [text(txt, prev, pos)]->Some)
280
+ | (true, _) => (pos, list{text(txt, prev, pos)}->Some)
278
281
  // current codepoint is an ANSI code or a HRef
279
282
  | (_, (length, Some(code))) =>
280
283
  let prevElem = txt->text(prev, pos);
281
284
  let pos = pos + length;
282
285
  switch (code) {
283
- | Clear => (pos, [prevElem]->Some)
286
+ | Clear => (pos, list{prevElem}->Some)
284
287
  | EraseLine => pos->go(pos)
285
- | CarriageReturn => (pos, [prevElem, LineBreak]->Some)
286
- | HRef(link) => (pos, [prevElem, link->Link]->Some)
288
+ | CarriageReturn => (pos, list{prevElem, LineBreak}->Some)
289
+ | HRef(link) => (pos, list{prevElem, link->Link}->Some)
287
290
  | Style(style) =>
288
291
  // recursively parse the stylized block
289
292
  switch (pos->go(pos)) {
290
293
  | (pos, Some(styled)) => (
291
294
  pos,
292
- [prevElem, DocStyle(style, styled)]->Some,
295
+ list{prevElem, DocStyle(style, styled)}->Some,
293
296
  )
294
297
  | _ => (pos, None)
295
298
  }
@@ -303,7 +306,7 @@ module Document = {
303
306
 
304
307
  // Convert a string to a document
305
308
  let parse = (txt: string): document => {
306
- let rec go = (txt: string, acc: list(document)) => {
309
+ let rec go = (txt: string, acc: list<document>) => {
307
310
  let length = txt->Js.String.length;
308
311
  switch (txt->Document.parse(length, 0)) {
309
312
  | (pos, Some(doc)) when pos == length => acc->List.add(doc)
@@ -312,39 +315,39 @@ let parse = (txt: string): document => {
312
315
  | _ => acc
313
316
  };
314
317
  };
315
- txt->go([])->Belt.List.reverse->Belt.List.flatten;
318
+ txt->go(list{})->Belt.List.reverse->Belt.List.flatten;
316
319
  };
317
320
 
318
321
  // Convert a document to a React.element
319
322
  let render = (doc: document): React.element => {
320
323
  let rec go =
321
- (xs: document, idx: int, acc: list(React.element)): React.element =>
324
+ (xs: document, idx: int, acc: list<React.element>): React.element =>
322
325
  switch (xs) {
323
- | [] => acc->List.reverse->List.toArray->ReasonReact.array
324
- | [LineBreak, ...xs] =>
326
+ | list{} => acc->List.reverse->List.toArray->React.array
327
+ | list{LineBreak, ...xs} =>
325
328
  xs->go(idx + 1, acc->List.add(<br key={idx->string_of_int} />))
326
- | [Text(txt), ...xs] =>
327
- xs->go(idx + 1, acc->List.add(txt->React.string))
328
- | [Link(href), ...xs] =>
329
+ | list{Text(txt), ...xs} =>
330
+ xs->go(idx + 1, acc->List.add(React.string(txt)))
331
+ | list{Link(href), ...xs} =>
329
332
  xs->go(
330
333
  idx + 1,
331
334
  acc->List.add(
332
- <a key={idx->string_of_int} href> href->React.string </a>,
335
+ <a key={idx->string_of_int} href> {href->React.string} </a>,
333
336
  ),
334
337
  )
335
- | [DocStyle(style, elems), ...xs] =>
338
+ | list{DocStyle(style, elems), ...xs} =>
336
339
  xs->go(
337
340
  idx + 1,
338
341
  acc->List.add(
339
- <span key={idx->string_of_int} style> {elems->go(0, [])} </span>,
342
+ <span key={idx->string_of_int} style> {elems->go(0, list{})} </span>,
340
343
  ),
341
344
  )
342
345
  };
343
- doc->go(0, []);
346
+ doc->go(0, list{});
344
347
  };
345
348
 
346
349
  // The react component
347
- [@react.component]
350
+ @react.component
348
351
  let make = (~log: string) => {
349
352
  <div> {log->parse->render} </div>;
350
353
  };