@whenessel/seql-js 1.4.0 → 1.6.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.
- package/README.md +25 -0
- package/dist/seql-js.d.ts +116 -6
- package/dist/seql-js.js +797 -548
- package/dist/seql-js.js.map +1 -1
- package/dist/seql-js.umd.cjs +10 -1
- package/dist/seql-js.umd.cjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -146,6 +146,30 @@ Manage the LRU cache to improve performance for frequent generations/resolutions
|
|
|
146
146
|
- `src/resolver/`: Logic for resolving EID JSON back to DOM elements.
|
|
147
147
|
- `src/types/`: Core type definitions for EIDs, Semantics, and Constraints.
|
|
148
148
|
- `src/utils/`: Shared utilities, constants, and scoring algorithms.
|
|
149
|
+
- `extensions/chrome/`: Chrome DevTools extension for visual SEQL inspection.
|
|
150
|
+
|
|
151
|
+
## Developer Tools
|
|
152
|
+
|
|
153
|
+
### Chrome DevTools Extension
|
|
154
|
+
|
|
155
|
+
The SEQL Inspector extension provides visual tooling for working with SEQL selectors directly in Chrome DevTools.
|
|
156
|
+
|
|
157
|
+
**Features:**
|
|
158
|
+
|
|
159
|
+
- Generate SEQL selectors for all elements or pick individual elements
|
|
160
|
+
- Full iframe support with automatic detection and context switching
|
|
161
|
+
- Live search and resolution testing
|
|
162
|
+
- Interactive element highlighting and inspection
|
|
163
|
+
- Tree view with grouping and filtering
|
|
164
|
+
|
|
165
|
+
**Installation:**
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
yarn extension:prepare
|
|
169
|
+
# Then load extensions/chrome/ as unpacked extension in Chrome
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
See [Chrome Extension README](extensions/chrome/README.md) for detailed documentation.
|
|
149
173
|
|
|
150
174
|
## Scripts
|
|
151
175
|
|
|
@@ -154,6 +178,7 @@ Manage the LRU cache to improve performance for frequent generations/resolutions
|
|
|
154
178
|
- `yarn test:watch`: Run tests in watch mode.
|
|
155
179
|
- `yarn test:coverage`: Run tests with coverage report.
|
|
156
180
|
- `yarn types:check`: Run TypeScript type checking.
|
|
181
|
+
- `yarn extension:prepare`: Build library and prepare Chrome extension.
|
|
157
182
|
- `npx vitest <path>`: Run a specific test file.
|
|
158
183
|
|
|
159
184
|
## Documentation
|
package/dist/seql-js.d.ts
CHANGED
|
@@ -452,12 +452,12 @@ export declare class CssGenerator {
|
|
|
452
452
|
* div with utility classes) can still be identified using positional information
|
|
453
453
|
* (nthChild).
|
|
454
454
|
*/
|
|
455
|
-
export declare const DEFAULT_GENERATOR_OPTIONS: Omit<Required<GeneratorOptions>, 'cache'> & Pick<GeneratorOptions, 'cache'>;
|
|
455
|
+
export declare const DEFAULT_GENERATOR_OPTIONS: Omit<Required<GeneratorOptions>, 'cache' | 'root'> & Pick<GeneratorOptions, 'cache' | 'root'>;
|
|
456
456
|
|
|
457
457
|
/**
|
|
458
458
|
* Default resolver options
|
|
459
459
|
*/
|
|
460
|
-
export declare const DEFAULT_RESOLVER_OPTIONS: Required<ResolverOptions>;
|
|
460
|
+
export declare const DEFAULT_RESOLVER_OPTIONS: Omit<Required<ResolverOptions>, 'root' | 'documentUrl'> & Pick<ResolverOptions, 'root' | 'documentUrl'>;
|
|
461
461
|
|
|
462
462
|
/**
|
|
463
463
|
* EID specification version
|
|
@@ -744,6 +744,21 @@ export declare interface GeneratorOptions {
|
|
|
744
744
|
source?: string;
|
|
745
745
|
/** Optional cache instance for performance optimization */
|
|
746
746
|
cache?: EIDCache;
|
|
747
|
+
/**
|
|
748
|
+
* Root element or document for validation (optional).
|
|
749
|
+
*
|
|
750
|
+
* ⚠️ IMPORTANT: When working with iframes, pass iframe.contentDocument
|
|
751
|
+
* to ensure cross-document validation works correctly.
|
|
752
|
+
*
|
|
753
|
+
* @example
|
|
754
|
+
* // Main document
|
|
755
|
+
* generateEID(element, { root: document });
|
|
756
|
+
*
|
|
757
|
+
* // Iframe content
|
|
758
|
+
* const iframe = document.querySelector('iframe');
|
|
759
|
+
* generateEID(iframeElement, { root: iframe.contentDocument });
|
|
760
|
+
*/
|
|
761
|
+
root?: Document | Element;
|
|
747
762
|
}
|
|
748
763
|
|
|
749
764
|
/**
|
|
@@ -948,7 +963,7 @@ export declare interface ResolveResult {
|
|
|
948
963
|
/** Metadata about resolution */
|
|
949
964
|
meta: {
|
|
950
965
|
degraded: boolean;
|
|
951
|
-
degradationReason?:
|
|
966
|
+
degradationReason?: 'not-found' | 'strict-not-found' | 'ambiguous' | 'anchor-fallback' | 'anchor-not-found' | 'first-of-multiple' | 'best-of-multiple' | 'multiple-matches' | 'over-constrained' | 'relaxed-text-matching' | 'invalid-context' | 'invalid-selector' | 'invalid-anchor-selector';
|
|
952
967
|
};
|
|
953
968
|
}
|
|
954
969
|
|
|
@@ -963,6 +978,63 @@ export declare interface ResolverOptions {
|
|
|
963
978
|
enableFallback?: boolean;
|
|
964
979
|
/** Maximum candidates to consider (default: 20) */
|
|
965
980
|
maxCandidates?: number;
|
|
981
|
+
/**
|
|
982
|
+
* Root element or document for CSS queries.
|
|
983
|
+
*
|
|
984
|
+
* ⚠️ IMPORTANT: When working with iframes, you MUST pass iframe.contentDocument
|
|
985
|
+
* as the root parameter. Otherwise, resolution will fail or return incorrect elements.
|
|
986
|
+
*
|
|
987
|
+
* @example
|
|
988
|
+
* // Main document
|
|
989
|
+
* resolve(eid, document, { root: document });
|
|
990
|
+
*
|
|
991
|
+
* // Iframe content
|
|
992
|
+
* const iframe = document.querySelector('iframe');
|
|
993
|
+
* resolve(eid, iframe.contentDocument, { root: iframe.contentDocument });
|
|
994
|
+
*/
|
|
995
|
+
root?: Document | Element;
|
|
996
|
+
/**
|
|
997
|
+
* Document base URL for URL normalization.
|
|
998
|
+
* Used when comparing href/src attributes to provide correct origin context.
|
|
999
|
+
*
|
|
1000
|
+
* ⚠️ IMPORTANT: When working with iframes, this should match iframe.contentWindow.location.href
|
|
1001
|
+
* to ensure correct same-origin detection.
|
|
1002
|
+
*
|
|
1003
|
+
* If not provided, falls back to root.defaultView?.location?.href or window.location.href.
|
|
1004
|
+
*
|
|
1005
|
+
* @example
|
|
1006
|
+
* // Iframe context
|
|
1007
|
+
* const iframe = document.querySelector('iframe');
|
|
1008
|
+
* resolve(eid, iframe.contentDocument, {
|
|
1009
|
+
* root: iframe.contentDocument,
|
|
1010
|
+
* documentUrl: iframe.contentWindow.location.href
|
|
1011
|
+
* });
|
|
1012
|
+
*
|
|
1013
|
+
* @example
|
|
1014
|
+
* // Manual override for testing
|
|
1015
|
+
* resolve(eid, document, {
|
|
1016
|
+
* documentUrl: 'https://example.com'
|
|
1017
|
+
* });
|
|
1018
|
+
*/
|
|
1019
|
+
documentUrl?: string;
|
|
1020
|
+
/**
|
|
1021
|
+
* Match URLs by pathname only, ignoring origin differences.
|
|
1022
|
+
* Useful for cross-origin rrweb replay scenarios (e.g., localhost dev with production links).
|
|
1023
|
+
*
|
|
1024
|
+
* When enabled (default):
|
|
1025
|
+
* - /booking matches https://any-origin.com/booking
|
|
1026
|
+
* - Ignores protocol and domain differences
|
|
1027
|
+
* - Compares only pathname (+ search + hash if present)
|
|
1028
|
+
* - Recommended for rrweb replay and development environments
|
|
1029
|
+
*
|
|
1030
|
+
* When disabled:
|
|
1031
|
+
* - Full URL normalization with same-origin detection
|
|
1032
|
+
* - Cross-origin URLs preserved as absolute
|
|
1033
|
+
* - More strict origin validation
|
|
1034
|
+
*
|
|
1035
|
+
* @default true
|
|
1036
|
+
*/
|
|
1037
|
+
matchUrlsByPathOnly?: boolean;
|
|
966
1038
|
}
|
|
967
1039
|
|
|
968
1040
|
/**
|
|
@@ -985,6 +1057,21 @@ export declare interface ResolverOptions {
|
|
|
985
1057
|
* highlightElement(elements[0]);
|
|
986
1058
|
* }
|
|
987
1059
|
* ```
|
|
1060
|
+
*
|
|
1061
|
+
* @example
|
|
1062
|
+
* ```typescript
|
|
1063
|
+
* // Working with iframes - pass iframe.contentDocument as both root and in options
|
|
1064
|
+
* const iframe = document.querySelector('iframe');
|
|
1065
|
+
* const iframeDoc = iframe.contentDocument;
|
|
1066
|
+
* const selector = "v1: form#payment :: input[name=cardnumber]";
|
|
1067
|
+
*
|
|
1068
|
+
* // IMPORTANT: Pass contentDocument as root in options for correct resolution
|
|
1069
|
+
* const elements = resolveSEQL(selector, iframeDoc, { root: iframeDoc });
|
|
1070
|
+
*
|
|
1071
|
+
* if (elements.length > 0) {
|
|
1072
|
+
* console.log('Found payment input in iframe:', elements[0]);
|
|
1073
|
+
* }
|
|
1074
|
+
* ```
|
|
988
1075
|
*/
|
|
989
1076
|
export declare function resolveSEQL(selector: string, root: Document | Element, options?: ResolverOptions): Element[];
|
|
990
1077
|
|
|
@@ -1083,11 +1170,15 @@ export declare class SemanticsMatcher {
|
|
|
1083
1170
|
* Filters elements that match the semantics
|
|
1084
1171
|
* @param elements - Candidate elements
|
|
1085
1172
|
* @param semantics - Target semantics to match
|
|
1173
|
+
* @param documentUrl - Optional document base URL for URL normalization (iframe context)
|
|
1174
|
+
* @param matchUrlsByPathOnly - Optional flag to match URLs by pathname only (ignoring origin)
|
|
1086
1175
|
* @returns Filtered elements that match
|
|
1087
1176
|
*/
|
|
1088
|
-
match(elements: Element[], semantics: ElementSemantics): Element[];
|
|
1177
|
+
match(elements: Element[], semantics: ElementSemantics, documentUrl?: string, matchUrlsByPathOnly?: boolean): Element[];
|
|
1089
1178
|
/**
|
|
1090
1179
|
* Checks if a single element matches the semantics
|
|
1180
|
+
* @param documentUrl - Optional document base URL for URL normalization (iframe context)
|
|
1181
|
+
* @param matchUrlsByPathOnly - Optional flag to match URLs by pathname only (ignoring origin)
|
|
1091
1182
|
*/
|
|
1092
1183
|
private matchElement;
|
|
1093
1184
|
/**
|
|
@@ -1096,9 +1187,28 @@ export declare class SemanticsMatcher {
|
|
|
1096
1187
|
*/
|
|
1097
1188
|
matchText(element: Element, text: TextContent): boolean;
|
|
1098
1189
|
/**
|
|
1099
|
-
*
|
|
1190
|
+
* Lenient text matching - uses partial matching instead of exact
|
|
1191
|
+
* Used as fallback when exact matching fails
|
|
1192
|
+
*/
|
|
1193
|
+
private matchTextLenient;
|
|
1194
|
+
/**
|
|
1195
|
+
* Checks if a single element matches the semantics with lenient text matching
|
|
1196
|
+
* @param documentUrl - Optional document base URL for URL normalization (iframe context)
|
|
1197
|
+
* @param matchUrlsByPathOnly - Optional flag to match URLs by pathname only (ignoring origin)
|
|
1198
|
+
*/
|
|
1199
|
+
private matchElementLenient;
|
|
1200
|
+
/**
|
|
1201
|
+
* Filters elements with lenient matching (exported for use in resolver)
|
|
1202
|
+
* @param documentUrl - Optional document base URL for URL normalization (iframe context)
|
|
1203
|
+
* @param matchUrlsByPathOnly - Optional flag to match URLs by pathname only (ignoring origin)
|
|
1204
|
+
*/
|
|
1205
|
+
matchLenient(elements: Element[], semantics: ElementSemantics, documentUrl?: string, matchUrlsByPathOnly?: boolean): Element[];
|
|
1206
|
+
/**
|
|
1207
|
+
* Matches attributes with URL normalization for href/src
|
|
1208
|
+
* @param documentUrl - Optional document base URL for URL normalization (iframe context)
|
|
1209
|
+
* @param matchUrlsByPathOnly - Optional flag to match URLs by pathname only (ignoring origin, default: true)
|
|
1100
1210
|
*/
|
|
1101
|
-
matchAttributes(element: Element, attrs: Record<string, string
|
|
1211
|
+
matchAttributes(element: Element, attrs: Record<string, string>, documentUrl?: string, matchUrlsByPathOnly?: boolean): boolean;
|
|
1102
1212
|
/**
|
|
1103
1213
|
* Matches SVG fingerprint
|
|
1104
1214
|
*/
|