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.
- checksums.yaml +7 -0
- data/bin/presently +13 -0
- data/lib/presently/application.rb +104 -0
- data/lib/presently/clock.rb +77 -0
- data/lib/presently/display_view.rb +73 -0
- data/lib/presently/environment/application.rb +62 -0
- data/lib/presently/page.rb +38 -0
- data/lib/presently/page.xrb +31 -0
- data/lib/presently/presentation.rb +72 -0
- data/lib/presently/presentation_controller.rb +181 -0
- data/lib/presently/presenter_view.rb +264 -0
- data/lib/presently/slide.rb +148 -0
- data/lib/presently/slide_view.rb +92 -0
- data/lib/presently/state.rb +66 -0
- data/lib/presently/version.rb +9 -0
- data/lib/presently.rb +9 -0
- data/license.md +21 -0
- data/public/_components/@socketry/syntax/Syntax/CodeElement.js +337 -0
- data/public/_components/@socketry/syntax/Syntax/Errors.js +52 -0
- data/public/_components/@socketry/syntax/Syntax/Language/apache.js +49 -0
- data/public/_components/@socketry/syntax/Syntax/Language/applescript.js +157 -0
- data/public/_components/@socketry/syntax/Syntax/Language/assembly.js +42 -0
- data/public/_components/@socketry/syntax/Syntax/Language/bash-script.js +108 -0
- data/public/_components/@socketry/syntax/Syntax/Language/bash.js +32 -0
- data/public/_components/@socketry/syntax/Syntax/Language/basic.js +232 -0
- data/public/_components/@socketry/syntax/Syntax/Language/c++.js +1 -0
- data/public/_components/@socketry/syntax/Syntax/Language/c.js +1 -0
- data/public/_components/@socketry/syntax/Syntax/Language/clang.js +201 -0
- data/public/_components/@socketry/syntax/Syntax/Language/cpp.js +1 -0
- data/public/_components/@socketry/syntax/Syntax/Language/csharp.js +166 -0
- data/public/_components/@socketry/syntax/Syntax/Language/css.js +244 -0
- data/public/_components/@socketry/syntax/Syntax/Language/diff.js +24 -0
- data/public/_components/@socketry/syntax/Syntax/Language/go.js +135 -0
- data/public/_components/@socketry/syntax/Syntax/Language/haskell.js +110 -0
- data/public/_components/@socketry/syntax/Syntax/Language/html.js +69 -0
- data/public/_components/@socketry/syntax/Syntax/Language/io.js +68 -0
- data/public/_components/@socketry/syntax/Syntax/Language/java.js +134 -0
- data/public/_components/@socketry/syntax/Syntax/Language/javascript.js +89 -0
- data/public/_components/@socketry/syntax/Syntax/Language/json.js +36 -0
- data/public/_components/@socketry/syntax/Syntax/Language/lisp.js +38 -0
- data/public/_components/@socketry/syntax/Syntax/Language/lua.js +87 -0
- data/public/_components/@socketry/syntax/Syntax/Language/markdown.js +112 -0
- data/public/_components/@socketry/syntax/Syntax/Language/nginx.js +37 -0
- data/public/_components/@socketry/syntax/Syntax/Language/objective-c.js +1 -0
- data/public/_components/@socketry/syntax/Syntax/Language/ocaml.js +225 -0
- data/public/_components/@socketry/syntax/Syntax/Language/pascal.js +166 -0
- data/public/_components/@socketry/syntax/Syntax/Language/patch.js +2 -0
- data/public/_components/@socketry/syntax/Syntax/Language/perl5.js +317 -0
- data/public/_components/@socketry/syntax/Syntax/Language/php-script.js +112 -0
- data/public/_components/@socketry/syntax/Syntax/Language/php.js +18 -0
- data/public/_components/@socketry/syntax/Syntax/Language/plain.js +20 -0
- data/public/_components/@socketry/syntax/Syntax/Language/protobuf.js +77 -0
- data/public/_components/@socketry/syntax/Syntax/Language/python.js +208 -0
- data/public/_components/@socketry/syntax/Syntax/Language/ruby.js +124 -0
- data/public/_components/@socketry/syntax/Syntax/Language/scala.js +81 -0
- data/public/_components/@socketry/syntax/Syntax/Language/smalltalk.js +30 -0
- data/public/_components/@socketry/syntax/Syntax/Language/sql.js +865 -0
- data/public/_components/@socketry/syntax/Syntax/Language/super-collider.js +70 -0
- data/public/_components/@socketry/syntax/Syntax/Language/swift.js +176 -0
- data/public/_components/@socketry/syntax/Syntax/Language/xml.js +76 -0
- data/public/_components/@socketry/syntax/Syntax/Language/xrb.js +33 -0
- data/public/_components/@socketry/syntax/Syntax/Language/yaml.js +29 -0
- data/public/_components/@socketry/syntax/Syntax/Language.js +276 -0
- data/public/_components/@socketry/syntax/Syntax/Loader.js +78 -0
- data/public/_components/@socketry/syntax/Syntax/Match.js +546 -0
- data/public/_components/@socketry/syntax/Syntax/Rule.js +306 -0
- data/public/_components/@socketry/syntax/Syntax.js +356 -0
- data/public/_components/@socketry/syntax/bin/syntax-ast.js +42 -0
- data/public/_components/@socketry/syntax/examples/_template.html +53 -0
- data/public/_components/@socketry/syntax/examples/apache.html +72 -0
- data/public/_components/@socketry/syntax/examples/applescript.html +72 -0
- data/public/_components/@socketry/syntax/examples/assembly.html +74 -0
- data/public/_components/@socketry/syntax/examples/bash.html +90 -0
- data/public/_components/@socketry/syntax/examples/basic.html +87 -0
- data/public/_components/@socketry/syntax/examples/c.html +141 -0
- data/public/_components/@socketry/syntax/examples/clang.html +202 -0
- data/public/_components/@socketry/syntax/examples/csharp.html +110 -0
- data/public/_components/@socketry/syntax/examples/css-colors.html +179 -0
- data/public/_components/@socketry/syntax/examples/custom-theme.html +155 -0
- data/public/_components/@socketry/syntax/examples/diff.html +142 -0
- data/public/_components/@socketry/syntax/examples/examples.css +216 -0
- data/public/_components/@socketry/syntax/examples/go.html +413 -0
- data/public/_components/@socketry/syntax/examples/haskell.html +373 -0
- data/public/_components/@socketry/syntax/examples/html.html +316 -0
- data/public/_components/@socketry/syntax/examples/index.html +97 -0
- data/public/_components/@socketry/syntax/examples/io.html +552 -0
- data/public/_components/@socketry/syntax/examples/java.html +786 -0
- data/public/_components/@socketry/syntax/examples/javascript.html +199 -0
- data/public/_components/@socketry/syntax/examples/json.html +150 -0
- data/public/_components/@socketry/syntax/examples/lisp.html +476 -0
- data/public/_components/@socketry/syntax/examples/lua.html +737 -0
- data/public/_components/@socketry/syntax/examples/markdown.html +121 -0
- data/public/_components/@socketry/syntax/examples/mixed.html +306 -0
- data/public/_components/@socketry/syntax/examples/nginx.html +554 -0
- data/public/_components/@socketry/syntax/examples/ocaml.html +596 -0
- data/public/_components/@socketry/syntax/examples/pascal.html +762 -0
- data/public/_components/@socketry/syntax/examples/perl5.html +488 -0
- data/public/_components/@socketry/syntax/examples/php-script.html +142 -0
- data/public/_components/@socketry/syntax/examples/php.html +95 -0
- data/public/_components/@socketry/syntax/examples/plain.html +222 -0
- data/public/_components/@socketry/syntax/examples/protobuf.html +405 -0
- data/public/_components/@socketry/syntax/examples/python.html +82 -0
- data/public/_components/@socketry/syntax/examples/readme.md +79 -0
- data/public/_components/@socketry/syntax/examples/ruby.html +58 -0
- data/public/_components/@socketry/syntax/examples/scala.html +41 -0
- data/public/_components/@socketry/syntax/examples/smalltalk.html +436 -0
- data/public/_components/@socketry/syntax/examples/sql.html +373 -0
- data/public/_components/@socketry/syntax/examples/super-collider.html +55 -0
- data/public/_components/@socketry/syntax/examples/swift.html +176 -0
- data/public/_components/@socketry/syntax/examples/wrap-demo.html +103 -0
- data/public/_components/@socketry/syntax/examples/xml.html +112 -0
- data/public/_components/@socketry/syntax/examples/xrb.html +37 -0
- data/public/_components/@socketry/syntax/examples/yaml.html +72 -0
- data/public/_components/@socketry/syntax/license.md +21 -0
- data/public/_components/@socketry/syntax/package-lock.json +834 -0
- data/public/_components/@socketry/syntax/package.json +43 -0
- data/public/_components/@socketry/syntax/readme.md +162 -0
- data/public/_components/@socketry/syntax/test/Syntax/CodeElement.js +306 -0
- data/public/_components/@socketry/syntax/test/Syntax/ErrorHandling.js +85 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/apache.js +153 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/applescript.js +198 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/assembly.js +209 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/bash-script.js +225 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/bash.js +162 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/basic.js +265 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/clang.js +390 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/csharp.js +436 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/css.js +431 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/diff.js +206 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/go.js +386 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/haskell.js +454 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/html.js +111 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/io.js +229 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/java.js +362 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/javascript.js +101 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/json.js +101 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/lisp.js +224 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/lua.js +307 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/markdown.js +163 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/nginx.js +267 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/ocaml.js +299 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/pascal.js +311 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/perl5.js +333 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/php-script.js +197 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/php.js +92 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/plain.js +327 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/protobuf.js +294 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/python.js +213 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/ruby.js +70 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/scala.js +75 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/smalltalk.js +223 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/sql.js +281 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/super-collider.js +66 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/swift.js +71 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/xml.js +170 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/xrb.js +57 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language/yaml.js +123 -0
- data/public/_components/@socketry/syntax/test/Syntax/Language.js +62 -0
- data/public/_components/@socketry/syntax/test/Syntax/Match.js +40 -0
- data/public/_components/@socketry/syntax/test/Syntax/Rule.js +251 -0
- data/public/_components/@socketry/syntax/test/Syntax.js +38 -0
- data/public/_components/@socketry/syntax/test/helpers/ast-matcher.js +90 -0
- data/public/_components/@socketry/syntax/themes/base/apache.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/applescript.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/assembly.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/bash.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/basic.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/c.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/clang.css +0 -0
- data/public/_components/@socketry/syntax/themes/base/csharp.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/css.css +22 -0
- data/public/_components/@socketry/syntax/themes/base/diff.css +48 -0
- data/public/_components/@socketry/syntax/themes/base/go.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/haskell.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/html.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/io.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/java.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/javascript.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/json.css +41 -0
- data/public/_components/@socketry/syntax/themes/base/lisp.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/lua.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/markdown.css +16 -0
- data/public/_components/@socketry/syntax/themes/base/nginx.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/ocaml.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/pascal.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/perl5.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/php-script.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/php.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/plain.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/protobuf.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/python.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/ruby.css +23 -0
- data/public/_components/@socketry/syntax/themes/base/scala.css +3 -0
- data/public/_components/@socketry/syntax/themes/base/smalltalk.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/sql.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/super-collider.css +33 -0
- data/public/_components/@socketry/syntax/themes/base/swift.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/syntax.css +63 -0
- data/public/_components/@socketry/syntax/themes/base/xml.css +1 -0
- data/public/_components/@socketry/syntax/themes/base/xrb.css +29 -0
- data/public/_components/@socketry/syntax/themes/base/yaml.css +1 -0
- data/public/_components/@socketry/syntax/themes/theming.md +233 -0
- data/public/_components/@socketry/syntax/update-examples.js +135 -0
- data/public/_static/index.css +593 -0
- data/public/application.js +147 -0
- data/readme.md +69 -0
- data/releases.md +3 -0
- data/templates/code.xrb +12 -0
- data/templates/default.xrb +5 -0
- data/templates/image.xrb +8 -0
- data/templates/section.xrb +5 -0
- data/templates/title.xrb +8 -0
- data/templates/translation.xrb +8 -0
- data/templates/two_column.xrb +8 -0
- metadata +280 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for SQL 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('SQL language can be registered', async () => {
|
|
19
|
+
const language = await syntax.getResource('sql');
|
|
20
|
+
assert.ok(language);
|
|
21
|
+
assert.equal(language.name, 'sql');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('SQL can match SELECT keyword', async () => {
|
|
25
|
+
const language = await syntax.getResource('sql');
|
|
26
|
+
const matches = await language.getMatches(syntax, 'SELECT * FROM users');
|
|
27
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
28
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'SELECT'));
|
|
29
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'FROM'));
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('SQL can match INSERT keyword', async () => {
|
|
33
|
+
const language = await syntax.getResource('sql');
|
|
34
|
+
const matches = await language.getMatches(
|
|
35
|
+
syntax,
|
|
36
|
+
'INSERT INTO users VALUES (1, 2)'
|
|
37
|
+
);
|
|
38
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
39
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'INSERT'));
|
|
40
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'INTO'));
|
|
41
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'VALUES'));
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('SQL can match UPDATE keyword', async () => {
|
|
45
|
+
const language = await syntax.getResource('sql');
|
|
46
|
+
const matches = await language.getMatches(
|
|
47
|
+
syntax,
|
|
48
|
+
'UPDATE users SET name = "John"'
|
|
49
|
+
);
|
|
50
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
51
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'UPDATE'));
|
|
52
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'SET'));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('SQL can match DELETE keyword', async () => {
|
|
56
|
+
const language = await syntax.getResource('sql');
|
|
57
|
+
const matches = await language.getMatches(
|
|
58
|
+
syntax,
|
|
59
|
+
'DELETE FROM users WHERE id = 1'
|
|
60
|
+
);
|
|
61
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
62
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'DELETE'));
|
|
63
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'WHERE'));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('SQL can match CREATE TABLE', async () => {
|
|
67
|
+
const language = await syntax.getResource('sql');
|
|
68
|
+
const matches = await language.getMatches(
|
|
69
|
+
syntax,
|
|
70
|
+
'CREATE TABLE users (id INT PRIMARY KEY)'
|
|
71
|
+
);
|
|
72
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
73
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'CREATE'));
|
|
74
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'TABLE'));
|
|
75
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'PRIMARY'));
|
|
76
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'KEY'));
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('SQL can match JOIN keywords', async () => {
|
|
80
|
+
const language = await syntax.getResource('sql');
|
|
81
|
+
const matches = await language.getMatches(
|
|
82
|
+
syntax,
|
|
83
|
+
'SELECT * FROM a LEFT JOIN b ON a.id = b.id'
|
|
84
|
+
);
|
|
85
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
86
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'LEFT'));
|
|
87
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'JOIN'));
|
|
88
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'ON'));
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('SQL can match operators', async () => {
|
|
92
|
+
const language = await syntax.getResource('sql');
|
|
93
|
+
const matches = await language.getMatches(
|
|
94
|
+
syntax,
|
|
95
|
+
'WHERE a = 1 AND b != 2 OR c > 3'
|
|
96
|
+
);
|
|
97
|
+
const operators = matches.filter(m => m.type === 'operator');
|
|
98
|
+
assert.ok(operators.some(m => m.value === '='));
|
|
99
|
+
assert.ok(operators.some(m => m.value === '!='));
|
|
100
|
+
assert.ok(operators.some(m => m.value === '>'));
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('SQL can match comparison operators', async () => {
|
|
104
|
+
const language = await syntax.getResource('sql');
|
|
105
|
+
const matches = await language.getMatches(
|
|
106
|
+
syntax,
|
|
107
|
+
'WHERE x < 5 AND y >= 10 AND z <= 20'
|
|
108
|
+
);
|
|
109
|
+
const operators = matches.filter(m => m.type === 'operator');
|
|
110
|
+
assert.ok(operators.some(m => m.value === '<'));
|
|
111
|
+
assert.ok(operators.some(m => m.value === '>='));
|
|
112
|
+
assert.ok(operators.some(m => m.value === '<='));
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('SQL can match arithmetic operators', async () => {
|
|
116
|
+
const language = await syntax.getResource('sql');
|
|
117
|
+
const matches = await language.getMatches(
|
|
118
|
+
syntax,
|
|
119
|
+
'SELECT a + b - c * d / e % f'
|
|
120
|
+
);
|
|
121
|
+
const operators = matches.filter(m => m.type === 'operator');
|
|
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('SQL can match single-line comments', async () => {
|
|
130
|
+
const language = await syntax.getResource('sql');
|
|
131
|
+
const matches = await language.getMatches(
|
|
132
|
+
syntax,
|
|
133
|
+
'-- This is a comment\nSELECT * FROM users'
|
|
134
|
+
);
|
|
135
|
+
const comments = matches.filter(m => m.type === 'comment');
|
|
136
|
+
assert.ok(comments.some(m => m.value === '-- This is a comment'));
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('SQL can match single-quoted strings', async () => {
|
|
140
|
+
const language = await syntax.getResource('sql');
|
|
141
|
+
const matches = await language.getMatches(
|
|
142
|
+
syntax,
|
|
143
|
+
"SELECT * FROM users WHERE name = 'John Doe'"
|
|
144
|
+
);
|
|
145
|
+
const strings = matches.filter(m => m.type === 'string');
|
|
146
|
+
assert.ok(strings.some(m => m.value === "'John Doe'"));
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test('SQL can match double-quoted strings', async () => {
|
|
150
|
+
const language = await syntax.getResource('sql');
|
|
151
|
+
const matches = await language.getMatches(
|
|
152
|
+
syntax,
|
|
153
|
+
'SELECT * FROM users WHERE name = "Jane Smith"'
|
|
154
|
+
);
|
|
155
|
+
const strings = matches.filter(m => m.type === 'string');
|
|
156
|
+
assert.ok(strings.some(m => m.value === '"Jane Smith"'));
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('SQL can match decimal numbers', async () => {
|
|
160
|
+
const language = await syntax.getResource('sql');
|
|
161
|
+
const matches = await language.getMatches(
|
|
162
|
+
syntax,
|
|
163
|
+
'SELECT * FROM items WHERE price = 19.99'
|
|
164
|
+
);
|
|
165
|
+
const numbers = matches.filter(m => m.type === 'constant');
|
|
166
|
+
assert.ok(numbers.some(m => m.value === '19.99'));
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test('SQL can match hexadecimal numbers', async () => {
|
|
170
|
+
const language = await syntax.getResource('sql');
|
|
171
|
+
const matches = await language.getMatches(syntax, 'SELECT 0xFF, 0x1A2B');
|
|
172
|
+
const numbers = matches.filter(m => m.type === 'constant');
|
|
173
|
+
assert.ok(numbers.some(m => m.value === '0xFF'));
|
|
174
|
+
assert.ok(numbers.some(m => m.value === '0x1A2B'));
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test('SQL keywords are case-insensitive', async () => {
|
|
178
|
+
const language = await syntax.getResource('sql');
|
|
179
|
+
const matches = await language.getMatches(
|
|
180
|
+
syntax,
|
|
181
|
+
'select * from users where id = 1'
|
|
182
|
+
);
|
|
183
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
184
|
+
assert.ok(keywords.some(m => m.value.toLowerCase() === 'select'));
|
|
185
|
+
assert.ok(keywords.some(m => m.value.toLowerCase() === 'from'));
|
|
186
|
+
assert.ok(keywords.some(m => m.value.toLowerCase() === 'where'));
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test('SQL can match data types', async () => {
|
|
190
|
+
const language = await syntax.getResource('sql');
|
|
191
|
+
const matches = await language.getMatches(
|
|
192
|
+
syntax,
|
|
193
|
+
'CREATE TABLE t (id INT, name VARCHAR, created TIMESTAMP)'
|
|
194
|
+
);
|
|
195
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
196
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'INT'));
|
|
197
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'VARCHAR'));
|
|
198
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'TIMESTAMP'));
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('SQL can match aggregate functions', async () => {
|
|
202
|
+
const language = await syntax.getResource('sql');
|
|
203
|
+
const matches = await language.getMatches(
|
|
204
|
+
syntax,
|
|
205
|
+
'SELECT COUNT(*), SUM(price), AVG(rating) FROM items'
|
|
206
|
+
);
|
|
207
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
208
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'COUNT'));
|
|
209
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'SUM'));
|
|
210
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'AVG'));
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test('SQL can match GROUP BY and HAVING', async () => {
|
|
214
|
+
const language = await syntax.getResource('sql');
|
|
215
|
+
const matches = await language.getMatches(
|
|
216
|
+
syntax,
|
|
217
|
+
'SELECT category FROM items GROUP BY category HAVING COUNT(*) > 5'
|
|
218
|
+
);
|
|
219
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
220
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'GROUP'));
|
|
221
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'BY'));
|
|
222
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'HAVING'));
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test('SQL can match ORDER BY', async () => {
|
|
226
|
+
const language = await syntax.getResource('sql');
|
|
227
|
+
const matches = await language.getMatches(
|
|
228
|
+
syntax,
|
|
229
|
+
'SELECT * FROM users ORDER BY name ASC, age DESC'
|
|
230
|
+
);
|
|
231
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
232
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'ORDER'));
|
|
233
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'BY'));
|
|
234
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'ASC'));
|
|
235
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'DESC'));
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test('SQL can match DISTINCT keyword', async () => {
|
|
239
|
+
const language = await syntax.getResource('sql');
|
|
240
|
+
const matches = await language.getMatches(
|
|
241
|
+
syntax,
|
|
242
|
+
'SELECT DISTINCT category FROM items'
|
|
243
|
+
);
|
|
244
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
245
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'DISTINCT'));
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test('SQL can match LIMIT and OFFSET', async () => {
|
|
249
|
+
const language = await syntax.getResource('sql');
|
|
250
|
+
const matches = await language.getMatches(
|
|
251
|
+
syntax,
|
|
252
|
+
'SELECT * FROM users LIMIT 10 OFFSET 20'
|
|
253
|
+
);
|
|
254
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
255
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'LIMIT'));
|
|
256
|
+
assert.ok(keywords.some(m => m.value.toUpperCase() === 'OFFSET'));
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('SQL can process complete query', async () => {
|
|
260
|
+
const language = await syntax.getResource('sql');
|
|
261
|
+
const code = `-- Get active users with their order counts
|
|
262
|
+
SELECT
|
|
263
|
+
u.id,
|
|
264
|
+
u.name,
|
|
265
|
+
COUNT(o.id) AS order_count
|
|
266
|
+
FROM users u
|
|
267
|
+
LEFT JOIN orders o ON u.id = o.user_id
|
|
268
|
+
WHERE u.active = 1
|
|
269
|
+
GROUP BY u.id, u.name
|
|
270
|
+
HAVING COUNT(o.id) > 0
|
|
271
|
+
ORDER BY order_count DESC
|
|
272
|
+
LIMIT 100;`;
|
|
273
|
+
const matches = await language.getMatches(syntax, code);
|
|
274
|
+
assert.ok(matches.length > 0);
|
|
275
|
+
|
|
276
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
277
|
+
assert.ok(keywords.length > 0);
|
|
278
|
+
|
|
279
|
+
const comments = matches.filter(m => m.type === 'comment');
|
|
280
|
+
assert.ok(comments.length > 0);
|
|
281
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import Syntax from '../../../Syntax.js';
|
|
2
|
+
import registerSuperCollider from '../../../Syntax/Language/super-collider.js';
|
|
3
|
+
import {strictEqual} from 'node:assert';
|
|
4
|
+
import test from 'node:test';
|
|
5
|
+
|
|
6
|
+
async function getTypesFor(code) {
|
|
7
|
+
const syntax = new Syntax();
|
|
8
|
+
registerSuperCollider(syntax);
|
|
9
|
+
const language = await syntax.getLanguage('super-collider');
|
|
10
|
+
const matches = await language.getMatches(syntax, code);
|
|
11
|
+
return matches.map(m => m.expression.type);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
test('SuperCollider: keywords', async () => {
|
|
15
|
+
const types = await getTypesFor('var x; classvar y; const z; arg a;');
|
|
16
|
+
strictEqual(types.includes('keyword'), true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('SuperCollider: operators', async () => {
|
|
20
|
+
const types = await getTypesFor(
|
|
21
|
+
'a+b - c * d / e % f < g > h = i & j | k ~ l ! m : n @ o'
|
|
22
|
+
);
|
|
23
|
+
strictEqual(types.includes('operator'), true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('SuperCollider: values/constants', async () => {
|
|
27
|
+
const types = await getTypesFor(
|
|
28
|
+
'thisFunction thisMethod thisProcess thisThread this super true false nil inf'
|
|
29
|
+
);
|
|
30
|
+
strictEqual(types.filter(t => t === 'constant').length >= 3, true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('SuperCollider: camel case type', async () => {
|
|
34
|
+
const types = await getTypesFor('SynthDef EnvGen Pan2 SinOsc');
|
|
35
|
+
strictEqual(types.includes('type'), true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('SuperCollider: single character constants', async () => {
|
|
39
|
+
const types = await getTypesFor('$a $\n');
|
|
40
|
+
strictEqual(types.includes('constant'), true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('SuperCollider: symbols', async () => {
|
|
44
|
+
const types1 = await getTypesFor('\\freq \\amp');
|
|
45
|
+
strictEqual(types1.includes('symbol'), true);
|
|
46
|
+
const types2 = await getTypesFor("'foo' 'bar'");
|
|
47
|
+
strictEqual(types2.includes('symbol'), true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('SuperCollider: comments and links', async () => {
|
|
51
|
+
const types = await getTypesFor('/* comment */ // line http://example.com');
|
|
52
|
+
strictEqual(types.includes('comment'), true);
|
|
53
|
+
strictEqual(types.includes('href'), true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('SuperCollider: strings and numbers', async () => {
|
|
57
|
+
const types = await getTypesFor('\'a\' "b" 0xFF 123 3.14');
|
|
58
|
+
// 'a' is a Symbol (handled in the symbols test). Only \"b\" is a String.
|
|
59
|
+
strictEqual(types.filter(t => t === 'string').length >= 1, true);
|
|
60
|
+
strictEqual(types.filter(t => t === 'constant').length >= 2, true);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('SuperCollider: method calls and functions', async () => {
|
|
64
|
+
const types = await getTypesFor('object.method(); func()');
|
|
65
|
+
strictEqual(types.includes('function'), true);
|
|
66
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Swift 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('Swift language can be registered', async () => {
|
|
19
|
+
const language = await syntax.getResource('swift');
|
|
20
|
+
assert.ok(language);
|
|
21
|
+
assert.equal(language.name, 'swift');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('Swift can match keywords', async () => {
|
|
25
|
+
const language = await syntax.getResource('swift');
|
|
26
|
+
const matches = await language.getMatches(
|
|
27
|
+
syntax,
|
|
28
|
+
'class MyClass func test() { if true { } }'
|
|
29
|
+
);
|
|
30
|
+
const keywords = matches.filter(m => m.type === 'keyword');
|
|
31
|
+
assert.ok(keywords.some(m => m.value === 'class'));
|
|
32
|
+
assert.ok(keywords.some(m => m.value === 'func'));
|
|
33
|
+
assert.ok(keywords.some(m => m.value === 'if'));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('Swift can match access modifiers', async () => {
|
|
37
|
+
const language = await syntax.getResource('swift');
|
|
38
|
+
const matches = await language.getMatches(
|
|
39
|
+
syntax,
|
|
40
|
+
'public class A private var b'
|
|
41
|
+
);
|
|
42
|
+
const access = matches.filter(m => m.type === 'access');
|
|
43
|
+
assert.ok(access.some(m => m.value === 'public'));
|
|
44
|
+
assert.ok(access.some(m => m.value === 'private'));
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('Swift can match constants', async () => {
|
|
48
|
+
const language = await syntax.getResource('swift');
|
|
49
|
+
const matches = await language.getMatches(
|
|
50
|
+
syntax,
|
|
51
|
+
'let a = true, b = false, c = nil'
|
|
52
|
+
);
|
|
53
|
+
const constants = matches.filter(m => m.type === 'constant');
|
|
54
|
+
assert.ok(constants.some(m => m.value === 'true'));
|
|
55
|
+
assert.ok(constants.some(m => m.value === 'false'));
|
|
56
|
+
assert.ok(constants.some(m => m.value === 'nil'));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('Swift can match backtick identifiers', async () => {
|
|
60
|
+
const language = await syntax.getResource('swift');
|
|
61
|
+
const matches = await language.getMatches(syntax, 'let `class` = "test"');
|
|
62
|
+
const identifiers = matches.filter(m => m.type === 'identifier');
|
|
63
|
+
assert.ok(identifiers.some(m => m.value === '`class`'));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('Swift can match arrow operator', async () => {
|
|
67
|
+
const language = await syntax.getResource('swift');
|
|
68
|
+
const matches = await language.getMatches(syntax, 'func foo() -> Int { }');
|
|
69
|
+
const operators = matches.filter(m => m.type === 'operator');
|
|
70
|
+
assert.ok(operators.some(m => m.value === '->'));
|
|
71
|
+
});
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for XML 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('XML language can be registered', async () => {
|
|
19
|
+
const language = await syntax.getResource('xml');
|
|
20
|
+
assert.ok(language);
|
|
21
|
+
assert.equal(language.name, 'xml');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('xml-tag language can be registered', async () => {
|
|
25
|
+
const language = await syntax.getResource('xml-tag');
|
|
26
|
+
assert.ok(language);
|
|
27
|
+
assert.equal(language.name, 'xml-tag');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('XML can match opening tags', async () => {
|
|
31
|
+
const language = await syntax.getResource('xml');
|
|
32
|
+
const matches = await language.getMatches(syntax, '<root>');
|
|
33
|
+
assert.ok(matches.some(m => m.value === '<root>'));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('XML can match closing tags', async () => {
|
|
37
|
+
const language = await syntax.getResource('xml');
|
|
38
|
+
const matches = await language.getMatches(syntax, '</root>');
|
|
39
|
+
assert.ok(matches.some(m => m.value === '</root>'));
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('XML can match self-closing tags', async () => {
|
|
43
|
+
const language = await syntax.getResource('xml');
|
|
44
|
+
const matches = await language.getMatches(syntax, '<element/>');
|
|
45
|
+
assert.ok(matches.some(m => m.value === '<element/>'));
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('XML can match tags with namespace', async () => {
|
|
49
|
+
const language = await syntax.getResource('xml');
|
|
50
|
+
const matches = await language.getMatches(syntax, '<ns:element>');
|
|
51
|
+
assert.ok(matches.some(m => m.value === '<ns:element>'));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('XML can match tags with attributes', async () => {
|
|
55
|
+
const language = await syntax.getResource('xml');
|
|
56
|
+
const matches = await language.getMatches(syntax, '<element attr="value">');
|
|
57
|
+
assert.ok(matches.some(m => m.value === '<element attr="value">'));
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('XML can match entities', async () => {
|
|
61
|
+
const language = await syntax.getResource('xml');
|
|
62
|
+
const matches = await language.getMatches(syntax, ' < > &');
|
|
63
|
+
const entities = matches.filter(m => m.type === 'entity');
|
|
64
|
+
assert.ok(entities.some(m => m.value === ' '));
|
|
65
|
+
assert.ok(entities.some(m => m.value === '<'));
|
|
66
|
+
assert.ok(entities.some(m => m.value === '>'));
|
|
67
|
+
assert.ok(entities.some(m => m.value === '&'));
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('XML can match CDATA sections', async () => {
|
|
71
|
+
const language = await syntax.getResource('xml');
|
|
72
|
+
const matches = await language.getMatches(syntax, '<![CDATA[some data]]>');
|
|
73
|
+
const cdata = matches.filter(m => m.type === 'cdata');
|
|
74
|
+
assert.ok(cdata.length > 0);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('XML can match CDATA with special chars', async () => {
|
|
78
|
+
const language = await syntax.getResource('xml');
|
|
79
|
+
const matches = await language.getMatches(syntax, '<![CDATA[<>&"\']]>');
|
|
80
|
+
const cdata = matches.filter(m => m.type === 'cdata');
|
|
81
|
+
assert.ok(cdata.length > 0);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('XML can match comments', async () => {
|
|
85
|
+
const language = await syntax.getResource('xml');
|
|
86
|
+
const matches = await language.getMatches(syntax, '<!-- comment -->');
|
|
87
|
+
const comments = matches.filter(m => m.type === 'comment');
|
|
88
|
+
assert.ok(comments.length > 0);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('XML can match multi-line comments', async () => {
|
|
92
|
+
const language = await syntax.getResource('xml');
|
|
93
|
+
const matches = await language.getMatches(
|
|
94
|
+
syntax,
|
|
95
|
+
'<!-- multi\nline\ncomment -->'
|
|
96
|
+
);
|
|
97
|
+
const comments = matches.filter(m => m.type === 'comment');
|
|
98
|
+
assert.ok(comments.length > 0);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('XML can match percent escapes', async () => {
|
|
102
|
+
const language = await syntax.getResource('xml');
|
|
103
|
+
const matches = await language.getMatches(syntax, '%20%2F%3A');
|
|
104
|
+
const escapes = matches.filter(m => m.type === 'percent-escape');
|
|
105
|
+
assert.ok(escapes.some(m => m.value === '%20'));
|
|
106
|
+
assert.ok(escapes.some(m => m.value === '%2F'));
|
|
107
|
+
assert.ok(escapes.some(m => m.value === '%3A'));
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('XML can match URLs', async () => {
|
|
111
|
+
const language = await syntax.getResource('xml');
|
|
112
|
+
const matches = await language.getMatches(syntax, 'http://example.com/path');
|
|
113
|
+
const urls = matches.filter(m => m.type === 'href');
|
|
114
|
+
assert.ok(urls.some(m => m.value === 'http://example.com/path'));
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('xml-tag can match tag names', async () => {
|
|
118
|
+
const xmlTag = await syntax.getResource('xml-tag');
|
|
119
|
+
const matches = await xmlTag.getMatches(syntax, '<element>');
|
|
120
|
+
const tagNames = matches.filter(m => m.type === 'tag-name');
|
|
121
|
+
assert.ok(tagNames.some(m => m.value === 'element'));
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('xml-tag can match namespaces', async () => {
|
|
125
|
+
const xmlTag = await syntax.getResource('xml-tag');
|
|
126
|
+
const matches = await xmlTag.getMatches(syntax, '<ns:element>');
|
|
127
|
+
const namespaces = matches.filter(m => m.type === 'namespace');
|
|
128
|
+
assert.ok(namespaces.some(m => m.value === 'ns:'));
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('xml-tag can match attributes', async () => {
|
|
132
|
+
const xmlTag = await syntax.getResource('xml-tag');
|
|
133
|
+
const matches = await xmlTag.getMatches(syntax, '<element attr="value">');
|
|
134
|
+
const attributes = matches.filter(m => m.type === 'attribute');
|
|
135
|
+
assert.ok(attributes.some(m => m.value === 'attr'));
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('xml-tag can match attribute values', async () => {
|
|
139
|
+
const xmlTag = await syntax.getResource('xml-tag');
|
|
140
|
+
const matches = await xmlTag.getMatches(syntax, '<element attr="value">');
|
|
141
|
+
const strings = matches.filter(m => m.type === 'string');
|
|
142
|
+
assert.ok(strings.some(m => m.value === '"value"'));
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test('xml-tag can match single-quoted attributes', async () => {
|
|
146
|
+
const xmlTag = await syntax.getResource('xml-tag');
|
|
147
|
+
const matches = await xmlTag.getMatches(syntax, "<element attr='value'>");
|
|
148
|
+
const strings = matches.filter(m => m.type === 'string');
|
|
149
|
+
assert.ok(strings.some(m => m.value === "'value'"));
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test('xml-tag can match unquoted attributes', async () => {
|
|
153
|
+
const xmlTag = await syntax.getResource('xml-tag');
|
|
154
|
+
const matches = await xmlTag.getMatches(syntax, '<element attr=value>');
|
|
155
|
+
const strings = matches.filter(m => m.type === 'string');
|
|
156
|
+
assert.ok(strings.some(m => m.value === 'value'));
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('XML can process complete document', async () => {
|
|
160
|
+
const language = await syntax.getResource('xml');
|
|
161
|
+
const code = `<?xml version="1.0"?>
|
|
162
|
+
<root xmlns:ns="http://example.com">
|
|
163
|
+
<!-- Comment -->
|
|
164
|
+
<element attr="value">text & entity</element>
|
|
165
|
+
<ns:element/>
|
|
166
|
+
<![CDATA[<raw>data</raw>]]>
|
|
167
|
+
</root>`;
|
|
168
|
+
const matches = await language.getMatches(syntax, code);
|
|
169
|
+
assert.ok(matches.length > 0);
|
|
170
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import Syntax from '../../../Syntax.js';
|
|
2
|
+
import registerXRB from '../../../Syntax/Language/xrb.js';
|
|
3
|
+
import registerRuby from '../../../Syntax/Language/ruby.js';
|
|
4
|
+
import registerXML from '../../../Syntax/Language/xml.js';
|
|
5
|
+
import {strictEqual} from 'node:assert';
|
|
6
|
+
import test from 'node:test';
|
|
7
|
+
|
|
8
|
+
async function getMatches(code) {
|
|
9
|
+
const syntax = new Syntax();
|
|
10
|
+
registerRuby(syntax);
|
|
11
|
+
registerXML(syntax);
|
|
12
|
+
registerXRB(syntax);
|
|
13
|
+
const language = await syntax.getLanguage('xrb');
|
|
14
|
+
return await language.getMatches(syntax, code);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function typesFrom(matches) {
|
|
18
|
+
return matches.map(m => m.expression.type);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test('XRB: ruby processing instruction', async () => {
|
|
22
|
+
const matches = await getMatches('<?r puts "Hello" ?>');
|
|
23
|
+
const types = typesFrom(matches);
|
|
24
|
+
// Should include a keyword-class token for opening/closing and an embedded ruby subtree
|
|
25
|
+
strictEqual(
|
|
26
|
+
types.some(t => t.includes('keyword')),
|
|
27
|
+
true
|
|
28
|
+
);
|
|
29
|
+
strictEqual(
|
|
30
|
+
matches.some(m => m.expression && m.expression.language === 'ruby'),
|
|
31
|
+
true
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('XRB: interpolation #{...}', async () => {
|
|
36
|
+
const matches = await getMatches('Value: #{x + 1}');
|
|
37
|
+
const types = typesFrom(matches);
|
|
38
|
+
strictEqual(
|
|
39
|
+
types.some(t => t.includes('keyword')),
|
|
40
|
+
true
|
|
41
|
+
);
|
|
42
|
+
// Embedded ruby subtree should be present
|
|
43
|
+
strictEqual(
|
|
44
|
+
matches.some(m => m.expression && m.expression.language === 'ruby'),
|
|
45
|
+
true
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('XRB: xml context preserved', async () => {
|
|
50
|
+
const matches = await getMatches('<tag attr="v">#{1+2}</tag>');
|
|
51
|
+
const types = typesFrom(matches);
|
|
52
|
+
// Expect interpolation keyword to be present; XML tags are handled via subtree
|
|
53
|
+
strictEqual(
|
|
54
|
+
types.some(t => t.includes('keyword')),
|
|
55
|
+
true
|
|
56
|
+
);
|
|
57
|
+
});
|