ripple 0.3.44 → 0.3.45
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/CHANGELOG.md +18 -0
- package/package.json +4 -4
- package/src/runtime/internal/client/events.js +5 -5
- package/src/runtime/internal/client/render.js +5 -2
- package/src/runtime/internal/server/index.js +3 -3
- package/src/runtime/reactive-value.js +8 -5
- package/tests/client/basic/basic.components.test.tsrx +7 -0
- package/tests/client/basic/basic.rendering.test.tsrx +14 -0
- package/tests/client/compiler/compiler.basic.test.tsrx +94 -0
- package/tests/server/basic.components.test.tsrx +7 -0
- package/tests/server/compiler.test.tsrx +38 -0
- package/tests/server/if.test.tsrx +13 -0
- package/types/index.d.ts +4 -11
- package/src/utils/ast.js +0 -273
- package/src/utils/attributes.js +0 -43
- package/src/utils/builders.js +0 -1287
- package/src/utils/escaping.js +0 -37
- package/src/utils/events.js +0 -154
- package/src/utils/normalize_css_property_name.js +0 -23
- package/src/utils/patterns.js +0 -24
- package/src/utils/sanitize_template_string.js +0 -7
- package/tests/utils/double-quoted-text-children.test.js +0 -16
- package/tests/utils/escaping.test.js +0 -104
- package/tests/utils/events.test.js +0 -158
- package/tests/utils/normalize_css_property_name.test.js +0 -42
- package/tests/utils/patterns.test.js +0 -386
- package/tests/utils/sanitize_template_string.test.js +0 -52
package/src/utils/escaping.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
const ATTR_REGEX = /[&"<]/g;
|
|
2
|
-
const CONTENT_REGEX = /[&<]/g;
|
|
3
|
-
const OPEN_TAG_REGEX = /</g;
|
|
4
|
-
const CLOSE_TAG_REGEX = />/g;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @template V
|
|
8
|
-
* @param {V} value
|
|
9
|
-
* @param {boolean} [is_attr]
|
|
10
|
-
*/
|
|
11
|
-
export function escape(value, is_attr) {
|
|
12
|
-
const str = String(value ?? '');
|
|
13
|
-
|
|
14
|
-
const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX;
|
|
15
|
-
pattern.lastIndex = 0;
|
|
16
|
-
|
|
17
|
-
let escaped = '';
|
|
18
|
-
let last = 0;
|
|
19
|
-
|
|
20
|
-
while (pattern.test(str)) {
|
|
21
|
-
const i = pattern.lastIndex - 1;
|
|
22
|
-
const ch = str[i];
|
|
23
|
-
escaped += str.substring(last, i) + (ch === '&' ? '&' : ch === '"' ? '"' : '<');
|
|
24
|
-
last = i + 1;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return escaped + str.substring(last);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Escapes characters that can prematurely terminate inline script tags.
|
|
32
|
-
* @param {string} str
|
|
33
|
-
* @returns {string}
|
|
34
|
-
*/
|
|
35
|
-
export function escape_script(str) {
|
|
36
|
-
return str.replace(OPEN_TAG_REGEX, '\\u003c').replace(CLOSE_TAG_REGEX, '\\u003e');
|
|
37
|
-
}
|
package/src/utils/events.js
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
/** @import { AddEventObject } from '#public'*/
|
|
2
|
-
|
|
3
|
-
const NON_DELEGATED_EVENTS = new Set([
|
|
4
|
-
'abort',
|
|
5
|
-
'afterprint',
|
|
6
|
-
'beforeprint',
|
|
7
|
-
'beforetoggle',
|
|
8
|
-
'beforeunload',
|
|
9
|
-
'blur',
|
|
10
|
-
'close',
|
|
11
|
-
'command',
|
|
12
|
-
'contextmenu',
|
|
13
|
-
'cuechange',
|
|
14
|
-
'DOMContentLoaded',
|
|
15
|
-
'error',
|
|
16
|
-
'focus',
|
|
17
|
-
'invalid',
|
|
18
|
-
'load',
|
|
19
|
-
'loadend',
|
|
20
|
-
'loadstart',
|
|
21
|
-
'mouseenter',
|
|
22
|
-
'mouseleave',
|
|
23
|
-
'pointerenter',
|
|
24
|
-
'pointerleave',
|
|
25
|
-
'progress',
|
|
26
|
-
'readystatechange',
|
|
27
|
-
'resize',
|
|
28
|
-
'scroll',
|
|
29
|
-
'scrollend',
|
|
30
|
-
'toggle',
|
|
31
|
-
'unload',
|
|
32
|
-
'visibilitychange',
|
|
33
|
-
// Media Events
|
|
34
|
-
'canplay',
|
|
35
|
-
'canplaythrough',
|
|
36
|
-
'durationchange',
|
|
37
|
-
'emptied',
|
|
38
|
-
'encrypted',
|
|
39
|
-
'ended',
|
|
40
|
-
'loadeddata',
|
|
41
|
-
'loadedmetadata',
|
|
42
|
-
'loadstart',
|
|
43
|
-
'pause',
|
|
44
|
-
'play',
|
|
45
|
-
'playing',
|
|
46
|
-
'progress',
|
|
47
|
-
'ratechange',
|
|
48
|
-
'seeked',
|
|
49
|
-
'seeking',
|
|
50
|
-
'stalled',
|
|
51
|
-
'suspend',
|
|
52
|
-
'timeupdate',
|
|
53
|
-
'volumechange',
|
|
54
|
-
'waiting',
|
|
55
|
-
'waitingforkey',
|
|
56
|
-
]);
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Checks if an event should be delegated
|
|
60
|
-
* @param {string} event_name - The event name (e.g., 'click', 'focus')
|
|
61
|
-
* @returns {boolean}
|
|
62
|
-
*/
|
|
63
|
-
export function is_non_delegated(event_name) {
|
|
64
|
-
return NON_DELEGATED_EVENTS.has(event_name);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Determines if an attribute is an event attribute (e.g., 'onClick').
|
|
69
|
-
* @param {string} attr - The attribute name.
|
|
70
|
-
* @returns {boolean}
|
|
71
|
-
*/
|
|
72
|
-
export function is_event_attribute(attr) {
|
|
73
|
-
return attr.startsWith('on') && attr.length > 2 && attr[2] === attr[2].toUpperCase();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Checks if the event is a capture event.
|
|
78
|
-
* @param {string} event_name - The event name.
|
|
79
|
-
* @returns {boolean}
|
|
80
|
-
*/
|
|
81
|
-
export function is_capture_event(event_name) {
|
|
82
|
-
var lowered = event_name.toLowerCase();
|
|
83
|
-
return (
|
|
84
|
-
event_name.endsWith('Capture') &&
|
|
85
|
-
lowered !== 'gotpointercapture' &&
|
|
86
|
-
lowered !== 'lostpointercapture'
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Retrieves the original event name from an event attribute.
|
|
92
|
-
* @param {string} name
|
|
93
|
-
* @returns {string}
|
|
94
|
-
*/
|
|
95
|
-
export function get_original_event_name(name) {
|
|
96
|
-
return name.slice(2);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Normalizes the event name to lowercase.
|
|
101
|
-
* @param {string} name
|
|
102
|
-
* @returns {string}
|
|
103
|
-
*/
|
|
104
|
-
export function normalize_event_name(name) {
|
|
105
|
-
return extract_event_name(name).toLowerCase();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Extracts the base event name from an event attribute.
|
|
110
|
-
* @param {string} name
|
|
111
|
-
* @returns {string}
|
|
112
|
-
*/
|
|
113
|
-
function extract_event_name(name) {
|
|
114
|
-
name = get_original_event_name(name);
|
|
115
|
-
|
|
116
|
-
if (is_capture_event(name)) {
|
|
117
|
-
return event_name_from_capture(name);
|
|
118
|
-
}
|
|
119
|
-
return name;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Converts a capture event name to its base event name.
|
|
124
|
-
* @param {string} event_name
|
|
125
|
-
* @returns {string}
|
|
126
|
-
*/
|
|
127
|
-
export function event_name_from_capture(event_name) {
|
|
128
|
-
return event_name.slice(0, -7); // strip "Capture"
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Converts an event attribute name to the actual event name.
|
|
133
|
-
* @param {string} name
|
|
134
|
-
* @param {EventListener | AddEventObject} handler
|
|
135
|
-
* @returns {string}
|
|
136
|
-
*/
|
|
137
|
-
export function get_attribute_event_name(name, handler) {
|
|
138
|
-
name = extract_event_name(name);
|
|
139
|
-
|
|
140
|
-
return typeof handler === 'object' && handler.customName
|
|
141
|
-
? handler.customName
|
|
142
|
-
: name.toLowerCase();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const PASSIVE_EVENTS = ['touchstart', 'touchmove', 'wheel', 'mousewheel'];
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Checks if an event is passive (e.g., 'touchstart', 'touchmove').
|
|
149
|
-
* @param {string} name - The event name.
|
|
150
|
-
* @returns {boolean}
|
|
151
|
-
*/
|
|
152
|
-
export function is_passive_event(name) {
|
|
153
|
-
return PASSIVE_EVENTS.includes(name);
|
|
154
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/** @type {Map<string, string>} */
|
|
2
|
-
const normalized_properties_cache = new Map();
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Takes a camelCased string and returns a hyphenated string
|
|
6
|
-
* @param {string} str
|
|
7
|
-
* @returns {string}
|
|
8
|
-
* @example
|
|
9
|
-
* normalize_css_property_name('backgroundColor') // 'background-color'
|
|
10
|
-
*/
|
|
11
|
-
export function normalize_css_property_name(str) {
|
|
12
|
-
if (str.startsWith('--')) return str;
|
|
13
|
-
|
|
14
|
-
let normalized_result = normalized_properties_cache.get(str);
|
|
15
|
-
if (normalized_result != null) {
|
|
16
|
-
return normalized_result;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
normalized_result = str.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
|
|
20
|
-
normalized_properties_cache.set(str, normalized_result);
|
|
21
|
-
|
|
22
|
-
return normalized_result;
|
|
23
|
-
}
|
package/src/utils/patterns.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export const regex_whitespace = /\s/;
|
|
2
|
-
export const regex_whitespaces = /\s+/;
|
|
3
|
-
export const regex_starts_with_newline = /^\r?\n/;
|
|
4
|
-
export const regex_starts_with_whitespace = /^\s/;
|
|
5
|
-
export const regex_starts_with_whitespaces = /^[ \t\r\n]+/;
|
|
6
|
-
export const regex_ends_with_whitespace = /\s$/;
|
|
7
|
-
export const regex_ends_with_whitespaces = /[ \t\r\n]+$/;
|
|
8
|
-
/** Not \S because that also removes explicit whitespace defined through things like ` ` */
|
|
9
|
-
export const regex_not_whitespace = /[^ \t\r\n]/;
|
|
10
|
-
/** Not \s+ because that also includes explicit whitespace defined through things like ` ` */
|
|
11
|
-
export const regex_whitespaces_strict = /[ \t\n\r\f]+/g;
|
|
12
|
-
|
|
13
|
-
export const regex_only_whitespaces = /^[ \t\n\r\f]+$/;
|
|
14
|
-
|
|
15
|
-
export const regex_newline_characters = /\n/g;
|
|
16
|
-
export const regex_not_newline_characters = /[^\n]/g;
|
|
17
|
-
|
|
18
|
-
export const regex_is_valid_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
|
|
19
|
-
// used in replace all to remove all invalid chars from a literal identifier
|
|
20
|
-
export const regex_invalid_identifier_chars = /(^[^a-zA-Z_$]|[^a-zA-Z0-9_$])/g;
|
|
21
|
-
|
|
22
|
-
export const regex_starts_with_vowel = /^[aeiou]/;
|
|
23
|
-
export const regex_heading_tags = /^h[1-6]$/;
|
|
24
|
-
export const regex_illegal_attribute_character = /(^[0-9-.])|[\^$@%&#?!|()[\]{}^*+~;]/;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { compile } from '@tsrx/ripple';
|
|
3
|
-
|
|
4
|
-
describe('double-quoted text children', () => {
|
|
5
|
-
it('decodes JSX-style entities before server text escaping', () => {
|
|
6
|
-
const result = compile(
|
|
7
|
-
`component App() {
|
|
8
|
-
<div>"Rock & "Roll""</div>
|
|
9
|
-
}`,
|
|
10
|
-
'/src/App.tsrx',
|
|
11
|
-
{ mode: 'server' },
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
expect(result.js.code).toContain(`_$_.output_push('Rock & "Roll"')`);
|
|
15
|
-
});
|
|
16
|
-
});
|
|
@@ -1,104 +0,0 @@
|
|
|
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(
|
|
94
|
-
'<div class="foo & bar">',
|
|
95
|
-
);
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
describe('default parameter behavior', () => {
|
|
100
|
-
it('should default to content escaping when is_attr is undefined', () => {
|
|
101
|
-
expect(escape('foo "bar"')).toBe('foo "bar"');
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
});
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
/** @import { AddEventObject } from '#public'*/
|
|
2
|
-
|
|
3
|
-
import { describe, it, expect } from 'vitest';
|
|
4
|
-
import {
|
|
5
|
-
is_non_delegated,
|
|
6
|
-
is_event_attribute,
|
|
7
|
-
get_attribute_event_name,
|
|
8
|
-
is_passive_event,
|
|
9
|
-
is_capture_event,
|
|
10
|
-
} from '../../src/utils/events.js';
|
|
11
|
-
|
|
12
|
-
describe('events utility', () => {
|
|
13
|
-
describe('is event delegated', () => {
|
|
14
|
-
it('should confirm delegated events', () => {
|
|
15
|
-
expect(is_non_delegated('click')).toBe(false);
|
|
16
|
-
expect(is_non_delegated('input')).toBe(false);
|
|
17
|
-
expect(is_non_delegated('change')).toBe(false);
|
|
18
|
-
expect(is_non_delegated('mousedown')).toBe(false);
|
|
19
|
-
expect(is_non_delegated('keydown')).toBe(false);
|
|
20
|
-
expect(is_non_delegated('pointerdown')).toBe(false);
|
|
21
|
-
expect(is_non_delegated('touchstart')).toBe(false);
|
|
22
|
-
expect(is_non_delegated('focusin')).toBe(false);
|
|
23
|
-
expect(is_non_delegated('focusout')).toBe(false);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should confirm non-delegated events', () => {
|
|
27
|
-
expect(is_non_delegated('focus')).toBe(true);
|
|
28
|
-
expect(is_non_delegated('blur')).toBe(true);
|
|
29
|
-
expect(is_non_delegated('scroll')).toBe(true);
|
|
30
|
-
expect(is_non_delegated('load')).toBe(true);
|
|
31
|
-
expect(is_non_delegated('resize')).toBe(true);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should confirm that events with any capital letters are delegated', () => {
|
|
35
|
-
expect(is_non_delegated('Click')).toBe(false);
|
|
36
|
-
expect(is_non_delegated('CLICK')).toBe(false);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe('is_event_attribute', () => {
|
|
41
|
-
it('should return true for valid event attributes', () => {
|
|
42
|
-
expect(is_event_attribute('onClick')).toBe(true);
|
|
43
|
-
expect(is_event_attribute('onInput')).toBe(true);
|
|
44
|
-
expect(is_event_attribute('onChange')).toBe(true);
|
|
45
|
-
expect(is_event_attribute('onMouseDown')).toBe(true);
|
|
46
|
-
expect(is_event_attribute('onKeyPress')).toBe(true);
|
|
47
|
-
expect(is_event_attribute('on-click')).toBe(true);
|
|
48
|
-
expect(is_event_attribute('on_click')).toBe(true);
|
|
49
|
-
expect(is_event_attribute('on$click')).toBe(true);
|
|
50
|
-
expect(is_event_attribute('on$')).toBe(true);
|
|
51
|
-
expect(is_event_attribute('on-')).toBe(true);
|
|
52
|
-
expect(is_event_attribute('on_')).toBe(true);
|
|
53
|
-
expect(is_event_attribute('on1')).toBe(true);
|
|
54
|
-
expect(is_event_attribute('on1click')).toBe(true);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('should return false for non-event attributes', () => {
|
|
58
|
-
expect(is_event_attribute('on')).toBe(false);
|
|
59
|
-
expect(is_event_attribute('onclick')).toBe(false);
|
|
60
|
-
expect(is_event_attribute('class')).toBe(false);
|
|
61
|
-
expect(is_event_attribute('id')).toBe(false);
|
|
62
|
-
expect(is_event_attribute('value')).toBe(false);
|
|
63
|
-
expect(is_event_attribute('aria-label')).toBe(false);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should require uppercase third character', () => {
|
|
67
|
-
expect(is_event_attribute('onabc')).toBe(false);
|
|
68
|
-
expect(is_event_attribute('onAbc')).toBe(true);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should require at least 3 characters', () => {
|
|
72
|
-
expect(is_event_attribute('onA')).toBe(true);
|
|
73
|
-
expect(is_event_attribute('on')).toBe(false);
|
|
74
|
-
expect(is_event_attribute('o')).toBe(false);
|
|
75
|
-
expect(is_event_attribute('')).toBe(false);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
describe('get_attribute_event_name', () => {
|
|
80
|
-
it('should convert event attribute names to lowercase and strip "on" prefix', () => {
|
|
81
|
-
const fn = () => {};
|
|
82
|
-
expect(get_attribute_event_name('onClick', fn)).toBe('click');
|
|
83
|
-
expect(get_attribute_event_name('onInput', fn)).toBe('input');
|
|
84
|
-
expect(get_attribute_event_name('onMouseDown', fn)).toBe('mousedown');
|
|
85
|
-
expect(get_attribute_event_name('onKeyPress', fn)).toBe('keypress');
|
|
86
|
-
expect(get_attribute_event_name('onChange', fn)).toBe('change');
|
|
87
|
-
expect(get_attribute_event_name('onFocus', fn)).toBe('focus');
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('should keep event attribute names letter case and strip "on" prefix', () => {
|
|
91
|
-
/** @type AddEventObject */
|
|
92
|
-
const customHandler = { handleEvent: () => {} };
|
|
93
|
-
expect(get_attribute_event_name('onClick', { ...customHandler, customName: 'Click' })).toBe(
|
|
94
|
-
'Click',
|
|
95
|
-
);
|
|
96
|
-
expect(get_attribute_event_name('onInput', { ...customHandler, customName: 'Input' })).toBe(
|
|
97
|
-
'Input',
|
|
98
|
-
);
|
|
99
|
-
expect(
|
|
100
|
-
get_attribute_event_name('onMouseDown', { ...customHandler, customName: 'MouseDown' }),
|
|
101
|
-
).toBe('MouseDown');
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe('is_capture_event', () => {
|
|
106
|
-
it('should return true for capture events', () => {
|
|
107
|
-
expect(is_capture_event('clickCapture')).toBe(true);
|
|
108
|
-
expect(is_capture_event('mousedownCapture')).toBe(true);
|
|
109
|
-
expect(is_capture_event('keydownCapture')).toBe(true);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('should return false for non-capture events', () => {
|
|
113
|
-
expect(is_capture_event('click')).toBe(false);
|
|
114
|
-
expect(is_capture_event('mousedown')).toBe(false);
|
|
115
|
-
expect(is_capture_event('mousedown')).toBe(false);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should exclude gotpointercapture and lostpointercapture', () => {
|
|
119
|
-
expect(is_capture_event('gotpointercapture')).toBe(false);
|
|
120
|
-
expect(is_capture_event('lostpointercapture')).toBe(false);
|
|
121
|
-
expect(is_capture_event('gotPointerCapture')).toBe(false);
|
|
122
|
-
expect(is_capture_event('lostPointerCapture')).toBe(false);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should be case-insensitive for pointer capture events', () => {
|
|
126
|
-
expect(is_capture_event('GOTPOINTERCAPTURE')).toBe(false);
|
|
127
|
-
expect(is_capture_event('LOSTPOINTERCAPTURE')).toBe(false);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('should be case-sensitive for other events', () => {
|
|
131
|
-
expect(is_capture_event('clickCapture')).toBe(true);
|
|
132
|
-
expect(is_capture_event('keypressCapture')).toBe(true);
|
|
133
|
-
expect(is_capture_event('clickcapture')).toBe(false);
|
|
134
|
-
expect(is_capture_event('keypresscapture')).toBe(false);
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
describe('is_passive_event', () => {
|
|
139
|
-
it('should return true for passive events', () => {
|
|
140
|
-
expect(is_passive_event('touchstart')).toBe(true);
|
|
141
|
-
expect(is_passive_event('touchmove')).toBe(true);
|
|
142
|
-
expect(is_passive_event('wheel')).toBe(true);
|
|
143
|
-
expect(is_passive_event('mousewheel')).toBe(true);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should return false for non-passive events', () => {
|
|
147
|
-
expect(is_passive_event('click')).toBe(false);
|
|
148
|
-
expect(is_passive_event('mousedown')).toBe(false);
|
|
149
|
-
expect(is_passive_event('touchend')).toBe(false);
|
|
150
|
-
expect(is_passive_event('scroll')).toBe(false);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('should be case-sensitive', () => {
|
|
154
|
-
expect(is_passive_event('TouchStart')).toBe(false);
|
|
155
|
-
expect(is_passive_event('TOUCHMOVE')).toBe(false);
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
});
|
|
@@ -1,42 +0,0 @@
|
|
|
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
|
-
});
|