ripple 0.2.121 → 0.2.125
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/compiler/index.js +1 -1
- package/src/compiler/phases/1-parse/index.js +1 -0
- package/src/compiler/phases/2-analyze/index.js +66 -32
- package/src/compiler/phases/3-transform/client/index.js +19 -0
- package/src/compiler/phases/3-transform/server/index.js +50 -37
- package/src/runtime/internal/client/composite.js +2 -4
- package/src/runtime/internal/client/script.js +1 -1
- package/src/runtime/internal/server/index.js +22 -13
- package/src/utils/builders.js +2 -2
- package/tests/client/__snapshots__/for.test.ripple.snap +0 -80
- package/tests/client/basic/__snapshots__/basic.rendering.test.ripple.snap +0 -48
- package/tests/client/basic/basic.errors.test.ripple +16 -0
- package/tests/client/basic/basic.get-set.test.ripple +291 -0
- package/tests/client/dynamic-elements.test.ripple +210 -8
- package/tests/server/await.test.ripple +61 -0
- package/tests/server/for.test.ripple +44 -0
- package/tests/server/if.test.ripple +21 -1
- package/tests/utils/escaping.test.js +102 -0
- package/tests/utils/events.test.js +147 -0
- package/tests/utils/normalize_css_property_name.test.js +43 -0
- package/tests/utils/patterns.test.js +382 -0
- package/tests/utils/sanitize_template_string.test.js +51 -0
- package/types/server.d.ts +25 -3
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { escape } from '../../src/utils/escaping.js';
|
|
3
|
+
|
|
4
|
+
describe('escape utility', () => {
|
|
5
|
+
describe('content escaping (is_attr = false)', () => {
|
|
6
|
+
it('should escape & to &', () => {
|
|
7
|
+
expect(escape('foo & bar', false)).toBe('foo & bar');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('should escape < to <', () => {
|
|
11
|
+
expect(escape('foo < bar', false)).toBe('foo < bar');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should escape multiple special characters', () => {
|
|
15
|
+
expect(escape('a & b < c', false)).toBe('a & b < c');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should not escape double quotes in content', () => {
|
|
19
|
+
expect(escape('foo "bar" baz', false)).toBe('foo "bar" baz');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should handle empty string', () => {
|
|
23
|
+
expect(escape('', false)).toBe('');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should handle string with no special characters', () => {
|
|
27
|
+
expect(escape('hello world', false)).toBe('hello world');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should handle null values', () => {
|
|
31
|
+
expect(escape(null, false)).toBe('');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should handle undefined values', () => {
|
|
35
|
+
expect(escape(undefined, false)).toBe('');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should handle numbers', () => {
|
|
39
|
+
expect(escape(123, false)).toBe('123');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should escape consecutive special characters', () => {
|
|
43
|
+
expect(escape('&&<<', false)).toBe('&&<<');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should handle special characters at start', () => {
|
|
47
|
+
expect(escape('&hello', false)).toBe('&hello');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should handle special characters at end', () => {
|
|
51
|
+
expect(escape('hello<', false)).toBe('hello<');
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('attribute escaping (is_attr = true)', () => {
|
|
56
|
+
it('should escape & to &', () => {
|
|
57
|
+
expect(escape('foo & bar', true)).toBe('foo & bar');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should escape < to <', () => {
|
|
61
|
+
expect(escape('foo < bar', true)).toBe('foo < bar');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should escape " to "', () => {
|
|
65
|
+
expect(escape('foo "bar" baz', true)).toBe('foo "bar" baz');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should escape all three special characters', () => {
|
|
69
|
+
expect(escape('a & b < c "d"', true)).toBe('a & b < c "d"');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should handle empty string', () => {
|
|
73
|
+
expect(escape('', true)).toBe('');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should handle string with no special characters', () => {
|
|
77
|
+
expect(escape('hello world', true)).toBe('hello world');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should handle null values', () => {
|
|
81
|
+
expect(escape(null, true)).toBe('');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should handle undefined values', () => {
|
|
85
|
+
expect(escape(undefined, true)).toBe('');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should escape consecutive quotes', () => {
|
|
89
|
+
expect(escape('"""', true)).toBe('"""');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should handle mixed escaping', () => {
|
|
93
|
+
expect(escape('<div class="foo & bar">', true)).toBe('<div class="foo & bar">');
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('default parameter behavior', () => {
|
|
98
|
+
it('should default to content escaping when is_attr is undefined', () => {
|
|
99
|
+
expect(escape('foo "bar"')).toBe('foo "bar"');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
is_delegated,
|
|
4
|
+
is_event_attribute,
|
|
5
|
+
is_capture_event,
|
|
6
|
+
get_attribute_event_name,
|
|
7
|
+
is_passive_event
|
|
8
|
+
} from '../../src/utils/events.js';
|
|
9
|
+
|
|
10
|
+
describe('events utility', () => {
|
|
11
|
+
describe('is_delegated', () => {
|
|
12
|
+
it('should return true for delegated events', () => {
|
|
13
|
+
expect(is_delegated('click')).toBe(true);
|
|
14
|
+
expect(is_delegated('input')).toBe(true);
|
|
15
|
+
expect(is_delegated('change')).toBe(true);
|
|
16
|
+
expect(is_delegated('mousedown')).toBe(true);
|
|
17
|
+
expect(is_delegated('keydown')).toBe(true);
|
|
18
|
+
expect(is_delegated('pointerdown')).toBe(true);
|
|
19
|
+
expect(is_delegated('touchstart')).toBe(true);
|
|
20
|
+
expect(is_delegated('focusin')).toBe(true);
|
|
21
|
+
expect(is_delegated('focusout')).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should return false for non-delegated events', () => {
|
|
25
|
+
expect(is_delegated('focus')).toBe(false);
|
|
26
|
+
expect(is_delegated('blur')).toBe(false);
|
|
27
|
+
expect(is_delegated('scroll')).toBe(false);
|
|
28
|
+
expect(is_delegated('load')).toBe(false);
|
|
29
|
+
expect(is_delegated('resize')).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should be case-sensitive', () => {
|
|
33
|
+
expect(is_delegated('Click')).toBe(false);
|
|
34
|
+
expect(is_delegated('CLICK')).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('is_event_attribute', () => {
|
|
39
|
+
it('should return true for valid event attributes', () => {
|
|
40
|
+
expect(is_event_attribute('onClick')).toBe(true);
|
|
41
|
+
expect(is_event_attribute('onInput')).toBe(true);
|
|
42
|
+
expect(is_event_attribute('onChange')).toBe(true);
|
|
43
|
+
expect(is_event_attribute('onMouseDown')).toBe(true);
|
|
44
|
+
expect(is_event_attribute('onKeyPress')).toBe(true);
|
|
45
|
+
expect(is_event_attribute('on-click')).toBe(true);
|
|
46
|
+
expect(is_event_attribute('on_click')).toBe(true);
|
|
47
|
+
expect(is_event_attribute('on$click')).toBe(true);
|
|
48
|
+
expect(is_event_attribute('on$')).toBe(true);
|
|
49
|
+
expect(is_event_attribute('on-')).toBe(true);
|
|
50
|
+
expect(is_event_attribute('on_')).toBe(true);
|
|
51
|
+
expect(is_event_attribute('on1')).toBe(true);
|
|
52
|
+
expect(is_event_attribute('on1click')).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should return false for non-event attributes', () => {
|
|
56
|
+
expect(is_event_attribute('on')).toBe(false);
|
|
57
|
+
expect(is_event_attribute('onclick')).toBe(false);
|
|
58
|
+
expect(is_event_attribute('class')).toBe(false);
|
|
59
|
+
expect(is_event_attribute('id')).toBe(false);
|
|
60
|
+
expect(is_event_attribute('value')).toBe(false);
|
|
61
|
+
expect(is_event_attribute('aria-label')).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should require uppercase third character', () => {
|
|
65
|
+
expect(is_event_attribute('onabc')).toBe(false);
|
|
66
|
+
expect(is_event_attribute('onAbc')).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should require at least 3 characters', () => {
|
|
70
|
+
expect(is_event_attribute('onA')).toBe(true);
|
|
71
|
+
expect(is_event_attribute('on')).toBe(false);
|
|
72
|
+
expect(is_event_attribute('o')).toBe(false);
|
|
73
|
+
expect(is_event_attribute('')).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('is_capture_event', () => {
|
|
78
|
+
it('should return true for capture events', () => {
|
|
79
|
+
expect(is_capture_event('clickCapture')).toBe(true);
|
|
80
|
+
expect(is_capture_event('mousedownCapture')).toBe(true);
|
|
81
|
+
expect(is_capture_event('keydownCapture')).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should return false for non-capture events', () => {
|
|
85
|
+
expect(is_capture_event('click')).toBe(false);
|
|
86
|
+
expect(is_capture_event('mousedown')).toBe(false);
|
|
87
|
+
expect(is_capture_event('mousedown')).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should exclude gotpointercapture and lostpointercapture', () => {
|
|
91
|
+
expect(is_capture_event('gotpointercapture')).toBe(false);
|
|
92
|
+
expect(is_capture_event('lostpointercapture')).toBe(false);
|
|
93
|
+
expect(is_capture_event('gotPointerCapture')).toBe(false);
|
|
94
|
+
expect(is_capture_event('lostPointerCapture')).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should be case-insensitive for pointer capture events', () => {
|
|
98
|
+
expect(is_capture_event('GOTPOINTERCAPTURE')).toBe(false);
|
|
99
|
+
expect(is_capture_event('LOSTPOINTERCAPTURE')).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should be case-sensitive for other events', () => {
|
|
103
|
+
expect(is_capture_event('clickCapture')).toBe(true);
|
|
104
|
+
expect(is_capture_event('keypressCapture')).toBe(true);
|
|
105
|
+
expect(is_capture_event('clickcapture')).toBe(false);
|
|
106
|
+
expect(is_capture_event('keypresscapture')).toBe(false);
|
|
107
|
+
})
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('get_attribute_event_name', () => {
|
|
111
|
+
it('should convert event attribute names to lowercase and strip "on" prefix', () => {
|
|
112
|
+
expect(get_attribute_event_name('onClick')).toBe('click');
|
|
113
|
+
expect(get_attribute_event_name('onInput')).toBe('input');
|
|
114
|
+
expect(get_attribute_event_name('onMouseDown')).toBe('mousedown');
|
|
115
|
+
expect(get_attribute_event_name('onKeyPress')).toBe('keypress');
|
|
116
|
+
expect(get_attribute_event_name('onChange')).toBe('change');
|
|
117
|
+
expect(get_attribute_event_name('onFocus')).toBe('focus');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should handle capture events and strip both "on" and "Capture"', () => {
|
|
121
|
+
expect(get_attribute_event_name('onClickCapture')).toBe('click');
|
|
122
|
+
expect(get_attribute_event_name('onMouseDownCapture')).toBe('mousedown');
|
|
123
|
+
expect(get_attribute_event_name('onMouseDownCapture')).toBe('mousedown');
|
|
124
|
+
expect(get_attribute_event_name('onGotPointerCapture')).toBe('gotpointercapture');
|
|
125
|
+
expect(get_attribute_event_name('onLostPointerCapture')).toBe('lostpointercapture');
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe('is_passive_event', () => {
|
|
130
|
+
it('should return true for passive events', () => {
|
|
131
|
+
expect(is_passive_event('touchstart')).toBe(true);
|
|
132
|
+
expect(is_passive_event('touchmove')).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should return false for non-passive events', () => {
|
|
136
|
+
expect(is_passive_event('click')).toBe(false);
|
|
137
|
+
expect(is_passive_event('mousedown')).toBe(false);
|
|
138
|
+
expect(is_passive_event('touchend')).toBe(false);
|
|
139
|
+
expect(is_passive_event('scroll')).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should be case-sensitive', () => {
|
|
143
|
+
expect(is_passive_event('TouchStart')).toBe(false);
|
|
144
|
+
expect(is_passive_event('TOUCHMOVE')).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { normalize_css_property_name } from '../../src/utils/normalize_css_property_name.js';
|
|
3
|
+
|
|
4
|
+
describe('normalize_css_property_name utility', () => {
|
|
5
|
+
it('should convert camelCase to kebab-case', () => {
|
|
6
|
+
expect(normalize_css_property_name('backgroundColor')).toBe('background-color');
|
|
7
|
+
expect(normalize_css_property_name('fontSize')).toBe('font-size');
|
|
8
|
+
expect(normalize_css_property_name('marginTop')).toBe('margin-top');
|
|
9
|
+
expect(normalize_css_property_name('borderRadius')).toBe('border-radius');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should handle multiple uppercase letters', () => {
|
|
13
|
+
expect(normalize_css_property_name('WebkitTransform')).toBe('-webkit-transform');
|
|
14
|
+
expect(normalize_css_property_name('MozAppearance')).toBe('-moz-appearance');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should preserve CSS custom properties (starting with --)', () => {
|
|
18
|
+
expect(normalize_css_property_name('--custom-property')).toBe('--custom-property');
|
|
19
|
+
expect(normalize_css_property_name('--myColor')).toBe('--myColor');
|
|
20
|
+
expect(normalize_css_property_name('--themePrimary')).toBe('--themePrimary');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should handle already lowercase properties', () => {
|
|
24
|
+
expect(normalize_css_property_name('color')).toBe('color');
|
|
25
|
+
expect(normalize_css_property_name('display')).toBe('display');
|
|
26
|
+
expect(normalize_css_property_name('position')).toBe('position');
|
|
27
|
+
expect(normalize_css_property_name('z-index')).toBe('z-index');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should handle consecutive uppercase letters', () => {
|
|
31
|
+
expect(normalize_css_property_name('HTMLElement')).toBe('-h-t-m-l-element');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should handle empty string', () => {
|
|
35
|
+
expect(normalize_css_property_name('')).toBe('');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should handle complex property names', () => {
|
|
39
|
+
expect(normalize_css_property_name('borderTopLeftRadius')).toBe('border-top-left-radius');
|
|
40
|
+
expect(normalize_css_property_name('textDecorationColor')).toBe('text-decoration-color');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import * as patterns from '../../src/utils/patterns.js';
|
|
3
|
+
|
|
4
|
+
describe('patterns utility', () => {
|
|
5
|
+
describe('regex_whitespace', () => {
|
|
6
|
+
it('should match single whitespace characters', () => {
|
|
7
|
+
expect(patterns.regex_whitespace.test(' ')).toBe(true);
|
|
8
|
+
expect(patterns.regex_whitespace.test('\t')).toBe(true);
|
|
9
|
+
expect(patterns.regex_whitespace.test('\n')).toBe(true);
|
|
10
|
+
expect(patterns.regex_whitespace.test('\r')).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should match whitespace character between characters', () => {
|
|
14
|
+
expect(patterns.regex_whitespace.test('a b')).toBe(true);
|
|
15
|
+
expect(patterns.regex_whitespace.test('a\tb')).toBe(true);
|
|
16
|
+
expect(patterns.regex_whitespace.test('a\nb')).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should match whitespace at start or end', () => {
|
|
20
|
+
expect(patterns.regex_whitespace.test(' hello')).toBe(true);
|
|
21
|
+
expect(patterns.regex_whitespace.test('hello ')).toBe(true);
|
|
22
|
+
expect(patterns.regex_whitespace.test('\thello')).toBe(true);
|
|
23
|
+
expect(patterns.regex_whitespace.test('hello\t')).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should match multiple whitespace characters', () => {
|
|
27
|
+
expect(patterns.regex_whitespace.test(' ')).toBe(true);
|
|
28
|
+
expect(patterns.regex_whitespace.test('\t\r\n ')).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should not match non-whitespace', () => {
|
|
32
|
+
expect(patterns.regex_whitespace.test('helloworld')).toBe(false);
|
|
33
|
+
expect(patterns.regex_whitespace.test('1')).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should not match empty string', () => {
|
|
37
|
+
expect(patterns.regex_whitespace.test('')).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('regex_whitespaces', () => {
|
|
42
|
+
it('should match multiple whitespace characters', () => {
|
|
43
|
+
expect(patterns.regex_whitespaces.test(' ')).toBe(true);
|
|
44
|
+
expect(patterns.regex_whitespaces.test('\t\t')).toBe(true);
|
|
45
|
+
expect(patterns.regex_whitespaces.test(' \t\n')).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should match single whitespace character', () => {
|
|
49
|
+
expect(patterns.regex_whitespaces.test(' ')).toBe(true);
|
|
50
|
+
expect(patterns.regex_whitespaces.test('\t')).toBe(true);
|
|
51
|
+
expect(patterns.regex_whitespaces.test('\n')).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should match whitespaces between characters', () => {
|
|
55
|
+
expect(patterns.regex_whitespaces.test('a b')).toBe(true);
|
|
56
|
+
expect(patterns.regex_whitespaces.test('a\t\r\nb')).toBe(true);
|
|
57
|
+
expect(patterns.regex_whitespaces.test('a\nb')).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should match whitespaces at start or end', () => {
|
|
61
|
+
expect(patterns.regex_whitespaces.test(' hello')).toBe(true);
|
|
62
|
+
expect(patterns.regex_whitespaces.test('hello \n')).toBe(true);
|
|
63
|
+
expect(patterns.regex_whitespaces.test('\t\rhello')).toBe(true);
|
|
64
|
+
expect(patterns.regex_whitespaces.test('hello\t ')).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should not match non-whitespace', () => {
|
|
68
|
+
expect(patterns.regex_whitespaces.test('helloworld')).toBe(false);
|
|
69
|
+
expect(patterns.regex_whitespaces.test('1')).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should not match empty string', () => {
|
|
73
|
+
expect(patterns.regex_whitespaces.test('')).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('regex_starts_with_newline', () => {
|
|
78
|
+
it('should match strings starting with newline', () => {
|
|
79
|
+
expect(patterns.regex_starts_with_newline.test('\nhello')).toBe(true);
|
|
80
|
+
expect(patterns.regex_starts_with_newline.test('\r\nworld')).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should match strings with only newline', () => {
|
|
84
|
+
expect(patterns.regex_starts_with_newline.test('\n')).toBe(true);
|
|
85
|
+
expect(patterns.regex_starts_with_newline.test('\r\n')).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should not match empty string', () => {
|
|
89
|
+
expect(patterns.regex_starts_with_newline.test('')).toBe(false);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should not match strings without leading newline', () => {
|
|
93
|
+
expect(patterns.regex_starts_with_newline.test('hello\n')).toBe(false);
|
|
94
|
+
expect(patterns.regex_starts_with_newline.test(' \nhello')).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('regex_starts_with_whitespace', () => {
|
|
99
|
+
it('should match strings starting with whitespace', () => {
|
|
100
|
+
expect(patterns.regex_starts_with_whitespace.test(' hello')).toBe(true);
|
|
101
|
+
expect(patterns.regex_starts_with_whitespace.test('\thello')).toBe(true);
|
|
102
|
+
expect(patterns.regex_starts_with_whitespace.test('\nhello')).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should match strings starting with multiple whitespaces', () => {
|
|
106
|
+
expect(patterns.regex_starts_with_whitespace.test(' hello')).toBe(true);
|
|
107
|
+
expect(patterns.regex_starts_with_whitespace.test('\t\nhello')).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should match strings with only whitespace', () => {
|
|
111
|
+
expect(patterns.regex_starts_with_whitespace.test(' ')).toBe(true);
|
|
112
|
+
expect(patterns.regex_starts_with_whitespace.test('\t\n\r')).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('should not match empty string', () => {
|
|
116
|
+
expect(patterns.regex_starts_with_whitespace.test('')).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should not match strings without leading whitespace', () => {
|
|
120
|
+
expect(patterns.regex_starts_with_whitespace.test('hello ')).toBe(false);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('regex_starts_with_whitespaces', () => {
|
|
125
|
+
it('should match strings starting with a single whitespace', () => {
|
|
126
|
+
expect(patterns.regex_starts_with_whitespaces.test(' hello')).toBe(true);
|
|
127
|
+
expect(patterns.regex_starts_with_whitespaces.test('\thello')).toBe(true);
|
|
128
|
+
expect(patterns.regex_starts_with_whitespaces.test('\nhello')).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should match strings starting with multiple whitespaces', () => {
|
|
132
|
+
expect(patterns.regex_starts_with_whitespaces.test(' hello')).toBe(true);
|
|
133
|
+
expect(patterns.regex_starts_with_whitespaces.test('\t\nhello')).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('should match strings with only whitespace', () => {
|
|
137
|
+
expect(patterns.regex_starts_with_whitespaces.test(' ')).toBe(true);
|
|
138
|
+
expect(patterns.regex_starts_with_whitespaces.test('\t\n\r')).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should not match empty string', () => {
|
|
142
|
+
expect(patterns.regex_starts_with_whitespaces.test('')).toBe(false);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should not match strings without leading whitespace', () => {
|
|
146
|
+
expect(patterns.regex_starts_with_whitespaces.test('hello ')).toBe(false);
|
|
147
|
+
expect(patterns.regex_starts_with_whitespaces.test('a b c ')).toBe(false);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('regex_ends_with_whitespace', () => {
|
|
152
|
+
it('should match strings ending with whitespace', () => {
|
|
153
|
+
expect(patterns.regex_ends_with_whitespace.test('hello ')).toBe(true);
|
|
154
|
+
expect(patterns.regex_ends_with_whitespace.test('hello\t')).toBe(true);
|
|
155
|
+
expect(patterns.regex_ends_with_whitespace.test('hello\n')).toBe(true);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should match strings ending with multiple whitespaces', () => {
|
|
159
|
+
expect(patterns.regex_ends_with_whitespace.test('hello ')).toBe(true);
|
|
160
|
+
expect(patterns.regex_ends_with_whitespace.test('hello\t\n')).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should match strings with only whitespace', () => {
|
|
164
|
+
expect(patterns.regex_ends_with_whitespace.test(' ')).toBe(true);
|
|
165
|
+
expect(patterns.regex_ends_with_whitespace.test('\t\n\r')).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should not match empty string', () => {
|
|
169
|
+
expect(patterns.regex_ends_with_whitespace.test('')).toBe(false);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should not match strings without trailing whitespace', () => {
|
|
173
|
+
expect(patterns.regex_ends_with_whitespace.test(' hello')).toBe(false);
|
|
174
|
+
expect(patterns.regex_ends_with_whitespace.test('hello')).toBe(false);
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe('regex_ends_with_whitespaces', () => {
|
|
179
|
+
it('should match strings ending with multiple whitespaces', () => {
|
|
180
|
+
expect(patterns.regex_ends_with_whitespaces.test('hello ')).toBe(true);
|
|
181
|
+
expect(patterns.regex_ends_with_whitespaces.test('hello\t\n')).toBe(true);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should match strings with only whitespaces', () => {
|
|
185
|
+
expect(patterns.regex_ends_with_whitespaces.test(' ')).toBe(true);
|
|
186
|
+
expect(patterns.regex_ends_with_whitespaces.test('\t\n\r')).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('should not match empty string', () => {
|
|
190
|
+
expect(patterns.regex_ends_with_whitespaces.test('')).toBe(false);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should not match strings not ending with whitespaces', () => {
|
|
194
|
+
expect(patterns.regex_ends_with_whitespaces.test(' hello')).toBe(false);
|
|
195
|
+
expect(patterns.regex_ends_with_whitespaces.test('hello')).toBe(false);
|
|
196
|
+
expect(patterns.regex_ends_with_whitespaces.test('hello')).toBe(false);
|
|
197
|
+
expect(patterns.regex_ends_with_whitespaces.test('a b\nc')).toBe(false);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
describe('regex_not_whitespace', () => {
|
|
202
|
+
it('should match non-whitespace characters', () => {
|
|
203
|
+
expect(patterns.regex_not_whitespace.test('a')).toBe(true);
|
|
204
|
+
expect(patterns.regex_not_whitespace.test('1')).toBe(true);
|
|
205
|
+
expect(patterns.regex_not_whitespace.test('hello world')).toBe(true);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should not match empty string', () => {
|
|
209
|
+
expect(patterns.regex_not_whitespace.test('')).toBe(false);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('should not match only whitespace', () => {
|
|
213
|
+
expect(patterns.regex_not_whitespace.test(' ')).toBe(false);
|
|
214
|
+
expect(patterns.regex_not_whitespace.test('\t\n\r')).toBe(false);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe('regex_only_whitespaces', () => {
|
|
219
|
+
it('should match strings with only whitespaces', () => {
|
|
220
|
+
expect(patterns.regex_only_whitespaces.test(' ')).toBe(true);
|
|
221
|
+
expect(patterns.regex_only_whitespaces.test('\t\n\r\f')).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('should not match empty string', () => {
|
|
225
|
+
expect(patterns.regex_only_whitespaces.test('')).toBe(false);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('should not match strings with content', () => {
|
|
229
|
+
expect(patterns.regex_only_whitespaces.test(' a ')).toBe(false);
|
|
230
|
+
expect(patterns.regex_only_whitespaces.test('hello')).toBe(false);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
describe('regex_is_valid_identifier', () => {
|
|
235
|
+
it('should match valid JavaScript identifiers', () => {
|
|
236
|
+
expect(patterns.regex_is_valid_identifier.test('foo')).toBe(true);
|
|
237
|
+
expect(patterns.regex_is_valid_identifier.test('_private')).toBe(true);
|
|
238
|
+
expect(patterns.regex_is_valid_identifier.test('$jquery')).toBe(true);
|
|
239
|
+
expect(patterns.regex_is_valid_identifier.test('myVar123')).toBe(true);
|
|
240
|
+
expect(patterns.regex_is_valid_identifier.test('CamelCase')).toBe(true);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should not match invalid identifiers', () => {
|
|
244
|
+
expect(patterns.regex_is_valid_identifier.test('123abc')).toBe(false);
|
|
245
|
+
expect(patterns.regex_is_valid_identifier.test('my-var')).toBe(false);
|
|
246
|
+
expect(patterns.regex_is_valid_identifier.test('my var')).toBe(false);
|
|
247
|
+
expect(patterns.regex_is_valid_identifier.test('my.var')).toBe(false);
|
|
248
|
+
expect(patterns.regex_is_valid_identifier.test('')).toBe(false);
|
|
249
|
+
expect(patterns.regex_is_valid_identifier.test('\n')).toBe(false);
|
|
250
|
+
expect(patterns.regex_is_valid_identifier.test('my\tvar')).toBe(false);
|
|
251
|
+
expect(patterns.regex_is_valid_identifier.test('my\rvar')).toBe(false);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
describe('regex_invalid_identifier_chars', () => {
|
|
256
|
+
it('should remove invalid identifier characters', () => {
|
|
257
|
+
expect('123abc'.replace(patterns.regex_invalid_identifier_chars, '_')).toBe('_23abc');
|
|
258
|
+
expect('my-var'.replace(patterns.regex_invalid_identifier_chars, '_')).toBe('my_var');
|
|
259
|
+
expect('hello.world'.replace(patterns.regex_invalid_identifier_chars, '_')).toBe('hello_world');
|
|
260
|
+
expect('\t\r\nhello.world'.replace(patterns.regex_invalid_identifier_chars, '_')).toBe('___hello_world');
|
|
261
|
+
expect('my\tvar'.replace(patterns.regex_invalid_identifier_chars, '_')).toBe('my_var');
|
|
262
|
+
expect('my\rvar'.replace(patterns.regex_invalid_identifier_chars, '_')).toBe('my_var');
|
|
263
|
+
expect(''.replace(patterns.regex_invalid_identifier_chars, '_')).toBe('');
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe('regex_starts_with_vowel', () => {
|
|
268
|
+
it('should match strings starting with vowels', () => {
|
|
269
|
+
expect(patterns.regex_starts_with_vowel.test('apple')).toBe(true);
|
|
270
|
+
expect(patterns.regex_starts_with_vowel.test('elephant')).toBe(true);
|
|
271
|
+
expect(patterns.regex_starts_with_vowel.test('ice')).toBe(true);
|
|
272
|
+
expect(patterns.regex_starts_with_vowel.test('orange')).toBe(true);
|
|
273
|
+
expect(patterns.regex_starts_with_vowel.test('umbrella')).toBe(true);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('should not match strings starting with consonants', () => {
|
|
277
|
+
expect(patterns.regex_starts_with_vowel.test('banana')).toBe(false);
|
|
278
|
+
expect(patterns.regex_starts_with_vowel.test('cat')).toBe(false);
|
|
279
|
+
expect(patterns.regex_starts_with_vowel.test('d')).toBe(false);
|
|
280
|
+
expect(patterns.regex_starts_with_vowel.test('f')).toBe(false);
|
|
281
|
+
expect(patterns.regex_starts_with_vowel.test('g')).toBe(false);
|
|
282
|
+
expect(patterns.regex_starts_with_vowel.test('hello')).toBe(false);
|
|
283
|
+
expect(patterns.regex_starts_with_vowel.test('j')).toBe(false);
|
|
284
|
+
expect(patterns.regex_starts_with_vowel.test('k')).toBe(false);
|
|
285
|
+
expect(patterns.regex_starts_with_vowel.test('l')).toBe(false);
|
|
286
|
+
expect(patterns.regex_starts_with_vowel.test('m')).toBe(false);
|
|
287
|
+
expect(patterns.regex_starts_with_vowel.test('n')).toBe(false);
|
|
288
|
+
expect(patterns.regex_starts_with_vowel.test('p')).toBe(false);
|
|
289
|
+
expect(patterns.regex_starts_with_vowel.test('q')).toBe(false);
|
|
290
|
+
expect(patterns.regex_starts_with_vowel.test('r')).toBe(false);
|
|
291
|
+
expect(patterns.regex_starts_with_vowel.test('s')).toBe(false);
|
|
292
|
+
expect(patterns.regex_starts_with_vowel.test('t')).toBe(false);
|
|
293
|
+
expect(patterns.regex_starts_with_vowel.test('v')).toBe(false);
|
|
294
|
+
expect(patterns.regex_starts_with_vowel.test('w')).toBe(false);
|
|
295
|
+
expect(patterns.regex_starts_with_vowel.test('x')).toBe(false);
|
|
296
|
+
expect(patterns.regex_starts_with_vowel.test('y')).toBe(false);
|
|
297
|
+
expect(patterns.regex_starts_with_vowel.test('z')).toBe(false);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('should be case-sensitive', () => {
|
|
301
|
+
expect(patterns.regex_starts_with_vowel.test('Apple')).toBe(false);
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
describe('regex_heading_tags', () => {
|
|
306
|
+
it('should match heading tags h1 through h6', () => {
|
|
307
|
+
expect(patterns.regex_heading_tags.test('h1')).toBe(true);
|
|
308
|
+
expect(patterns.regex_heading_tags.test('h2')).toBe(true);
|
|
309
|
+
expect(patterns.regex_heading_tags.test('h3')).toBe(true);
|
|
310
|
+
expect(patterns.regex_heading_tags.test('h4')).toBe(true);
|
|
311
|
+
expect(patterns.regex_heading_tags.test('h5')).toBe(true);
|
|
312
|
+
expect(patterns.regex_heading_tags.test('h6')).toBe(true);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('should not match invalid heading tags', () => {
|
|
316
|
+
expect(patterns.regex_heading_tags.test('h0')).toBe(false);
|
|
317
|
+
expect(patterns.regex_heading_tags.test('h7')).toBe(false);
|
|
318
|
+
expect(patterns.regex_heading_tags.test('H1')).toBe(false);
|
|
319
|
+
expect(patterns.regex_heading_tags.test('header')).toBe(false);
|
|
320
|
+
expect(patterns.regex_heading_tags.test('h')).toBe(false);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
describe('regex_illegal_attribute_character', () => {
|
|
325
|
+
it('should match illegal attribute characters', () => {
|
|
326
|
+
expect(patterns.regex_illegal_attribute_character.test('123')).toBe(true);
|
|
327
|
+
expect(patterns.regex_illegal_attribute_character.test('.class')).toBe(true);
|
|
328
|
+
expect(patterns.regex_illegal_attribute_character.test('-attr')).toBe(true);
|
|
329
|
+
expect(patterns.regex_illegal_attribute_character.test('attr^')).toBe(true);
|
|
330
|
+
expect(patterns.regex_illegal_attribute_character.test('attr$')).toBe(true);
|
|
331
|
+
expect(patterns.regex_illegal_attribute_character.test('attr@')).toBe(true);
|
|
332
|
+
expect(patterns.regex_illegal_attribute_character.test('attr%')).toBe(true);
|
|
333
|
+
expect(patterns.regex_illegal_attribute_character.test('attr&')).toBe(true);
|
|
334
|
+
expect(patterns.regex_illegal_attribute_character.test('attr#')).toBe(true);
|
|
335
|
+
expect(patterns.regex_illegal_attribute_character.test('attr?')).toBe(true);
|
|
336
|
+
expect(patterns.regex_illegal_attribute_character.test('attr!')).toBe(true);
|
|
337
|
+
expect(patterns.regex_illegal_attribute_character.test('attr|')).toBe(true);
|
|
338
|
+
expect(patterns.regex_illegal_attribute_character.test('attr[')).toBe(true);
|
|
339
|
+
expect(patterns.regex_illegal_attribute_character.test('attr]')).toBe(true);
|
|
340
|
+
expect(patterns.regex_illegal_attribute_character.test('attr{')).toBe(true);
|
|
341
|
+
expect(patterns.regex_illegal_attribute_character.test('attr}')).toBe(true);
|
|
342
|
+
expect(patterns.regex_illegal_attribute_character.test('attr*')).toBe(true);
|
|
343
|
+
expect(patterns.regex_illegal_attribute_character.test('attr+')).toBe(true);
|
|
344
|
+
expect(patterns.regex_illegal_attribute_character.test('attr~')).toBe(true);
|
|
345
|
+
expect(patterns.regex_illegal_attribute_character.test('attr;')).toBe(true);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('should not match valid attribute names', () => {
|
|
349
|
+
expect(patterns.regex_illegal_attribute_character.test('id')).toBe(false);
|
|
350
|
+
expect(patterns.regex_illegal_attribute_character.test('class')).toBe(false);
|
|
351
|
+
expect(patterns.regex_illegal_attribute_character.test('className')).toBe(false);
|
|
352
|
+
expect(patterns.regex_illegal_attribute_character.test('className123')).toBe(false);
|
|
353
|
+
expect(patterns.regex_illegal_attribute_character.test('class-name-123')).toBe(false);
|
|
354
|
+
expect(patterns.regex_illegal_attribute_character.test('data-value')).toBe(false);
|
|
355
|
+
expect(patterns.regex_illegal_attribute_character.test('aria-label')).toBe(false);
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
describe('regex_newline_characters', () => {
|
|
360
|
+
it('should match newline characters globally', () => {
|
|
361
|
+
const text = 'line1\nline2\nline3';
|
|
362
|
+
const matches = text.match(patterns.regex_newline_characters);
|
|
363
|
+
expect(matches?.length).toBe(2);
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
describe('regex_not_newline_characters', () => {
|
|
368
|
+
it('should match non-newline characters globally', () => {
|
|
369
|
+
const text = 'ab\ncd';
|
|
370
|
+
const matches = text.match(patterns.regex_not_newline_characters);
|
|
371
|
+
expect(matches?.length).toBe(4);
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
describe('regex_whitespaces_strict', () => {
|
|
376
|
+
it('should match strict whitespace sequences globally', () => {
|
|
377
|
+
const text = 'a b\tc d';
|
|
378
|
+
const result = text.replace(patterns.regex_whitespaces_strict, '-');
|
|
379
|
+
expect(result).toBe('a-b-c-d');
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
});
|