presently 0.1.0

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.
Files changed (215) hide show
  1. checksums.yaml +7 -0
  2. data/bin/presently +13 -0
  3. data/lib/presently/application.rb +104 -0
  4. data/lib/presently/clock.rb +77 -0
  5. data/lib/presently/display_view.rb +73 -0
  6. data/lib/presently/environment/application.rb +62 -0
  7. data/lib/presently/page.rb +38 -0
  8. data/lib/presently/page.xrb +31 -0
  9. data/lib/presently/presentation.rb +72 -0
  10. data/lib/presently/presentation_controller.rb +181 -0
  11. data/lib/presently/presenter_view.rb +264 -0
  12. data/lib/presently/slide.rb +148 -0
  13. data/lib/presently/slide_view.rb +92 -0
  14. data/lib/presently/state.rb +66 -0
  15. data/lib/presently/version.rb +9 -0
  16. data/lib/presently.rb +9 -0
  17. data/license.md +21 -0
  18. data/public/_components/@socketry/syntax/Syntax/CodeElement.js +337 -0
  19. data/public/_components/@socketry/syntax/Syntax/Errors.js +52 -0
  20. data/public/_components/@socketry/syntax/Syntax/Language/apache.js +49 -0
  21. data/public/_components/@socketry/syntax/Syntax/Language/applescript.js +157 -0
  22. data/public/_components/@socketry/syntax/Syntax/Language/assembly.js +42 -0
  23. data/public/_components/@socketry/syntax/Syntax/Language/bash-script.js +108 -0
  24. data/public/_components/@socketry/syntax/Syntax/Language/bash.js +32 -0
  25. data/public/_components/@socketry/syntax/Syntax/Language/basic.js +232 -0
  26. data/public/_components/@socketry/syntax/Syntax/Language/c++.js +1 -0
  27. data/public/_components/@socketry/syntax/Syntax/Language/c.js +1 -0
  28. data/public/_components/@socketry/syntax/Syntax/Language/clang.js +201 -0
  29. data/public/_components/@socketry/syntax/Syntax/Language/cpp.js +1 -0
  30. data/public/_components/@socketry/syntax/Syntax/Language/csharp.js +166 -0
  31. data/public/_components/@socketry/syntax/Syntax/Language/css.js +244 -0
  32. data/public/_components/@socketry/syntax/Syntax/Language/diff.js +24 -0
  33. data/public/_components/@socketry/syntax/Syntax/Language/go.js +135 -0
  34. data/public/_components/@socketry/syntax/Syntax/Language/haskell.js +110 -0
  35. data/public/_components/@socketry/syntax/Syntax/Language/html.js +69 -0
  36. data/public/_components/@socketry/syntax/Syntax/Language/io.js +68 -0
  37. data/public/_components/@socketry/syntax/Syntax/Language/java.js +134 -0
  38. data/public/_components/@socketry/syntax/Syntax/Language/javascript.js +89 -0
  39. data/public/_components/@socketry/syntax/Syntax/Language/json.js +36 -0
  40. data/public/_components/@socketry/syntax/Syntax/Language/lisp.js +38 -0
  41. data/public/_components/@socketry/syntax/Syntax/Language/lua.js +87 -0
  42. data/public/_components/@socketry/syntax/Syntax/Language/markdown.js +112 -0
  43. data/public/_components/@socketry/syntax/Syntax/Language/nginx.js +37 -0
  44. data/public/_components/@socketry/syntax/Syntax/Language/objective-c.js +1 -0
  45. data/public/_components/@socketry/syntax/Syntax/Language/ocaml.js +225 -0
  46. data/public/_components/@socketry/syntax/Syntax/Language/pascal.js +166 -0
  47. data/public/_components/@socketry/syntax/Syntax/Language/patch.js +2 -0
  48. data/public/_components/@socketry/syntax/Syntax/Language/perl5.js +317 -0
  49. data/public/_components/@socketry/syntax/Syntax/Language/php-script.js +112 -0
  50. data/public/_components/@socketry/syntax/Syntax/Language/php.js +18 -0
  51. data/public/_components/@socketry/syntax/Syntax/Language/plain.js +20 -0
  52. data/public/_components/@socketry/syntax/Syntax/Language/protobuf.js +77 -0
  53. data/public/_components/@socketry/syntax/Syntax/Language/python.js +208 -0
  54. data/public/_components/@socketry/syntax/Syntax/Language/ruby.js +124 -0
  55. data/public/_components/@socketry/syntax/Syntax/Language/scala.js +81 -0
  56. data/public/_components/@socketry/syntax/Syntax/Language/smalltalk.js +30 -0
  57. data/public/_components/@socketry/syntax/Syntax/Language/sql.js +865 -0
  58. data/public/_components/@socketry/syntax/Syntax/Language/super-collider.js +70 -0
  59. data/public/_components/@socketry/syntax/Syntax/Language/swift.js +176 -0
  60. data/public/_components/@socketry/syntax/Syntax/Language/xml.js +76 -0
  61. data/public/_components/@socketry/syntax/Syntax/Language/xrb.js +33 -0
  62. data/public/_components/@socketry/syntax/Syntax/Language/yaml.js +29 -0
  63. data/public/_components/@socketry/syntax/Syntax/Language.js +276 -0
  64. data/public/_components/@socketry/syntax/Syntax/Loader.js +78 -0
  65. data/public/_components/@socketry/syntax/Syntax/Match.js +546 -0
  66. data/public/_components/@socketry/syntax/Syntax/Rule.js +306 -0
  67. data/public/_components/@socketry/syntax/Syntax.js +356 -0
  68. data/public/_components/@socketry/syntax/bin/syntax-ast.js +42 -0
  69. data/public/_components/@socketry/syntax/examples/_template.html +53 -0
  70. data/public/_components/@socketry/syntax/examples/apache.html +72 -0
  71. data/public/_components/@socketry/syntax/examples/applescript.html +72 -0
  72. data/public/_components/@socketry/syntax/examples/assembly.html +74 -0
  73. data/public/_components/@socketry/syntax/examples/bash.html +90 -0
  74. data/public/_components/@socketry/syntax/examples/basic.html +87 -0
  75. data/public/_components/@socketry/syntax/examples/c.html +141 -0
  76. data/public/_components/@socketry/syntax/examples/clang.html +202 -0
  77. data/public/_components/@socketry/syntax/examples/csharp.html +110 -0
  78. data/public/_components/@socketry/syntax/examples/css-colors.html +179 -0
  79. data/public/_components/@socketry/syntax/examples/custom-theme.html +155 -0
  80. data/public/_components/@socketry/syntax/examples/diff.html +142 -0
  81. data/public/_components/@socketry/syntax/examples/examples.css +216 -0
  82. data/public/_components/@socketry/syntax/examples/go.html +413 -0
  83. data/public/_components/@socketry/syntax/examples/haskell.html +373 -0
  84. data/public/_components/@socketry/syntax/examples/html.html +316 -0
  85. data/public/_components/@socketry/syntax/examples/index.html +97 -0
  86. data/public/_components/@socketry/syntax/examples/io.html +552 -0
  87. data/public/_components/@socketry/syntax/examples/java.html +786 -0
  88. data/public/_components/@socketry/syntax/examples/javascript.html +199 -0
  89. data/public/_components/@socketry/syntax/examples/json.html +150 -0
  90. data/public/_components/@socketry/syntax/examples/lisp.html +476 -0
  91. data/public/_components/@socketry/syntax/examples/lua.html +737 -0
  92. data/public/_components/@socketry/syntax/examples/markdown.html +121 -0
  93. data/public/_components/@socketry/syntax/examples/mixed.html +306 -0
  94. data/public/_components/@socketry/syntax/examples/nginx.html +554 -0
  95. data/public/_components/@socketry/syntax/examples/ocaml.html +596 -0
  96. data/public/_components/@socketry/syntax/examples/pascal.html +762 -0
  97. data/public/_components/@socketry/syntax/examples/perl5.html +488 -0
  98. data/public/_components/@socketry/syntax/examples/php-script.html +142 -0
  99. data/public/_components/@socketry/syntax/examples/php.html +95 -0
  100. data/public/_components/@socketry/syntax/examples/plain.html +222 -0
  101. data/public/_components/@socketry/syntax/examples/protobuf.html +405 -0
  102. data/public/_components/@socketry/syntax/examples/python.html +82 -0
  103. data/public/_components/@socketry/syntax/examples/readme.md +79 -0
  104. data/public/_components/@socketry/syntax/examples/ruby.html +58 -0
  105. data/public/_components/@socketry/syntax/examples/scala.html +41 -0
  106. data/public/_components/@socketry/syntax/examples/smalltalk.html +436 -0
  107. data/public/_components/@socketry/syntax/examples/sql.html +373 -0
  108. data/public/_components/@socketry/syntax/examples/super-collider.html +55 -0
  109. data/public/_components/@socketry/syntax/examples/swift.html +176 -0
  110. data/public/_components/@socketry/syntax/examples/wrap-demo.html +103 -0
  111. data/public/_components/@socketry/syntax/examples/xml.html +112 -0
  112. data/public/_components/@socketry/syntax/examples/xrb.html +37 -0
  113. data/public/_components/@socketry/syntax/examples/yaml.html +72 -0
  114. data/public/_components/@socketry/syntax/license.md +21 -0
  115. data/public/_components/@socketry/syntax/package-lock.json +834 -0
  116. data/public/_components/@socketry/syntax/package.json +43 -0
  117. data/public/_components/@socketry/syntax/readme.md +162 -0
  118. data/public/_components/@socketry/syntax/test/Syntax/CodeElement.js +306 -0
  119. data/public/_components/@socketry/syntax/test/Syntax/ErrorHandling.js +85 -0
  120. data/public/_components/@socketry/syntax/test/Syntax/Language/apache.js +153 -0
  121. data/public/_components/@socketry/syntax/test/Syntax/Language/applescript.js +198 -0
  122. data/public/_components/@socketry/syntax/test/Syntax/Language/assembly.js +209 -0
  123. data/public/_components/@socketry/syntax/test/Syntax/Language/bash-script.js +225 -0
  124. data/public/_components/@socketry/syntax/test/Syntax/Language/bash.js +162 -0
  125. data/public/_components/@socketry/syntax/test/Syntax/Language/basic.js +265 -0
  126. data/public/_components/@socketry/syntax/test/Syntax/Language/clang.js +390 -0
  127. data/public/_components/@socketry/syntax/test/Syntax/Language/csharp.js +436 -0
  128. data/public/_components/@socketry/syntax/test/Syntax/Language/css.js +431 -0
  129. data/public/_components/@socketry/syntax/test/Syntax/Language/diff.js +206 -0
  130. data/public/_components/@socketry/syntax/test/Syntax/Language/go.js +386 -0
  131. data/public/_components/@socketry/syntax/test/Syntax/Language/haskell.js +454 -0
  132. data/public/_components/@socketry/syntax/test/Syntax/Language/html.js +111 -0
  133. data/public/_components/@socketry/syntax/test/Syntax/Language/io.js +229 -0
  134. data/public/_components/@socketry/syntax/test/Syntax/Language/java.js +362 -0
  135. data/public/_components/@socketry/syntax/test/Syntax/Language/javascript.js +101 -0
  136. data/public/_components/@socketry/syntax/test/Syntax/Language/json.js +101 -0
  137. data/public/_components/@socketry/syntax/test/Syntax/Language/lisp.js +224 -0
  138. data/public/_components/@socketry/syntax/test/Syntax/Language/lua.js +307 -0
  139. data/public/_components/@socketry/syntax/test/Syntax/Language/markdown.js +163 -0
  140. data/public/_components/@socketry/syntax/test/Syntax/Language/nginx.js +267 -0
  141. data/public/_components/@socketry/syntax/test/Syntax/Language/ocaml.js +299 -0
  142. data/public/_components/@socketry/syntax/test/Syntax/Language/pascal.js +311 -0
  143. data/public/_components/@socketry/syntax/test/Syntax/Language/perl5.js +333 -0
  144. data/public/_components/@socketry/syntax/test/Syntax/Language/php-script.js +197 -0
  145. data/public/_components/@socketry/syntax/test/Syntax/Language/php.js +92 -0
  146. data/public/_components/@socketry/syntax/test/Syntax/Language/plain.js +327 -0
  147. data/public/_components/@socketry/syntax/test/Syntax/Language/protobuf.js +294 -0
  148. data/public/_components/@socketry/syntax/test/Syntax/Language/python.js +213 -0
  149. data/public/_components/@socketry/syntax/test/Syntax/Language/ruby.js +70 -0
  150. data/public/_components/@socketry/syntax/test/Syntax/Language/scala.js +75 -0
  151. data/public/_components/@socketry/syntax/test/Syntax/Language/smalltalk.js +223 -0
  152. data/public/_components/@socketry/syntax/test/Syntax/Language/sql.js +281 -0
  153. data/public/_components/@socketry/syntax/test/Syntax/Language/super-collider.js +66 -0
  154. data/public/_components/@socketry/syntax/test/Syntax/Language/swift.js +71 -0
  155. data/public/_components/@socketry/syntax/test/Syntax/Language/xml.js +170 -0
  156. data/public/_components/@socketry/syntax/test/Syntax/Language/xrb.js +57 -0
  157. data/public/_components/@socketry/syntax/test/Syntax/Language/yaml.js +123 -0
  158. data/public/_components/@socketry/syntax/test/Syntax/Language.js +62 -0
  159. data/public/_components/@socketry/syntax/test/Syntax/Match.js +40 -0
  160. data/public/_components/@socketry/syntax/test/Syntax/Rule.js +251 -0
  161. data/public/_components/@socketry/syntax/test/Syntax.js +38 -0
  162. data/public/_components/@socketry/syntax/test/helpers/ast-matcher.js +90 -0
  163. data/public/_components/@socketry/syntax/themes/base/apache.css +1 -0
  164. data/public/_components/@socketry/syntax/themes/base/applescript.css +1 -0
  165. data/public/_components/@socketry/syntax/themes/base/assembly.css +1 -0
  166. data/public/_components/@socketry/syntax/themes/base/bash.css +1 -0
  167. data/public/_components/@socketry/syntax/themes/base/basic.css +1 -0
  168. data/public/_components/@socketry/syntax/themes/base/c.css +1 -0
  169. data/public/_components/@socketry/syntax/themes/base/clang.css +0 -0
  170. data/public/_components/@socketry/syntax/themes/base/csharp.css +1 -0
  171. data/public/_components/@socketry/syntax/themes/base/css.css +22 -0
  172. data/public/_components/@socketry/syntax/themes/base/diff.css +48 -0
  173. data/public/_components/@socketry/syntax/themes/base/go.css +1 -0
  174. data/public/_components/@socketry/syntax/themes/base/haskell.css +1 -0
  175. data/public/_components/@socketry/syntax/themes/base/html.css +1 -0
  176. data/public/_components/@socketry/syntax/themes/base/io.css +1 -0
  177. data/public/_components/@socketry/syntax/themes/base/java.css +1 -0
  178. data/public/_components/@socketry/syntax/themes/base/javascript.css +1 -0
  179. data/public/_components/@socketry/syntax/themes/base/json.css +41 -0
  180. data/public/_components/@socketry/syntax/themes/base/lisp.css +1 -0
  181. data/public/_components/@socketry/syntax/themes/base/lua.css +1 -0
  182. data/public/_components/@socketry/syntax/themes/base/markdown.css +16 -0
  183. data/public/_components/@socketry/syntax/themes/base/nginx.css +1 -0
  184. data/public/_components/@socketry/syntax/themes/base/ocaml.css +1 -0
  185. data/public/_components/@socketry/syntax/themes/base/pascal.css +1 -0
  186. data/public/_components/@socketry/syntax/themes/base/perl5.css +1 -0
  187. data/public/_components/@socketry/syntax/themes/base/php-script.css +1 -0
  188. data/public/_components/@socketry/syntax/themes/base/php.css +1 -0
  189. data/public/_components/@socketry/syntax/themes/base/plain.css +1 -0
  190. data/public/_components/@socketry/syntax/themes/base/protobuf.css +1 -0
  191. data/public/_components/@socketry/syntax/themes/base/python.css +1 -0
  192. data/public/_components/@socketry/syntax/themes/base/ruby.css +23 -0
  193. data/public/_components/@socketry/syntax/themes/base/scala.css +3 -0
  194. data/public/_components/@socketry/syntax/themes/base/smalltalk.css +1 -0
  195. data/public/_components/@socketry/syntax/themes/base/sql.css +1 -0
  196. data/public/_components/@socketry/syntax/themes/base/super-collider.css +33 -0
  197. data/public/_components/@socketry/syntax/themes/base/swift.css +1 -0
  198. data/public/_components/@socketry/syntax/themes/base/syntax.css +63 -0
  199. data/public/_components/@socketry/syntax/themes/base/xml.css +1 -0
  200. data/public/_components/@socketry/syntax/themes/base/xrb.css +29 -0
  201. data/public/_components/@socketry/syntax/themes/base/yaml.css +1 -0
  202. data/public/_components/@socketry/syntax/themes/theming.md +233 -0
  203. data/public/_components/@socketry/syntax/update-examples.js +135 -0
  204. data/public/_static/index.css +593 -0
  205. data/public/application.js +147 -0
  206. data/readme.md +69 -0
  207. data/releases.md +3 -0
  208. data/templates/code.xrb +12 -0
  209. data/templates/default.xrb +5 -0
  210. data/templates/image.xrb +8 -0
  211. data/templates/section.xrb +5 -0
  212. data/templates/title.xrb +8 -0
  213. data/templates/translation.xrb +8 -0
  214. data/templates/two_column.xrb +8 -0
  215. metadata +280 -0
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Tests for Io language syntax highlighting
3
+ */
4
+
5
+ import {test} from 'node:test';
6
+ import assert from 'node:assert/strict';
7
+ import {JSDOM} from 'jsdom';
8
+ import Syntax from '../../../Syntax.js';
9
+
10
+ const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
11
+ global.window = dom.window;
12
+ global.document = dom.window.document;
13
+ global.HTMLElement = dom.window.HTMLElement;
14
+ global.customElements = dom.window.customElements;
15
+
16
+ const syntax = new Syntax();
17
+
18
+ test('Io language can be registered', async () => {
19
+ const language = await syntax.getResource('io');
20
+ assert.ok(language);
21
+ assert.equal(language.name, 'io');
22
+ });
23
+
24
+ test('Io can match return keyword', async () => {
25
+ const language = await syntax.getResource('io');
26
+ const matches = await language.getMatches(syntax, 'return 42');
27
+ const keywords = matches.filter(m => m.type === 'keyword');
28
+ assert.ok(keywords.some(m => m.value === 'return'));
29
+ });
30
+
31
+ test('Io can match assignment operator', async () => {
32
+ const language = await syntax.getResource('io');
33
+ const matches = await language.getMatches(syntax, 'x := 42');
34
+ const operators = matches.filter(m => m.type === 'operator');
35
+ assert.ok(operators.some(m => m.value === ':='));
36
+ });
37
+
38
+ test('Io can match slot assignment operator', async () => {
39
+ const language = await syntax.getResource('io');
40
+ const matches = await language.getMatches(syntax, 'x ::= 42');
41
+ const operators = matches.filter(m => m.type === 'operator');
42
+ assert.ok(operators.some(m => m.value === '::='));
43
+ });
44
+
45
+ test('Io can match logical operators', async () => {
46
+ const language = await syntax.getResource('io');
47
+ const matches = await language.getMatches(syntax, 'true or false and true');
48
+ const operators = matches.filter(m => m.type === 'operator');
49
+ assert.ok(operators.some(m => m.value === 'or'));
50
+ assert.ok(operators.some(m => m.value === 'and'));
51
+ });
52
+
53
+ test('Io can match at operator', async () => {
54
+ const language = await syntax.getResource('io');
55
+ const matches = await language.getMatches(syntax, 'obj @method');
56
+ const operators = matches.filter(m => m.type === 'operator');
57
+ assert.ok(operators.some(m => m.value === '@'));
58
+ });
59
+
60
+ test('Io can match arithmetic operators', async () => {
61
+ const language = await syntax.getResource('io');
62
+ const matches = await language.getMatches(syntax, 'x + y - z * a / b % c');
63
+ const operators = matches.filter(m => m.type === 'operator');
64
+ assert.ok(operators.some(m => m.value === '+'));
65
+ assert.ok(operators.some(m => m.value === '-'));
66
+ assert.ok(operators.some(m => m.value === '*'));
67
+ assert.ok(operators.some(m => m.value === '/'));
68
+ assert.ok(operators.some(m => m.value === '%'));
69
+ });
70
+
71
+ test('Io can match bitwise operators', async () => {
72
+ const language = await syntax.getResource('io');
73
+ const matches = await language.getMatches(syntax, 'x & y | z ~ a');
74
+ const operators = matches.filter(m => m.type === 'operator');
75
+ assert.ok(operators.some(m => m.value === '&'));
76
+ assert.ok(operators.some(m => m.value === '|'));
77
+ assert.ok(operators.some(m => m.value === '~'));
78
+ });
79
+
80
+ test('Io can match comparison operators', async () => {
81
+ const language = await syntax.getResource('io');
82
+ const matches = await language.getMatches(syntax, 'x < y = z > a');
83
+ const operators = matches.filter(m => m.type === 'operator');
84
+ assert.ok(operators.some(m => m.value === '<'));
85
+ assert.ok(operators.some(m => m.value === '='));
86
+ assert.ok(operators.some(m => m.value === '>'));
87
+ });
88
+
89
+ test('Io can match bracket operators', async () => {
90
+ const language = await syntax.getResource('io');
91
+ const matches = await language.getMatches(syntax, 'x := [1, 2, 3]');
92
+ const operators = matches.filter(m => m.type === 'operator');
93
+ // Brackets are operators in the Io syntax definition
94
+ assert.ok(operators.length > 0);
95
+ });
96
+
97
+ test('Io can match new operator', async () => {
98
+ const language = await syntax.getResource('io');
99
+ const matches = await language.getMatches(syntax, 'obj := Object new');
100
+ const operators = matches.filter(m => m.type === 'operator');
101
+ assert.ok(operators.some(m => m.value === 'new'));
102
+ });
103
+
104
+ test('Io can match space-delimited method invocations', async () => {
105
+ const language = await syntax.getResource('io');
106
+ const matches = await language.getMatches(syntax, 'obj println');
107
+ const functions = matches.filter(m => m.type === 'function');
108
+ assert.ok(functions.some(m => m.value === 'println'));
109
+ });
110
+
111
+ test('Io can match method calls after parentheses', async () => {
112
+ const language = await syntax.getResource('io');
113
+ const matches = await language.getMatches(syntax, 'list(1, 2) println');
114
+ const functions = matches.filter(m => m.type === 'function');
115
+ assert.ok(functions.some(m => m.value === 'println'));
116
+ });
117
+
118
+ test('Io can match CamelCase types', async () => {
119
+ const language = await syntax.getResource('io');
120
+ const matches = await language.getMatches(syntax, 'Person := Object clone');
121
+ const types = matches.filter(m => m.type === 'type');
122
+ assert.ok(types.some(m => m.value === 'Person'));
123
+ assert.ok(types.some(m => m.value === 'Object'));
124
+ });
125
+
126
+ test('Io can match Perl-style comments', async () => {
127
+ const language = await syntax.getResource('io');
128
+ const matches = await language.getMatches(syntax, '# This is a comment');
129
+ const comments = matches.filter(m => m.type === 'comment');
130
+ assert.ok(comments.some(m => m.value === '# This is a comment'));
131
+ });
132
+
133
+ test('Io can match C-style comments', async () => {
134
+ const language = await syntax.getResource('io');
135
+ const matches = await language.getMatches(syntax, '/* This is a comment */');
136
+ const comments = matches.filter(m => m.type === 'comment');
137
+ assert.ok(comments.some(m => m.value === '/* This is a comment */'));
138
+ });
139
+
140
+ test('Io can match C++-style comments', async () => {
141
+ const language = await syntax.getResource('io');
142
+ const matches = await language.getMatches(
143
+ syntax,
144
+ '// This is a comment\nx := 5'
145
+ );
146
+ const comments = matches.filter(m => m.type === 'comment');
147
+ assert.ok(comments.some(m => m.value === '// This is a comment'));
148
+ });
149
+
150
+ test('Io can match single-quoted strings', async () => {
151
+ const language = await syntax.getResource('io');
152
+ const matches = await language.getMatches(syntax, "'Hello, World!'");
153
+ const strings = matches.filter(m => m.type === 'string');
154
+ assert.ok(strings.some(m => m.value === "'Hello, World!'"));
155
+ });
156
+
157
+ test('Io can match double-quoted strings', async () => {
158
+ const language = await syntax.getResource('io');
159
+ const matches = await language.getMatches(syntax, '"Hello, World!"');
160
+ const strings = matches.filter(m => m.type === 'string');
161
+ assert.ok(strings.some(m => m.value === '"Hello, World!"'));
162
+ });
163
+
164
+ test('Io can match string escapes', async () => {
165
+ const language = await syntax.getResource('io');
166
+ const matches = await language.getMatches(syntax, '"Line 1\\nLine 2"');
167
+ const strings = matches.filter(m => m.type === 'string');
168
+ assert.ok(strings.length > 0);
169
+ });
170
+
171
+ test('Io can match decimal numbers', async () => {
172
+ const language = await syntax.getResource('io');
173
+ const matches = await language.getMatches(syntax, 'x := 42; y := 3.14');
174
+ const numbers = matches.filter(m => m.type === 'constant');
175
+ assert.ok(numbers.some(m => m.value === '42'));
176
+ assert.ok(numbers.some(m => m.value === '3.14'));
177
+ });
178
+
179
+ test('Io can match hexadecimal numbers', async () => {
180
+ const language = await syntax.getResource('io');
181
+ const matches = await language.getMatches(syntax, 'color := 0xFF00AA');
182
+ const numbers = matches.filter(m => m.type === 'constant');
183
+ assert.ok(numbers.some(m => m.value === '0xFF00AA'));
184
+ });
185
+
186
+ test('Io can process object cloning', async () => {
187
+ const language = await syntax.getResource('io');
188
+ const code = 'Person := Object clone';
189
+ const matches = await language.getMatches(syntax, code);
190
+ assert.ok(matches.length > 0);
191
+
192
+ const types = matches.filter(m => m.type === 'type');
193
+ assert.ok(types.some(m => m.value === 'Person'));
194
+ assert.ok(types.some(m => m.value === 'Object'));
195
+ });
196
+
197
+ test('Io can process method definitions', async () => {
198
+ const language = await syntax.getResource('io');
199
+ const code = 'Person greet := method("Hello, " .. self name)';
200
+ const matches = await language.getMatches(syntax, code);
201
+ assert.ok(matches.length > 0);
202
+
203
+ const types = matches.filter(m => m.type === 'type');
204
+ assert.ok(types.some(m => m.value === 'Person'));
205
+ });
206
+
207
+ test('Io can process complete program', async () => {
208
+ const language = await syntax.getResource('io');
209
+ const code = `# Factorial function
210
+ factorial := method(n,
211
+ if(n <= 1,
212
+ return 1,
213
+ return n * factorial(n - 1)
214
+ )
215
+ )
216
+
217
+ factorial(5) println`;
218
+ const matches = await language.getMatches(syntax, code);
219
+ assert.ok(matches.length > 0);
220
+
221
+ const comments = matches.filter(m => m.type === 'comment');
222
+ assert.ok(comments.some(m => m.value === '# Factorial function'));
223
+
224
+ const keywords = matches.filter(m => m.type === 'keyword');
225
+ assert.ok(keywords.some(m => m.value === 'return'));
226
+
227
+ const operators = matches.filter(m => m.type === 'operator');
228
+ assert.ok(operators.some(m => m.value === ':='));
229
+ });
@@ -0,0 +1,362 @@
1
+ /**
2
+ * Tests for Java language syntax highlighting
3
+ */
4
+
5
+ import {test} from 'node:test';
6
+ import assert from 'node:assert/strict';
7
+ import {JSDOM} from 'jsdom';
8
+ import Syntax from '../../../Syntax.js';
9
+
10
+ const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
11
+ global.window = dom.window;
12
+ global.document = dom.window.document;
13
+ global.HTMLElement = dom.window.HTMLElement;
14
+ global.customElements = dom.window.customElements;
15
+
16
+ const syntax = new Syntax();
17
+
18
+ test('Java language can be registered', async () => {
19
+ const language = await syntax.getResource('java');
20
+ assert.ok(language);
21
+ assert.equal(language.name, 'java');
22
+ });
23
+
24
+ test('Java can match class keyword', async () => {
25
+ const language = await syntax.getResource('java');
26
+ const matches = await language.getMatches(syntax, 'public class MyClass { }');
27
+ const keywords = matches.filter(m => m.type === 'keyword');
28
+ assert.ok(keywords.some(m => m.value === 'class'));
29
+ });
30
+
31
+ test('Java can match control flow keywords', async () => {
32
+ const language = await syntax.getResource('java');
33
+ const matches = await language.getMatches(
34
+ syntax,
35
+ 'if (x > 0) { return true; } else { return false; }'
36
+ );
37
+ const keywords = matches.filter(m => m.type === 'keyword');
38
+ assert.ok(keywords.some(m => m.value === 'if'));
39
+ assert.ok(keywords.some(m => m.value === 'else'));
40
+ assert.ok(keywords.some(m => m.value === 'return'));
41
+ });
42
+
43
+ test('Java can match loop keywords', async () => {
44
+ const language = await syntax.getResource('java');
45
+ const matches = await language.getMatches(
46
+ syntax,
47
+ 'for (int i = 0; i < 10; i++) { while (true) { break; } }'
48
+ );
49
+ const keywords = matches.filter(m => m.type === 'keyword');
50
+ assert.ok(keywords.some(m => m.value === 'for'));
51
+ assert.ok(keywords.some(m => m.value === 'while'));
52
+ assert.ok(keywords.some(m => m.value === 'break'));
53
+ });
54
+
55
+ test('Java can match exception keywords', async () => {
56
+ const language = await syntax.getResource('java');
57
+ const matches = await language.getMatches(
58
+ syntax,
59
+ 'try { } catch (Exception e) { throw e; } finally { }'
60
+ );
61
+ const keywords = matches.filter(m => m.type === 'keyword');
62
+ assert.ok(keywords.some(m => m.value === 'try'));
63
+ assert.ok(keywords.some(m => m.value === 'catch'));
64
+ assert.ok(keywords.some(m => m.value === 'throw'));
65
+ assert.ok(keywords.some(m => m.value === 'finally'));
66
+ });
67
+
68
+ test('Java can match access modifiers', async () => {
69
+ const language = await syntax.getResource('java');
70
+ const matches = await language.getMatches(
71
+ syntax,
72
+ 'public private protected package'
73
+ );
74
+ const access = matches.filter(m => m.type === 'access');
75
+ assert.ok(access.some(m => m.value === 'public'));
76
+ assert.ok(access.some(m => m.value === 'private'));
77
+ assert.ok(access.some(m => m.value === 'protected'));
78
+ assert.ok(access.some(m => m.value === 'package'));
79
+ });
80
+
81
+ test('Java can match primitive types', async () => {
82
+ const language = await syntax.getResource('java');
83
+ const matches = await language.getMatches(
84
+ syntax,
85
+ 'int x; double y; boolean flag; char c;'
86
+ );
87
+ const types = matches.filter(m => m.type === 'type');
88
+ assert.ok(types.some(m => m.value === 'int'));
89
+ assert.ok(types.some(m => m.value === 'double'));
90
+ assert.ok(types.some(m => m.value === 'boolean'));
91
+ assert.ok(types.some(m => m.value === 'char'));
92
+ });
93
+
94
+ test('Java can match void type', async () => {
95
+ const language = await syntax.getResource('java');
96
+ const matches = await language.getMatches(syntax, 'void method() { }');
97
+ const types = matches.filter(m => m.type === 'type');
98
+ assert.ok(types.some(m => m.value === 'void'));
99
+ });
100
+
101
+ test('Java can match constants', async () => {
102
+ const language = await syntax.getResource('java');
103
+ const matches = await language.getMatches(
104
+ syntax,
105
+ 'this.value = true; that.value = false; x = null;'
106
+ );
107
+ const constants = matches.filter(m => m.type === 'constant');
108
+ assert.ok(constants.some(m => m.value === 'this'));
109
+ assert.ok(constants.some(m => m.value === 'true'));
110
+ assert.ok(constants.some(m => m.value === 'false'));
111
+ assert.ok(constants.some(m => m.value === 'null'));
112
+ });
113
+
114
+ test('Java can match comparison operators', async () => {
115
+ const language = await syntax.getResource('java');
116
+ const matches = await language.getMatches(
117
+ syntax,
118
+ 'if (a == b && c != d || e < f && g > h)'
119
+ );
120
+ const operators = matches.filter(m => m.type === 'operator');
121
+ assert.ok(operators.some(m => m.value === '=='));
122
+ assert.ok(operators.some(m => m.value === '!='));
123
+ assert.ok(operators.some(m => m.value === '<'));
124
+ assert.ok(operators.some(m => m.value === '>'));
125
+ assert.ok(operators.some(m => m.value === '&&'));
126
+ assert.ok(operators.some(m => m.value === '||'));
127
+ });
128
+
129
+ test('Java can match assignment operators', async () => {
130
+ const language = await syntax.getResource('java');
131
+ const matches = await language.getMatches(syntax, 'x += 5; y -= 3; z *= 2;');
132
+ const operators = matches.filter(m => m.type === 'operator');
133
+ assert.ok(operators.some(m => m.value === '+='));
134
+ assert.ok(operators.some(m => m.value === '-='));
135
+ assert.ok(operators.some(m => m.value === '*='));
136
+ });
137
+
138
+ test('Java can match bitwise operators', async () => {
139
+ const language = await syntax.getResource('java');
140
+ const matches = await language.getMatches(syntax, 'x << 2; y >> 1; z >>> 3;');
141
+ const operators = matches.filter(m => m.type === 'operator');
142
+ assert.ok(operators.some(m => m.value === '<<'));
143
+ assert.ok(operators.some(m => m.value === '>>'));
144
+ assert.ok(operators.some(m => m.value === '>>>'));
145
+ });
146
+
147
+ test('Java can match increment and decrement operators', async () => {
148
+ const language = await syntax.getResource('java');
149
+ const matches = await language.getMatches(syntax, 'i++; j--;');
150
+ const operators = matches.filter(m => m.type === 'operator');
151
+ assert.ok(operators.some(m => m.value === '++'));
152
+ assert.ok(operators.some(m => m.value === '--'));
153
+ });
154
+
155
+ test('Java can match instanceof operator', async () => {
156
+ const language = await syntax.getResource('java');
157
+ const matches = await language.getMatches(
158
+ syntax,
159
+ 'if (obj instanceof String)'
160
+ );
161
+ const operators = matches.filter(m => m.type === 'operator');
162
+ assert.ok(operators.some(m => m.value === 'instanceof'));
163
+ });
164
+
165
+ test('Java can match new operator', async () => {
166
+ const language = await syntax.getResource('java');
167
+ const matches = await language.getMatches(
168
+ syntax,
169
+ 'String s = new String("test");'
170
+ );
171
+ const operators = matches.filter(m => m.type === 'operator');
172
+ assert.ok(operators.some(m => m.value === 'new'));
173
+ });
174
+
175
+ test('Java can match CamelCase types', async () => {
176
+ const language = await syntax.getResource('java');
177
+ const matches = await language.getMatches(
178
+ syntax,
179
+ 'String name; ArrayList<Integer> list;'
180
+ );
181
+ const types = matches.filter(m => m.type === 'type');
182
+ assert.ok(types.some(m => m.value === 'String'));
183
+ assert.ok(types.some(m => m.value === 'ArrayList'));
184
+ assert.ok(types.some(m => m.value === 'Integer'));
185
+ });
186
+
187
+ test('Java can match C-style comments', async () => {
188
+ const language = await syntax.getResource('java');
189
+ const matches = await language.getMatches(syntax, '/* This is a comment */');
190
+ const comments = matches.filter(m => m.type === 'comment');
191
+ assert.ok(comments.some(m => m.value === '/* This is a comment */'));
192
+ });
193
+
194
+ test('Java can match C++-style comments', async () => {
195
+ const language = await syntax.getResource('java');
196
+ const matches = await language.getMatches(
197
+ syntax,
198
+ '// This is a comment\nint x = 5;'
199
+ );
200
+ const comments = matches.filter(m => m.type === 'comment');
201
+ assert.ok(comments.some(m => m.value === '// This is a comment'));
202
+ });
203
+
204
+ test('Java can match decimal numbers', async () => {
205
+ const language = await syntax.getResource('java');
206
+ const matches = await language.getMatches(
207
+ syntax,
208
+ 'int x = 42; double y = 3.14;'
209
+ );
210
+ const numbers = matches.filter(m => m.type === 'constant');
211
+ assert.ok(numbers.some(m => m.value === '42'));
212
+ assert.ok(numbers.some(m => m.value === '3.14'));
213
+ });
214
+
215
+ test('Java can match hexadecimal numbers', async () => {
216
+ const language = await syntax.getResource('java');
217
+ const matches = await language.getMatches(syntax, 'int color = 0xFF00AA;');
218
+ const numbers = matches.filter(m => m.type === 'constant');
219
+ assert.ok(numbers.some(m => m.value === '0xFF00AA'));
220
+ });
221
+
222
+ test('Java can match single-quoted strings', async () => {
223
+ const language = await syntax.getResource('java');
224
+ const matches = await language.getMatches(syntax, "char c = 'a';");
225
+ const strings = matches.filter(m => m.type === 'string');
226
+ assert.ok(strings.some(m => m.value === "'a'"));
227
+ });
228
+
229
+ test('Java can match double-quoted strings', async () => {
230
+ const language = await syntax.getResource('java');
231
+ const matches = await language.getMatches(
232
+ syntax,
233
+ 'String s = "Hello, World!";'
234
+ );
235
+ const strings = matches.filter(m => m.type === 'string');
236
+ assert.ok(strings.some(m => m.value === '"Hello, World!"'));
237
+ });
238
+
239
+ test('Java can match string escapes', async () => {
240
+ const language = await syntax.getResource('java');
241
+ const matches = await language.getMatches(
242
+ syntax,
243
+ 'String s = "Line 1\\nLine 2";'
244
+ );
245
+ const strings = matches.filter(m => m.type === 'string');
246
+ assert.ok(strings.length > 0);
247
+ });
248
+
249
+ test('Java can match function calls', async () => {
250
+ const language = await syntax.getResource('java');
251
+ const matches = await language.getMatches(
252
+ syntax,
253
+ 'System.out.println("Hello");'
254
+ );
255
+ const functions = matches.filter(m => m.type === 'function');
256
+ assert.ok(functions.some(m => m.value === 'println'));
257
+ });
258
+
259
+ test('Java can match method definitions', async () => {
260
+ const language = await syntax.getResource('java');
261
+ const matches = await language.getMatches(
262
+ syntax,
263
+ 'public void doSomething() { }'
264
+ );
265
+ const functions = matches.filter(m => m.type === 'function');
266
+ assert.ok(functions.some(m => m.value === 'doSomething'));
267
+ });
268
+
269
+ test('Java can match interface keyword', async () => {
270
+ const language = await syntax.getResource('java');
271
+ const matches = await language.getMatches(
272
+ syntax,
273
+ 'public interface MyInterface { }'
274
+ );
275
+ const keywords = matches.filter(m => m.type === 'keyword');
276
+ assert.ok(keywords.some(m => m.value === 'interface'));
277
+ });
278
+
279
+ test('Java can match implements keyword', async () => {
280
+ const language = await syntax.getResource('java');
281
+ const matches = await language.getMatches(
282
+ syntax,
283
+ 'class MyClass implements MyInterface { }'
284
+ );
285
+ const keywords = matches.filter(m => m.type === 'keyword');
286
+ assert.ok(keywords.some(m => m.value === 'implements'));
287
+ });
288
+
289
+ test('Java can match extends keyword', async () => {
290
+ const language = await syntax.getResource('java');
291
+ const matches = await language.getMatches(
292
+ syntax,
293
+ 'class Child extends Parent { }'
294
+ );
295
+ const keywords = matches.filter(m => m.type === 'keyword');
296
+ assert.ok(keywords.some(m => m.value === 'extends'));
297
+ });
298
+
299
+ test('Java can match static and final keywords', async () => {
300
+ const language = await syntax.getResource('java');
301
+ const matches = await language.getMatches(
302
+ syntax,
303
+ 'public static final int MAX = 100;'
304
+ );
305
+ const keywords = matches.filter(m => m.type === 'keyword');
306
+ assert.ok(keywords.some(m => m.value === 'static'));
307
+ assert.ok(keywords.some(m => m.value === 'final'));
308
+ });
309
+
310
+ test('Java can match abstract keyword', async () => {
311
+ const language = await syntax.getResource('java');
312
+ const matches = await language.getMatches(
313
+ syntax,
314
+ 'public abstract class MyClass { }'
315
+ );
316
+ const keywords = matches.filter(m => m.type === 'keyword');
317
+ assert.ok(keywords.some(m => m.value === 'abstract'));
318
+ });
319
+
320
+ test('Java can match synchronized keyword', async () => {
321
+ const language = await syntax.getResource('java');
322
+ const matches = await language.getMatches(
323
+ syntax,
324
+ 'synchronized void method() { }'
325
+ );
326
+ const keywords = matches.filter(m => m.type === 'keyword');
327
+ assert.ok(keywords.some(m => m.value === 'synchronized'));
328
+ });
329
+
330
+ test('Java can match enum keyword', async () => {
331
+ const language = await syntax.getResource('java');
332
+ const matches = await language.getMatches(
333
+ syntax,
334
+ 'enum Color { RED, GREEN, BLUE }'
335
+ );
336
+ const keywords = matches.filter(m => m.type === 'keyword');
337
+ assert.ok(keywords.some(m => m.value === 'enum'));
338
+ });
339
+
340
+ test('Java can process complete class definition', async () => {
341
+ const language = await syntax.getResource('java');
342
+ const code = `public class Calculator {
343
+ private int result;
344
+
345
+ public int add(int a, int b) {
346
+ return a + b;
347
+ }
348
+ }`;
349
+ const matches = await language.getMatches(syntax, code);
350
+ assert.ok(matches.length > 0);
351
+
352
+ const access = matches.filter(m => m.type === 'access');
353
+ assert.ok(access.some(m => m.value === 'public'));
354
+ assert.ok(access.some(m => m.value === 'private'));
355
+
356
+ const keywords = matches.filter(m => m.type === 'keyword');
357
+ assert.ok(keywords.some(m => m.value === 'class'));
358
+ assert.ok(keywords.some(m => m.value === 'return'));
359
+
360
+ const types = matches.filter(m => m.type === 'type');
361
+ assert.ok(types.some(m => m.value === 'int'));
362
+ });
@@ -0,0 +1,101 @@
1
+ import Syntax from '../../../Syntax.js';
2
+ import registerJavaScript from '../../../Syntax/Language/javascript.js';
3
+ import {strictEqual, ok} from 'node:assert';
4
+ import test from 'node:test';
5
+
6
+ async function getLanguage() {
7
+ const syntax = new Syntax();
8
+ registerJavaScript(syntax);
9
+ return await syntax.getLanguage('javascript');
10
+ }
11
+
12
+ function typesFrom(matches) {
13
+ return matches.map(m => m.expression.type);
14
+ }
15
+
16
+ test('JavaScript: keywords highlighted', async () => {
17
+ const language = await getLanguage();
18
+ const code =
19
+ 'async function run() { await fetch(); const x = class {}; let y; var z; return yield; }';
20
+ const matches = await language.getMatches(Syntax.default, code);
21
+ const types = typesFrom(matches);
22
+ ok(types.includes('keyword'));
23
+ });
24
+
25
+ test('JavaScript: constants highlighted', async () => {
26
+ const language = await getLanguage();
27
+ const code = 'this === null || true && false';
28
+ const matches = await language.getMatches(Syntax.default, code);
29
+ const constants = matches.filter(m => m.expression.type === 'constant');
30
+ ok(constants.length >= 4);
31
+ });
32
+
33
+ test('JavaScript: operators highlighted', async () => {
34
+ const language = await getLanguage();
35
+ const code = 'a + b * c / d - e & f | g ~ h ! i % j < k = l > m';
36
+ const matches = await language.getMatches(Syntax.default, code);
37
+ const operators = matches.filter(m => m.expression.type === 'operator');
38
+ ok(operators.length > 0);
39
+ });
40
+
41
+ test('JavaScript: access modifiers highlighted', async () => {
42
+ const language = await getLanguage();
43
+ const code =
44
+ 'public interface Foo extends Bar implements Baz { private x; protected y; package z; }';
45
+ const matches = await language.getMatches(Syntax.default, code);
46
+ const access = matches.filter(m => m.expression.type === 'access');
47
+ ok(access.length >= 5);
48
+ });
49
+
50
+ test('JavaScript: regex literals', async () => {
51
+ const language = await getLanguage();
52
+ const code = 'const pattern = /test\\d+/gi;';
53
+ const matches = await language.getMatches(Syntax.default, code);
54
+ const regex = matches.filter(
55
+ m => m.expression.type === 'constant' && m.value.startsWith('/')
56
+ );
57
+ ok(regex.length >= 1);
58
+ });
59
+
60
+ test('JavaScript: comments', async () => {
61
+ const language = await getLanguage();
62
+ const code = '/* block */ // line';
63
+ const matches = await language.getMatches(Syntax.default, code);
64
+ const comments = matches.filter(m => m.expression.type === 'comment');
65
+ ok(comments.length >= 2);
66
+ });
67
+
68
+ test('JavaScript: strings', async () => {
69
+ const language = await getLanguage();
70
+ const code =
71
+ 'const a = "double"; const b = \'single\'; const c = "esc\\"ape";';
72
+ const matches = await language.getMatches(Syntax.default, code);
73
+ const strings = matches.filter(m => m.expression.type === 'string');
74
+ ok(strings.length >= 3);
75
+ });
76
+
77
+ test('JavaScript: numbers', async () => {
78
+ const language = await getLanguage();
79
+ const code = 'const a = 42; const b = 3.14; const c = 0xFF;';
80
+ const matches = await language.getMatches(Syntax.default, code);
81
+ const numbers = matches.filter(
82
+ m => m.expression.type === 'constant' && /^\d/.test(m.value)
83
+ );
84
+ ok(numbers.length >= 3);
85
+ });
86
+
87
+ test('JavaScript: function calls', async () => {
88
+ const language = await getLanguage();
89
+ const code = 'console.log("test"); Math.max(1, 2);';
90
+ const matches = await language.getMatches(Syntax.default, code);
91
+ const functions = matches.filter(m => m.expression.type === 'function');
92
+ ok(functions.length >= 2);
93
+ });
94
+
95
+ test('JavaScript: CamelCase types', async () => {
96
+ const language = await getLanguage();
97
+ const code = 'const obj = new MyClass();';
98
+ const matches = await language.getMatches(Syntax.default, code);
99
+ const types = matches.filter(m => m.expression.type === 'type');
100
+ ok(types.length >= 1);
101
+ });