@guidelytech/guide-runtime 0.5.0 → 0.6.2
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/dist/capture.cjs +1336 -0
- package/dist/capture.cjs.map +1 -0
- package/dist/capture.d.cts +184 -0
- package/dist/capture.d.ts +184 -0
- package/dist/capture.js +857 -0
- package/dist/capture.js.map +1 -0
- package/dist/{chunk-SLBUGXNH.js → chunk-4FKYF6OB.js} +196 -23
- package/dist/chunk-4FKYF6OB.js.map +1 -0
- package/dist/{chunk-SGFC66YD.js → chunk-4UW6YF44.js} +150 -8
- package/dist/chunk-4UW6YF44.js.map +1 -0
- package/dist/chunk-7DOGZKWD.js +322 -0
- package/dist/chunk-7DOGZKWD.js.map +1 -0
- package/dist/chunk-GUSKGNNR.js +301 -0
- package/dist/chunk-GUSKGNNR.js.map +1 -0
- package/dist/index.cjs +192 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +29 -561
- package/dist/index.js.map +1 -1
- package/dist/messenger.cjs +825 -57
- package/dist/messenger.cjs.map +1 -1
- package/dist/messenger.d.cts +61 -3
- package/dist/messenger.d.ts +61 -3
- package/dist/messenger.js +662 -45
- package/dist/messenger.js.map +1 -1
- package/package.json +7 -2
- package/dist/chunk-SGFC66YD.js.map +0 -1
- package/dist/chunk-SLBUGXNH.js.map +0 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { CapturedElement, NormalizedRect, CaptureStepInput } from '@guidelytech/shared';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pure DOM helpers for how-to capture: which element an interaction is about, how to name it for
|
|
5
|
+
* people, which fields and on-screen text are sensitive, and where things sit in a screenshot.
|
|
6
|
+
*/
|
|
7
|
+
/** Elements a click is "about" when it lands on them or inside them. */
|
|
8
|
+
declare const CAPTURE_INTERACTIVE_SELECTOR = "a,button,input,select,textarea,label,summary,[role=button],[role=link],[role=tab],[role=menuitem],[role=menuitemcheckbox],[role=menuitemradio],[role=option],[role=checkbox],[role=radio],[role=switch],[role=combobox],[contenteditable]:not([contenteditable=false])";
|
|
9
|
+
/** Always-redacted elements (on top of the project's mask selectors). */
|
|
10
|
+
declare const REDACT_SELECTOR = "[data-guidely-redact]";
|
|
11
|
+
/** Fields whose typed text becomes a `type` step (instead of a click). */
|
|
12
|
+
declare function isTextEntry(el: Element): boolean;
|
|
13
|
+
/** The element a pointer interaction is about: the closest interactive ancestor, else the target itself. */
|
|
14
|
+
declare function actionTarget(target: Element): Element;
|
|
15
|
+
/** The control a `<label>` is for (clicking the label acts on it), if any. */
|
|
16
|
+
declare function labelControl(el: Element): Element | null;
|
|
17
|
+
/** Is the element (or an ancestor) covered by the mask selectors or `[data-guidely-redact]`? */
|
|
18
|
+
declare function isMaskedElement(el: Element, maskSelector: string): boolean;
|
|
19
|
+
/** Fields whose value is never recorded and whose pixels are redacted from screenshots. */
|
|
20
|
+
declare function isSensitiveField(el: Element, maskSelector?: string): boolean;
|
|
21
|
+
type SensitiveNumberKind = "card" | "ssn" | "phone";
|
|
22
|
+
/**
|
|
23
|
+
* Classifies a number run: card (13–19 digits in groups of 4+), US SSN (3-2-4) or phone
|
|
24
|
+
* (10–13 digits written with a country code, area-code parentheses or 3+ groups ending in 4 digits).
|
|
25
|
+
* Dates, times, prices, versions and IP addresses do not match.
|
|
26
|
+
*/
|
|
27
|
+
declare function classifyNumber(run: string): SensitiveNumberKind | null;
|
|
28
|
+
/** Character ranges `[start, end)` of emails, card numbers, SSNs and phone numbers in `text`. */
|
|
29
|
+
declare function findSensitiveText(text: string): Array<[number, number]>;
|
|
30
|
+
/** Typed values are recorded verbatim unless they contain something like a card number or SSN. */
|
|
31
|
+
declare function looksLikeSecretValue(value: string): boolean;
|
|
32
|
+
/** Normalised role: button, link, tab, menuitem, checkbox, radio, switch, field, dropdown, option or element. */
|
|
33
|
+
declare function captureRole(el: Element): string;
|
|
34
|
+
/**
|
|
35
|
+
* Visible name of an element for people: aria-label, aria-labelledby, its `<label>`, its text
|
|
36
|
+
* (not for fields, whose value is user data), placeholder, alt, title or name. Max 80 characters.
|
|
37
|
+
*/
|
|
38
|
+
declare function captureLabel(el: Element): string;
|
|
39
|
+
/** People-facing description of the element; masked elements get no label (never their text). */
|
|
40
|
+
declare function describeCapturedElement(el: Element, maskSelector?: string): CapturedElement;
|
|
41
|
+
/** The value a `type` step records: trimmed, at most 200 characters. */
|
|
42
|
+
declare function fieldValue(el: Element): string;
|
|
43
|
+
/** Text of the selected option(s) of a `<select>`. */
|
|
44
|
+
declare function selectedOptionText(el: HTMLSelectElement): string;
|
|
45
|
+
interface Box {
|
|
46
|
+
x: number;
|
|
47
|
+
y: number;
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Maps a viewport rect (CSS px) to fractions of a screenshot of that viewport, padded by `pad`
|
|
53
|
+
* CSS px and clamped to the frame. Returns null when nothing of it is on screen.
|
|
54
|
+
*/
|
|
55
|
+
declare function normalizeRect(rect: Box, viewport: {
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
}, pad?: number): NormalizedRect | null;
|
|
59
|
+
/** Scales a viewport rect (CSS px) to frame pixels, clipped to the frame. */
|
|
60
|
+
declare function toFrameRect(rect: Box, scaleX: number, scaleY: number, frame: {
|
|
61
|
+
width: number;
|
|
62
|
+
height: number;
|
|
63
|
+
}, pad?: number): Box | null;
|
|
64
|
+
interface RedactionOptions {
|
|
65
|
+
maskSelector?: string;
|
|
66
|
+
/** Stop after this many text nodes (keeps the synchronous scan cheap on huge pages). */
|
|
67
|
+
maxTextNodes?: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Viewport rects (CSS px) to blur in a screenshot: password and other sensitive fields, masked and
|
|
71
|
+
* `[data-guidely-redact]` elements, field values and visible text that look like emails, card
|
|
72
|
+
* numbers, SSNs or phone numbers. Runs synchronously so it matches the frame grabbed with it.
|
|
73
|
+
*/
|
|
74
|
+
declare function collectRedactions(doc: Document, options?: RedactionOptions): Box[];
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Screenshots for how-to capture: a tab-capture stream (`getDisplayMedia`) played into a hidden
|
|
78
|
+
* video, frames grabbed synchronously into a canvas, sensitive regions blurred into the pixels and
|
|
79
|
+
* the result encoded — all in the browser, so raw pixels of redacted regions never leave it.
|
|
80
|
+
*/
|
|
81
|
+
type ScreenResult = {
|
|
82
|
+
ok: true;
|
|
83
|
+
screen: ScreenSource;
|
|
84
|
+
} | {
|
|
85
|
+
ok: false;
|
|
86
|
+
reason: "unsupported" | "denied" | "wrong-surface" | "error";
|
|
87
|
+
};
|
|
88
|
+
interface ScreenSource {
|
|
89
|
+
/** True while the stream delivers frames. */
|
|
90
|
+
live(): boolean;
|
|
91
|
+
/** Called once when the user stops sharing (or the stream ends otherwise). */
|
|
92
|
+
onEnded(cb: () => void): void;
|
|
93
|
+
/** Draws the current frame into a new canvas (synchronously). Null when no frame is available. */
|
|
94
|
+
grab(): HTMLCanvasElement | null;
|
|
95
|
+
/** Does the current frame show the page as it is after `changedAt` (a `performance.now()` time)? */
|
|
96
|
+
freshSince(changedAt: number): boolean;
|
|
97
|
+
/** Resolves when the next frame arrives (or after `timeoutMs`). */
|
|
98
|
+
nextFrame(timeoutMs?: number): Promise<void>;
|
|
99
|
+
stop(): void;
|
|
100
|
+
}
|
|
101
|
+
/** Can this browser capture the tab at all? */
|
|
102
|
+
declare function canCaptureScreen(): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Asks the user to share this tab (must run from a user gesture) and plays the stream into a
|
|
105
|
+
* hidden `<video>` appended to `container`. Rejects windows and screens: their frames do not
|
|
106
|
+
* match the page's viewport, so highlights and redactions would land in the wrong place.
|
|
107
|
+
*/
|
|
108
|
+
declare function requestTabCapture(container: Node, doc?: Document): Promise<ScreenResult>;
|
|
109
|
+
/** Copies the video's current frame into a new canvas. */
|
|
110
|
+
declare function grabFrame(video: HTMLVideoElement, doc?: Document): HTMLCanvasElement | null;
|
|
111
|
+
/**
|
|
112
|
+
* Blurs viewport rects (CSS px) into the canvas by averaging each region down to a few samples per
|
|
113
|
+
* line of text and scaling it back up, which leaves nothing legible to recover. Returns the number
|
|
114
|
+
* of regions blurred.
|
|
115
|
+
*/
|
|
116
|
+
declare function redactCanvas(canvas: HTMLCanvasElement, rects: Box[], viewport: {
|
|
117
|
+
width: number;
|
|
118
|
+
height: number;
|
|
119
|
+
}): number;
|
|
120
|
+
/** Encodes as WebP (JPEG where WebP encoding is unsupported), at most `maxWidth` wide and `maxBytes` big. */
|
|
121
|
+
declare function encodeScreenshot(canvas: HTMLCanvasElement, options?: {
|
|
122
|
+
maxWidth?: number;
|
|
123
|
+
maxBytes?: number;
|
|
124
|
+
}): Promise<Blob | null>;
|
|
125
|
+
/** Synchronous JPEG data URL (≤ 1600 px wide), for persisting an unsent screenshot while the page unloads. */
|
|
126
|
+
declare function screenshotDataUrl(canvas: HTMLCanvasElement): string | null;
|
|
127
|
+
|
|
128
|
+
/** A captured step before the SDK gives it a `clientId`. */
|
|
129
|
+
type CaptureStepDraft = Omit<CaptureStepInput, "clientId">;
|
|
130
|
+
interface CapturedStep {
|
|
131
|
+
step: CaptureStepDraft;
|
|
132
|
+
/**
|
|
133
|
+
* The screenshot, already redacted (encode it with `encodeScreenshot`); null without screenshots.
|
|
134
|
+
* A promise when the current frame predates a scroll or resize: it resolves with the next frame,
|
|
135
|
+
* after `step.highlight` and `step.redactions` were updated to match it.
|
|
136
|
+
*/
|
|
137
|
+
frame: HTMLCanvasElement | Promise<HTMLCanvasElement | null> | null;
|
|
138
|
+
}
|
|
139
|
+
interface CaptureOptions {
|
|
140
|
+
/** How-to title shown in the toolbar before recording starts. */
|
|
141
|
+
title: string;
|
|
142
|
+
/** Steps already recorded (a recording continues across full page loads). */
|
|
143
|
+
stepCount?: number;
|
|
144
|
+
/** False when the server cannot store screenshots: record steps only. Default true. */
|
|
145
|
+
screenshots?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Continue a recording after a full page load: start recording straight away. `navigate` adds a
|
|
148
|
+
* step for the new page; `screenshots` offers "Screenshots paused — Resume" (the stream is gone).
|
|
149
|
+
*/
|
|
150
|
+
resume?: {
|
|
151
|
+
navigate: boolean;
|
|
152
|
+
screenshots: boolean;
|
|
153
|
+
};
|
|
154
|
+
/** Comma-joined CSS selectors whose text and pixels are never captured. */
|
|
155
|
+
maskSelector?: string;
|
|
156
|
+
onStep(step: CapturedStep): void;
|
|
157
|
+
/** Recording started; `screenshots` is whether the user chose to take screenshots. */
|
|
158
|
+
onStart?(info: {
|
|
159
|
+
screenshots: boolean;
|
|
160
|
+
}): void;
|
|
161
|
+
onFinish(): void;
|
|
162
|
+
onCancel(): void;
|
|
163
|
+
doc?: Document;
|
|
164
|
+
}
|
|
165
|
+
interface CaptureSession {
|
|
166
|
+
/** Shows "Saving…" (and stops recording) while queued uploads finish. */
|
|
167
|
+
setSaving(saving: boolean): void;
|
|
168
|
+
isRecording(): boolean;
|
|
169
|
+
stop(): void;
|
|
170
|
+
}
|
|
171
|
+
/** A repeat press on the same element within this window is a double click, not a new step. */
|
|
172
|
+
declare const DOUBLE_CLICK_MS = 400;
|
|
173
|
+
/** URL changes this soon after an interaction were caused by it (no separate navigate step). */
|
|
174
|
+
declare const NAV_AFTER_ACTION_MS = 1500;
|
|
175
|
+
/** Wait for the page to settle before capturing a navigate step. */
|
|
176
|
+
declare const NAV_SETTLE_MS = 600;
|
|
177
|
+
/**
|
|
178
|
+
* Starts how-to capture: a Shadow-DOM toolbar (bottom centre, a small pill while recording) and passive capture-phase
|
|
179
|
+
* listeners that turn clicks, typing, selections and navigations into steps. The app keeps
|
|
180
|
+
* receiving every event; nothing is prevented.
|
|
181
|
+
*/
|
|
182
|
+
declare function startCapture(options: CaptureOptions): CaptureSession;
|
|
183
|
+
|
|
184
|
+
export { type Box, CAPTURE_INTERACTIVE_SELECTOR, type CaptureOptions, type CaptureSession, type CaptureStepDraft, type CapturedStep, DOUBLE_CLICK_MS, NAV_AFTER_ACTION_MS, NAV_SETTLE_MS, REDACT_SELECTOR, type RedactionOptions, type ScreenResult, type ScreenSource, type SensitiveNumberKind, actionTarget, canCaptureScreen, captureLabel, captureRole, classifyNumber, collectRedactions, describeCapturedElement, encodeScreenshot, fieldValue, findSensitiveText, grabFrame, isMaskedElement, isSensitiveField, isTextEntry, labelControl, looksLikeSecretValue, normalizeRect, redactCanvas, requestTabCapture, screenshotDataUrl, selectedOptionText, startCapture, toFrameRect };
|