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,333 @@
1
+ /**
2
+ * Tests for Perl 5 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('Perl 5 language can be registered', async () => {
19
+ const language = await syntax.getResource('perl5');
20
+ assert.ok(language);
21
+ assert.equal(language.name, 'perl5');
22
+ });
23
+
24
+ test('Perl 5: keywords', async () => {
25
+ const language = await syntax.getResource('perl5');
26
+ const matches = await language.getMatches(
27
+ syntax,
28
+ 'if my foreach while unless until sub package'
29
+ );
30
+ const keywords = matches.filter(match => match.type === 'keyword');
31
+ assert.ok(keywords.length >= 8);
32
+ assert.ok(keywords.some(k => k.value === 'if'));
33
+ assert.ok(keywords.some(k => k.value === 'my'));
34
+ assert.ok(keywords.some(k => k.value === 'foreach'));
35
+ assert.ok(keywords.some(k => k.value === 'while'));
36
+ });
37
+
38
+ test('Perl 5: constants', async () => {
39
+ const language = await syntax.getResource('perl5');
40
+ const matches = await language.getMatches(syntax, 'this true false');
41
+ const constants = matches.filter(match => match.type === 'constant');
42
+ assert.ok(constants.some(c => c.value === 'this'));
43
+ assert.ok(constants.some(c => c.value === 'true'));
44
+ assert.ok(constants.some(c => c.value === 'false'));
45
+ });
46
+
47
+ test('Perl 5: operators', async () => {
48
+ const language = await syntax.getResource('perl5');
49
+ const matches = await language.getMatches(
50
+ syntax,
51
+ '+ - * / % ** && || // => <=> =~ !~'
52
+ );
53
+ const operators = matches.filter(match => match.type === 'operator');
54
+ assert.ok(operators.length >= 10);
55
+ assert.ok(operators.some(op => op.value === '+'));
56
+ assert.ok(operators.some(op => op.value === '**'));
57
+ assert.ok(operators.some(op => op.value === '&&'));
58
+ assert.ok(operators.some(op => op.value === '//'));
59
+ assert.ok(operators.some(op => op.value === '=>'));
60
+ assert.ok(operators.some(op => op.value === '<=>'));
61
+ assert.ok(operators.some(op => op.value === '=~'));
62
+ assert.ok(operators.some(op => op.value === '!~'));
63
+ });
64
+
65
+ test('Perl 5: built-in functions', async () => {
66
+ const language = await syntax.getResource('perl5');
67
+ const matches = await language.getMatches(
68
+ syntax,
69
+ 'print push pop shift unshift grep map join split'
70
+ );
71
+ const functions = matches.filter(match => match.type === 'function');
72
+ assert.ok(functions.length >= 9);
73
+ assert.ok(functions.some(fn => fn.value === 'print'));
74
+ assert.ok(functions.some(fn => fn.value === 'push'));
75
+ assert.ok(functions.some(fn => fn.value === 'grep'));
76
+ assert.ok(functions.some(fn => fn.value === 'map'));
77
+ });
78
+
79
+ test('Perl 5: variables', async () => {
80
+ const language = await syntax.getResource('perl5');
81
+ const matches = await language.getMatches(syntax, '$scalar @array %hash');
82
+ const variables = matches.filter(match => match.type === 'variable');
83
+ assert.ok(variables.length >= 3);
84
+ assert.ok(variables.some(v => v.value === '$scalar'));
85
+ assert.ok(variables.some(v => v.value === '@array'));
86
+ assert.ok(variables.some(v => v.value === '%hash'));
87
+ });
88
+
89
+ test('Perl 5: comments', async () => {
90
+ const language = await syntax.getResource('perl5');
91
+ const matches = await language.getMatches(
92
+ syntax,
93
+ '# This is a comment\nmy $x = 1;'
94
+ );
95
+ const comments = matches.filter(match => match.type === 'comment');
96
+ assert.ok(comments.some(c => c.value === '# This is a comment'));
97
+ });
98
+
99
+ test('Perl 5: __END__ marker', async () => {
100
+ const language = await syntax.getResource('perl5');
101
+ const matches = await language.getMatches(
102
+ syntax,
103
+ 'my $x = 1;\n__END__\nThis is documentation after END'
104
+ );
105
+ const comments = matches.filter(match => match.type === 'comment');
106
+ assert.ok(comments.some(c => c.value.includes('__END__')));
107
+ });
108
+
109
+ test('Perl 5: single-quoted strings', async () => {
110
+ const language = await syntax.getResource('perl5');
111
+ const matches = await language.getMatches(syntax, "my $str = 'hello world';");
112
+ const strings = matches.filter(match => match.type === 'string');
113
+ assert.ok(strings.some(s => s.value === "'hello world'"));
114
+ });
115
+
116
+ test('Perl 5: double-quoted strings', async () => {
117
+ const language = await syntax.getResource('perl5');
118
+ const matches = await language.getMatches(syntax, 'my $str = "hello world";');
119
+ const strings = matches.filter(match => match.type === 'string');
120
+ assert.ok(strings.some(s => s.value === '"hello world"'));
121
+ });
122
+
123
+ test('Perl 5: decimal numbers', async () => {
124
+ const language = await syntax.getResource('perl5');
125
+ const matches = await language.getMatches(
126
+ syntax,
127
+ 'my $x = 123; my $y = 45.67;'
128
+ );
129
+ const numbers = matches.filter(
130
+ match => match.type === 'constant' && /^\d/.test(match.value)
131
+ );
132
+ assert.ok(numbers.length >= 2);
133
+ });
134
+
135
+ test('Perl 5: hex numbers', async () => {
136
+ const language = await syntax.getResource('perl5');
137
+ const matches = await language.getMatches(syntax, 'my $hex = 0xFF;');
138
+ const hexNumbers = matches.filter(
139
+ match => match.type === 'constant' && match.value.includes('0x')
140
+ );
141
+ assert.ok(hexNumbers.some(h => h.value === '0xFF'));
142
+ });
143
+
144
+ test('Perl 5: regular expressions', async () => {
145
+ const language = await syntax.getResource('perl5');
146
+ const matches = await language.getMatches(
147
+ syntax,
148
+ 'if ($str =~ /pattern/) { }'
149
+ );
150
+ // Just check that =~ operator is matched
151
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === '=~'));
152
+ });
153
+
154
+ test('Perl 5: function definitions', async () => {
155
+ const language = await syntax.getResource('perl5');
156
+ const matches = await language.getMatches(syntax, 'sub my_function { }');
157
+ // Just check that sub keyword is matched
158
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'sub'));
159
+ });
160
+
161
+ test('Perl 5: complete subroutine', async () => {
162
+ const language = await syntax.getResource('perl5');
163
+ const code = `sub greet {
164
+ my ($name) = @_;
165
+ print "Hello, $name\\n";
166
+ }`;
167
+ const matches = await language.getMatches(syntax, code);
168
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'sub'));
169
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'my'));
170
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'print'));
171
+ });
172
+
173
+ test('Perl 5: array operations', async () => {
174
+ const language = await syntax.getResource('perl5');
175
+ const matches = await language.getMatches(
176
+ syntax,
177
+ 'push @array, $value; my $item = pop @array;'
178
+ );
179
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'push'));
180
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'pop'));
181
+ assert.ok(matches.some(m => m.type === 'variable' && m.value === '@array'));
182
+ });
183
+
184
+ test('Perl 5: hash operations', async () => {
185
+ const language = await syntax.getResource('perl5');
186
+ const matches = await language.getMatches(
187
+ syntax,
188
+ 'my %hash = (key => "value"); my @keys = keys %hash;'
189
+ );
190
+ assert.ok(matches.some(m => m.type === 'variable' && m.value === '%hash'));
191
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'keys'));
192
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === '=>'));
193
+ });
194
+
195
+ test('Perl 5: control flow', async () => {
196
+ const language = await syntax.getResource('perl5');
197
+ const code = `if ($x > 5) {
198
+ print "big";
199
+ } elsif ($x > 2) {
200
+ print "medium";
201
+ } else {
202
+ print "small";
203
+ }`;
204
+ const matches = await language.getMatches(syntax, code);
205
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'if'));
206
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'elsif'));
207
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'else'));
208
+ });
209
+
210
+ test('Perl 5: loops', async () => {
211
+ const language = await syntax.getResource('perl5');
212
+ const code = `foreach my $item (@array) {
213
+ print $item;
214
+ }
215
+ while ($condition) {
216
+ last if $done;
217
+ }`;
218
+ const matches = await language.getMatches(syntax, code);
219
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'foreach'));
220
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'while'));
221
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'last'));
222
+ });
223
+
224
+ test('Perl 5: package declaration', async () => {
225
+ const language = await syntax.getResource('perl5');
226
+ const matches = await language.getMatches(
227
+ syntax,
228
+ 'package MyModule; use strict; use warnings;'
229
+ );
230
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'package'));
231
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'use'));
232
+ });
233
+
234
+ test('Perl 5: object-oriented code', async () => {
235
+ const language = await syntax.getResource('perl5');
236
+ const matches = await language.getMatches(
237
+ syntax,
238
+ 'my $obj = bless {}, "ClassName"; $obj->method();'
239
+ );
240
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'bless'));
241
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === '->'));
242
+ });
243
+
244
+ test('Perl 5: file operations', async () => {
245
+ const language = await syntax.getResource('perl5');
246
+ const matches = await language.getMatches(
247
+ syntax,
248
+ 'open my $fh, "<", "file.txt"; close $fh;'
249
+ );
250
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'open'));
251
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'close'));
252
+ });
253
+
254
+ test('Perl 5: map and grep', async () => {
255
+ const language = await syntax.getResource('perl5');
256
+ const matches = await language.getMatches(
257
+ syntax,
258
+ 'my @doubled = map { $_ * 2 } @numbers; my @filtered = grep { $_ > 5 } @values;'
259
+ );
260
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'map'));
261
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'grep'));
262
+ });
263
+
264
+ test('Perl 5: die and warn', async () => {
265
+ const language = await syntax.getResource('perl5');
266
+ const matches = await language.getMatches(
267
+ syntax,
268
+ 'die "Error!" unless $ok; warn "Warning message";'
269
+ );
270
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'die'));
271
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'warn'));
272
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'unless'));
273
+ });
274
+
275
+ test('Perl 5: reference operators', async () => {
276
+ const language = await syntax.getResource('perl5');
277
+ const matches = await language.getMatches(
278
+ syntax,
279
+ 'my $arrayref = \\@array; my @copy = @{$arrayref};'
280
+ );
281
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === '\\'));
282
+ });
283
+
284
+ test('Perl 5: string operators', async () => {
285
+ const language = await syntax.getResource('perl5');
286
+ const matches = await language.getMatches(
287
+ syntax,
288
+ 'my $str = "hello" . " " . "world"; my $repeated = "x" x 5;'
289
+ );
290
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === '.'));
291
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === 'x'));
292
+ });
293
+
294
+ test('Perl 5: range operator', async () => {
295
+ const language = await syntax.getResource('perl5');
296
+ const matches = await language.getMatches(
297
+ syntax,
298
+ 'my @range = (1..10); my @letters = ("a".."z");'
299
+ );
300
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === '..'));
301
+ });
302
+
303
+ test('Perl 5: logical operators', async () => {
304
+ const language = await syntax.getResource('perl5');
305
+ const matches = await language.getMatches(
306
+ syntax,
307
+ 'if ($a and $b or $c) { } if ($x && $y || $z) { }'
308
+ );
309
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === 'and'));
310
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === 'or'));
311
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === '&&'));
312
+ assert.ok(matches.some(m => m.type === 'operator' && m.value === '||'));
313
+ });
314
+
315
+ test('Perl 5: special variables', async () => {
316
+ const language = await syntax.getResource('perl5');
317
+ const matches = await language.getMatches(
318
+ syntax,
319
+ 'print $_ for @array; my $args = @ARGV;'
320
+ );
321
+ assert.ok(matches.some(m => m.type === 'variable' && m.value === '$_'));
322
+ assert.ok(matches.some(m => m.type === 'variable' && m.value === '@ARGV'));
323
+ });
324
+
325
+ test('Perl 5: eval', async () => {
326
+ const language = await syntax.getResource('perl5');
327
+ const matches = await language.getMatches(
328
+ syntax,
329
+ 'eval { risky_operation(); }; warn $@ if $@;'
330
+ );
331
+ assert.ok(matches.some(m => m.type === 'keyword' && m.value === 'eval'));
332
+ assert.ok(matches.some(m => m.type === 'function' && m.value === 'warn'));
333
+ });
@@ -0,0 +1,197 @@
1
+ import {strictEqual} from 'assert';
2
+ import {test} from 'node:test';
3
+
4
+ import Syntax from '../../../Syntax.js';
5
+ import registerPhpScript from '../../../Syntax/Language/php-script.js';
6
+
7
+ test('PHP-Script: keywords are highlighted', async () => {
8
+ const syntax = new Syntax();
9
+ registerPhpScript(syntax);
10
+ const language = await syntax.getLanguage('php-script');
11
+
12
+ const matches = await language.getMatches(
13
+ syntax,
14
+ 'function class if else while'
15
+ );
16
+ const types = matches.map(m => m.expression.type);
17
+
18
+ strictEqual(types.filter(t => t === 'keyword').length, 5);
19
+ });
20
+
21
+ test('PHP-Script: access modifiers are highlighted', async () => {
22
+ const syntax = new Syntax();
23
+ registerPhpScript(syntax);
24
+ const language = await syntax.getLanguage('php-script');
25
+
26
+ const matches = await language.getMatches(syntax, 'public private protected');
27
+ const types = matches.map(m => m.expression.type);
28
+
29
+ strictEqual(types.filter(t => t === 'access').length, 3);
30
+ });
31
+
32
+ test('PHP-Script: operators are highlighted', async () => {
33
+ const syntax = new Syntax();
34
+ registerPhpScript(syntax);
35
+ const language = await syntax.getLanguage('php-script');
36
+
37
+ const matches = await language.getMatches(syntax, '+ - * / = < > new');
38
+ const types = matches.map(m => m.expression.type);
39
+
40
+ strictEqual(types.filter(t => t === 'operator').length >= 7, true);
41
+ });
42
+
43
+ test('PHP-Script: constants are highlighted', async () => {
44
+ const syntax = new Syntax();
45
+ registerPhpScript(syntax);
46
+ const language = await syntax.getLanguage('php-script');
47
+
48
+ const matches = await language.getMatches(syntax, 'this true false');
49
+ const types = matches.map(m => m.expression.type);
50
+
51
+ strictEqual(types.filter(t => t === 'constant').length, 3);
52
+ });
53
+
54
+ test('PHP-Script: variables are highlighted', async () => {
55
+ const syntax = new Syntax();
56
+ registerPhpScript(syntax);
57
+ const language = await syntax.getLanguage('php-script');
58
+
59
+ const matches = await language.getMatches(syntax, '$name $value $counter');
60
+ const types = matches.map(m => m.expression.type);
61
+
62
+ strictEqual(types.filter(t => t === 'variable').length, 3);
63
+ });
64
+
65
+ test('PHP-Script: functions are highlighted', async () => {
66
+ const syntax = new Syntax();
67
+ registerPhpScript(syntax);
68
+ const language = await syntax.getLanguage('php-script');
69
+
70
+ const matches = await language.getMatches(
71
+ syntax,
72
+ 'strlen($str) array_push($arr, $item)'
73
+ );
74
+ const types = matches.map(m => m.expression.type);
75
+
76
+ strictEqual(types.filter(t => t === 'function').length, 2);
77
+ });
78
+
79
+ test('PHP-Script: camel case types are highlighted', async () => {
80
+ const syntax = new Syntax();
81
+ registerPhpScript(syntax);
82
+ const language = await syntax.getLanguage('php-script');
83
+
84
+ const matches = await language.getMatches(
85
+ syntax,
86
+ 'MyClass DateTime Exception'
87
+ );
88
+ const types = matches.map(m => m.expression.type);
89
+
90
+ strictEqual(types.filter(t => t === 'type').length, 3);
91
+ });
92
+
93
+ test('PHP-Script: C-style comments are highlighted', async () => {
94
+ const syntax = new Syntax();
95
+ registerPhpScript(syntax);
96
+ const language = await syntax.getLanguage('php-script');
97
+
98
+ const matches = await language.getMatches(syntax, '/* block comment */');
99
+ const types = matches.map(m => m.expression.type);
100
+
101
+ strictEqual(types.filter(t => t === 'comment').length, 1);
102
+ });
103
+
104
+ test('PHP-Script: C++-style comments are highlighted', async () => {
105
+ const syntax = new Syntax();
106
+ registerPhpScript(syntax);
107
+ const language = await syntax.getLanguage('php-script');
108
+
109
+ const matches = await language.getMatches(syntax, '// single line comment');
110
+ const types = matches.map(m => m.expression.type);
111
+
112
+ strictEqual(types.filter(t => t === 'comment').length, 1);
113
+ });
114
+
115
+ test('PHP-Script: Perl-style comments are highlighted', async () => {
116
+ const syntax = new Syntax();
117
+ registerPhpScript(syntax);
118
+ const language = await syntax.getLanguage('php-script');
119
+
120
+ const matches = await language.getMatches(syntax, '# perl style comment');
121
+ const types = matches.map(m => m.expression.type);
122
+
123
+ strictEqual(types.filter(t => t === 'comment').length, 1);
124
+ });
125
+
126
+ test('PHP-Script: single-quoted strings are highlighted', async () => {
127
+ const syntax = new Syntax();
128
+ registerPhpScript(syntax);
129
+ const language = await syntax.getLanguage('php-script');
130
+
131
+ const matches = await language.getMatches(syntax, "'hello world'");
132
+ const types = matches.map(m => m.expression.type);
133
+
134
+ strictEqual(types.filter(t => t === 'string').length, 1);
135
+ });
136
+
137
+ test('PHP-Script: double-quoted strings are highlighted', async () => {
138
+ const syntax = new Syntax();
139
+ registerPhpScript(syntax);
140
+ const language = await syntax.getLanguage('php-script');
141
+
142
+ const matches = await language.getMatches(syntax, '"hello world"');
143
+ const types = matches.map(m => m.expression.type);
144
+
145
+ strictEqual(types.filter(t => t === 'string').length, 1);
146
+ });
147
+
148
+ test('PHP-Script: decimal numbers are highlighted', async () => {
149
+ const syntax = new Syntax();
150
+ registerPhpScript(syntax);
151
+ const language = await syntax.getLanguage('php-script');
152
+
153
+ const matches = await language.getMatches(syntax, '42 3.14 -10');
154
+ const types = matches.map(m => m.expression.type);
155
+
156
+ strictEqual(types.filter(t => t === 'constant').length >= 3, true);
157
+ });
158
+
159
+ test('PHP-Script: hex numbers are highlighted', async () => {
160
+ const syntax = new Syntax();
161
+ registerPhpScript(syntax);
162
+ const language = await syntax.getLanguage('php-script');
163
+
164
+ const matches = await language.getMatches(syntax, '0xFF 0x1A2B');
165
+ const types = matches.map(m => m.expression.type);
166
+
167
+ strictEqual(types.filter(t => t === 'constant').length >= 2, true);
168
+ });
169
+
170
+ test('PHP-Script: complete function definition', async () => {
171
+ const syntax = new Syntax();
172
+ registerPhpScript(syntax);
173
+ const language = await syntax.getLanguage('php-script');
174
+
175
+ const code = 'function hello($name) { return "Hello " . $name; }';
176
+ const matches = await language.getMatches(syntax, code);
177
+ const types = matches.map(m => m.expression.type);
178
+
179
+ strictEqual(types.includes('keyword'), true); // function
180
+ strictEqual(types.includes('function'), true); // hello(
181
+ strictEqual(types.includes('variable'), true); // $name
182
+ strictEqual(types.includes('string'), true); // "Hello "
183
+ });
184
+
185
+ test('PHP-Script: class definition', async () => {
186
+ const syntax = new Syntax();
187
+ registerPhpScript(syntax);
188
+ const language = await syntax.getLanguage('php-script');
189
+
190
+ const code = 'class Person { public $name; private $age; }';
191
+ const matches = await language.getMatches(syntax, code);
192
+ const types = matches.map(m => m.expression.type);
193
+
194
+ strictEqual(types.includes('keyword'), true); // class
195
+ strictEqual(types.includes('access'), true); // public, private
196
+ strictEqual(types.includes('variable'), true); // $name, $age
197
+ });
@@ -0,0 +1,92 @@
1
+ import {strictEqual} from 'assert';
2
+ import {test} from 'node:test';
3
+
4
+ import Syntax from '../../../Syntax.js';
5
+ import registerPhp from '../../../Syntax/Language/php.js';
6
+
7
+ test('PHP: opening and closing tags are highlighted', async () => {
8
+ const syntax = new Syntax();
9
+ registerPhp(syntax);
10
+ const language = await syntax.getLanguage('php');
11
+
12
+ const code = '<?php echo "hello"; ?>';
13
+ const matches = await language.getMatches(syntax, code);
14
+ const types = matches.map(m => m.expression.type);
15
+
16
+ strictEqual(types.filter(t => t === 'keyword').length >= 2, true); // <?php and ?>
17
+ });
18
+
19
+ test('PHP: short opening tag', async () => {
20
+ const syntax = new Syntax();
21
+ registerPhp(syntax);
22
+ const language = await syntax.getLanguage('php');
23
+
24
+ const code = '<? echo "hello"; ?>';
25
+ const matches = await language.getMatches(syntax, code);
26
+ const types = matches.map(m => m.expression.type);
27
+
28
+ strictEqual(types.filter(t => t === 'keyword').length >= 2, true); // <? and ?>
29
+ });
30
+
31
+ test('PHP: embedded PHP in HTML', async () => {
32
+ const syntax = new Syntax();
33
+ registerPhp(syntax);
34
+ const language = await syntax.getLanguage('php');
35
+
36
+ const code = '<html><?php echo $title; ?></html>';
37
+ const matches = await language.getMatches(syntax, code);
38
+ const types = matches.map(m => m.expression.type);
39
+
40
+ strictEqual(types.includes('keyword'), true); // PHP tags
41
+ });
42
+
43
+ test('PHP: multiple PHP blocks', async () => {
44
+ const syntax = new Syntax();
45
+ registerPhp(syntax);
46
+ const language = await syntax.getLanguage('php');
47
+
48
+ const code = '<?php $a = 1; ?> text <?php $b = 2; ?>';
49
+ const matches = await language.getMatches(syntax, code);
50
+ const types = matches.map(m => m.expression.type);
51
+
52
+ strictEqual(types.filter(t => t === 'keyword').length >= 4, true); // Two pairs of tags
53
+ });
54
+
55
+ test('PHP: multiline PHP block', async () => {
56
+ const syntax = new Syntax();
57
+ registerPhp(syntax);
58
+ const language = await syntax.getLanguage('php');
59
+
60
+ const code = `<?php
61
+ function hello() {
62
+ echo "Hello";
63
+ }
64
+ ?>`;
65
+ const matches = await language.getMatches(syntax, code);
66
+ const types = matches.map(m => m.expression.type);
67
+
68
+ strictEqual(types.includes('keyword'), true); // PHP tags
69
+ });
70
+
71
+ test('PHP: PHP with comments', async () => {
72
+ const syntax = new Syntax();
73
+ registerPhp(syntax);
74
+ const language = await syntax.getLanguage('php');
75
+
76
+ const code = '<?php // comment\necho "test"; ?>';
77
+ const matches = await language.getMatches(syntax, code);
78
+
79
+ strictEqual(matches.length > 0, true);
80
+ });
81
+
82
+ test('PHP: empty PHP block', async () => {
83
+ const syntax = new Syntax();
84
+ registerPhp(syntax);
85
+ const language = await syntax.getLanguage('php');
86
+
87
+ const code = '<?php ?>';
88
+ const matches = await language.getMatches(syntax, code);
89
+ const types = matches.map(m => m.expression.type);
90
+
91
+ strictEqual(types.filter(t => t === 'keyword').length >= 2, true);
92
+ });