@tsrx/core 0.0.1
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 +52 -0
- package/src/analyze/css-analyze.js +160 -0
- package/src/analyze/validation.js +167 -0
- package/src/comment-utils.js +91 -0
- package/src/constants.js +21 -0
- package/src/errors.js +82 -0
- package/src/helpers.d.ts +11 -0
- package/src/identifier-utils.js +80 -0
- package/src/index.js +141 -0
- package/src/parse/index.js +772 -0
- package/src/parse/style.js +704 -0
- package/src/scope.js +476 -0
- package/src/source-map-utils.js +358 -0
- package/src/transform/segments.js +2140 -0
- package/src/transform/stylesheet.js +545 -0
- package/src/utils/ast.js +273 -0
- package/src/utils/builders.js +1287 -0
- package/src/utils/escaping.js +26 -0
- package/src/utils/events.js +154 -0
- package/src/utils/hashing.js +15 -0
- package/src/utils/normalize_css_property_name.js +23 -0
- package/src/utils/patterns.js +24 -0
- package/src/utils/sanitize_template_string.js +7 -0
- package/src/utils.js +165 -0
- package/types/acorn.d.ts +3 -0
- package/types/estree-jsx.d.ts +3 -0
- package/types/estree.d.ts +3 -0
- package/types/index.d.ts +1550 -0
- package/types/parse.d.ts +1722 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const ATTR_REGEX = /[&"<]/g;
|
|
2
|
+
const CONTENT_REGEX = /[&<]/g;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @template V
|
|
6
|
+
* @param {V} value
|
|
7
|
+
* @param {boolean} [is_attr]
|
|
8
|
+
*/
|
|
9
|
+
export function escape(value, is_attr) {
|
|
10
|
+
const str = String(value ?? '');
|
|
11
|
+
|
|
12
|
+
const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX;
|
|
13
|
+
pattern.lastIndex = 0;
|
|
14
|
+
|
|
15
|
+
let escaped = '';
|
|
16
|
+
let last = 0;
|
|
17
|
+
|
|
18
|
+
while (pattern.test(str)) {
|
|
19
|
+
const i = pattern.lastIndex - 1;
|
|
20
|
+
const ch = str[i];
|
|
21
|
+
escaped += str.substring(last, i) + (ch === '&' ? '&' : ch === '"' ? '"' : '<');
|
|
22
|
+
last = i + 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return escaped + str.substring(last);
|
|
26
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/** @import { AddEventObject } from '../../types/index'*/
|
|
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
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const regex_return_characters = /\r/g;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hashes a string to a base36 value
|
|
5
|
+
* @param {string} str
|
|
6
|
+
* @returns {string}
|
|
7
|
+
*/
|
|
8
|
+
export function hash(str) {
|
|
9
|
+
str = str.replace(regex_return_characters, '');
|
|
10
|
+
let hash = 5381;
|
|
11
|
+
let i = str.length;
|
|
12
|
+
|
|
13
|
+
while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
|
|
14
|
+
return (hash >>> 0).toString(36);
|
|
15
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
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-.])|[\^$@%&#?!|()[\]{}^*+~;]/;
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic compiler utilities for tsrx-based frameworks.
|
|
3
|
+
* Framework-specific utilities should be in the framework package.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { hash } from './utils/hashing.js';
|
|
7
|
+
|
|
8
|
+
const VOID_ELEMENT_NAMES = [
|
|
9
|
+
'area',
|
|
10
|
+
'base',
|
|
11
|
+
'br',
|
|
12
|
+
'col',
|
|
13
|
+
'command',
|
|
14
|
+
'embed',
|
|
15
|
+
'hr',
|
|
16
|
+
'img',
|
|
17
|
+
'input',
|
|
18
|
+
'keygen',
|
|
19
|
+
'link',
|
|
20
|
+
'meta',
|
|
21
|
+
'param',
|
|
22
|
+
'source',
|
|
23
|
+
'track',
|
|
24
|
+
'wbr',
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Returns true if name is a void element
|
|
29
|
+
* @param {string} name
|
|
30
|
+
* @returns {boolean}
|
|
31
|
+
*/
|
|
32
|
+
export function is_void_element(name) {
|
|
33
|
+
return VOID_ELEMENT_NAMES.includes(name) || name.toLowerCase() === '!doctype';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const RESERVED_WORDS = [
|
|
37
|
+
'arguments',
|
|
38
|
+
'await',
|
|
39
|
+
'break',
|
|
40
|
+
'case',
|
|
41
|
+
'catch',
|
|
42
|
+
'class',
|
|
43
|
+
'const',
|
|
44
|
+
'continue',
|
|
45
|
+
'debugger',
|
|
46
|
+
'default',
|
|
47
|
+
'delete',
|
|
48
|
+
'do',
|
|
49
|
+
'else',
|
|
50
|
+
'enum',
|
|
51
|
+
'eval',
|
|
52
|
+
'export',
|
|
53
|
+
'extends',
|
|
54
|
+
'false',
|
|
55
|
+
'finally',
|
|
56
|
+
'for',
|
|
57
|
+
'function',
|
|
58
|
+
'if',
|
|
59
|
+
'implements',
|
|
60
|
+
'import',
|
|
61
|
+
'in',
|
|
62
|
+
'instanceof',
|
|
63
|
+
'interface',
|
|
64
|
+
'let',
|
|
65
|
+
'new',
|
|
66
|
+
'null',
|
|
67
|
+
'package',
|
|
68
|
+
'private',
|
|
69
|
+
'protected',
|
|
70
|
+
'public',
|
|
71
|
+
'return',
|
|
72
|
+
'static',
|
|
73
|
+
'super',
|
|
74
|
+
'switch',
|
|
75
|
+
'this',
|
|
76
|
+
'throw',
|
|
77
|
+
'true',
|
|
78
|
+
'try',
|
|
79
|
+
'typeof',
|
|
80
|
+
'var',
|
|
81
|
+
'void',
|
|
82
|
+
'while',
|
|
83
|
+
'with',
|
|
84
|
+
'yield',
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Returns true if word is a reserved JS keyword
|
|
89
|
+
* @param {string} word
|
|
90
|
+
* @returns {boolean}
|
|
91
|
+
*/
|
|
92
|
+
export function is_reserved(word) {
|
|
93
|
+
return RESERVED_WORDS.includes(word);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Attributes that are boolean, i.e. they are present or not present.
|
|
98
|
+
*/
|
|
99
|
+
const DOM_BOOLEAN_ATTRIBUTES = [
|
|
100
|
+
'allowfullscreen',
|
|
101
|
+
'async',
|
|
102
|
+
'autofocus',
|
|
103
|
+
'autoplay',
|
|
104
|
+
'checked',
|
|
105
|
+
'controls',
|
|
106
|
+
'default',
|
|
107
|
+
'disabled',
|
|
108
|
+
'formnovalidate',
|
|
109
|
+
'hidden',
|
|
110
|
+
'indeterminate',
|
|
111
|
+
'inert',
|
|
112
|
+
'ismap',
|
|
113
|
+
'loop',
|
|
114
|
+
'multiple',
|
|
115
|
+
'muted',
|
|
116
|
+
'nomodule',
|
|
117
|
+
'novalidate',
|
|
118
|
+
'open',
|
|
119
|
+
'playsinline',
|
|
120
|
+
'readonly',
|
|
121
|
+
'required',
|
|
122
|
+
'reversed',
|
|
123
|
+
'seamless',
|
|
124
|
+
'selected',
|
|
125
|
+
'webkitdirectory',
|
|
126
|
+
'defer',
|
|
127
|
+
'disablepictureinpicture',
|
|
128
|
+
'disableremoteplayback',
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Returns true if name is a boolean DOM attribute
|
|
133
|
+
* @param {string} name
|
|
134
|
+
* @returns {boolean}
|
|
135
|
+
*/
|
|
136
|
+
export function is_boolean_attribute(name) {
|
|
137
|
+
return DOM_BOOLEAN_ATTRIBUTES.includes(name);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const DOM_PROPERTIES = [
|
|
141
|
+
...DOM_BOOLEAN_ATTRIBUTES,
|
|
142
|
+
'formNoValidate',
|
|
143
|
+
'isMap',
|
|
144
|
+
'noModule',
|
|
145
|
+
'playsInline',
|
|
146
|
+
'readOnly',
|
|
147
|
+
'value',
|
|
148
|
+
'volume',
|
|
149
|
+
'defaultValue',
|
|
150
|
+
'defaultChecked',
|
|
151
|
+
'srcObject',
|
|
152
|
+
'noValidate',
|
|
153
|
+
'allowFullscreen',
|
|
154
|
+
'disablePictureInPicture',
|
|
155
|
+
'disableRemotePlayback',
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Returns true if name is a DOM property
|
|
160
|
+
* @param {string} name
|
|
161
|
+
* @returns {boolean}
|
|
162
|
+
*/
|
|
163
|
+
export function is_dom_property(name) {
|
|
164
|
+
return DOM_PROPERTIES.includes(name);
|
|
165
|
+
}
|
package/types/acorn.d.ts
ADDED