Compare commits
10 Commits
b149cf31ed
...
ba125e95a6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba125e95a6 | ||
|
|
3ae040ddf6 | ||
|
|
8eeaba7449 | ||
|
|
acba854f30 | ||
|
|
bcf93ca926 | ||
|
|
dab8c29da8 | ||
|
|
33e01f5f00 | ||
|
|
f0d25990c7 | ||
|
|
22bc4c334e | ||
|
|
ad5ac17422 |
6
.changeset/brave-walls-shine.md
Normal file
6
.changeset/brave-walls-shine.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@rrweb/record": major
|
||||
"@rrweb/replay": major
|
||||
---
|
||||
|
||||
BREAKING CHANGE: Rename UMD global names from `rrweb` to `rrwebRecord` for the recorder and `rrwebReplay` for the replayer. This avoids conflicts when both are loaded on the same page.
|
||||
10
.changeset/cuddly-dolphins-approve.md
Normal file
10
.changeset/cuddly-dolphins-approve.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
"@rrweb/all": patch
|
||||
"@rrweb/packer": patch
|
||||
"@rrweb/record": patch
|
||||
"rrweb-snapshot": patch
|
||||
"rrweb": patch
|
||||
"@rrweb/web-extension": patch
|
||||
---
|
||||
|
||||
Drop base64 inlined worker source from all bundles
|
||||
4
.changeset/docs-install-guidance.md
Normal file
4
.changeset/docs-install-guidance.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
---
|
||||
|
||||
Docs-only update: clarify package recommendation order (`@rrweb/record` + `@rrweb/replay` first, `@rrweb/all` as convenience), and fix example typos.
|
||||
2
.changeset/empty-devonly-template.md
Normal file
2
.changeset/empty-devonly-template.md
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
---
|
||||
5
.changeset/tender-foxes-rest.md
Normal file
5
.changeset/tender-foxes-rest.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"rrvideo": patch
|
||||
---
|
||||
|
||||
Adjust replay timeout to be based on video duration plus a 2-minute buffer instead of a fixed 2-minute timeout. This prevents timeout errors for longer recordings.
|
||||
21
.changeset/thirty-shirts-grow.md
Normal file
21
.changeset/thirty-shirts-grow.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
"@rrweb/all": patch
|
||||
"@rrweb/packer": patch
|
||||
"@rrweb/rrweb-plugin-canvas-webrtc-record": patch
|
||||
"@rrweb/rrweb-plugin-canvas-webrtc-replay": patch
|
||||
"@rrweb/rrweb-plugin-console-record": patch
|
||||
"@rrweb/rrweb-plugin-console-replay": patch
|
||||
"@rrweb/rrweb-plugin-sequential-id-record": patch
|
||||
"@rrweb/rrweb-plugin-sequential-id-replay": patch
|
||||
"@rrweb/record": patch
|
||||
"@rrweb/replay": patch
|
||||
"rrdom": patch
|
||||
"rrdom-nodejs": patch
|
||||
"rrweb": patch
|
||||
"rrweb-player": patch
|
||||
"rrweb-snapshot": patch
|
||||
"@rrweb/types": patch
|
||||
"@rrweb/utils": patch
|
||||
---
|
||||
|
||||
Provide a /umd/ output folder alongside the /dist/ one so that we can serve UMD (Universal Module Definition) files with a .js extension, without upsetting expectations set by package.json that all .js files in /dist/ are modules
|
||||
5
.changeset/twenty-flies-attend.md
Normal file
5
.changeset/twenty-flies-attend.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"rrvideo": patch
|
||||
---
|
||||
|
||||
Add better logging on playback and fix the use of rrweb-player so it doesn't stall and fail playback
|
||||
52
.github/scripts/measure-bundle-sizes.js
vendored
Normal file
52
.github/scripts/measure-bundle-sizes.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const outputPath = process.argv[2];
|
||||
|
||||
if (!outputPath) {
|
||||
console.error(
|
||||
'Usage: node .github/scripts/measure-bundle-sizes.js <output-path>',
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const rootDir = process.cwd();
|
||||
const sizes = {};
|
||||
|
||||
function normalizePath(filePath) {
|
||||
return path.relative(rootDir, filePath).replace(/\\/g, '/');
|
||||
}
|
||||
|
||||
function shouldTrack(filePath) {
|
||||
const normalizedPath = normalizePath(filePath);
|
||||
|
||||
if (normalizedPath.startsWith('packages/packer/dist/')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return /(^|\/)dist\/[^/]+\.(js|cjs|mjs|css)$/.test(normalizedPath);
|
||||
}
|
||||
|
||||
function walk(dirPath) {
|
||||
for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
|
||||
if (entry.name === 'node_modules') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const entryPath = path.join(dirPath, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
walk(entryPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!shouldTrack(entryPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sizes[normalizePath(entryPath)] = fs.statSync(entryPath).size;
|
||||
}
|
||||
}
|
||||
|
||||
walk(rootDir);
|
||||
fs.writeFileSync(outputPath, `${JSON.stringify(sizes, null, 2)}\n`);
|
||||
227
.github/scripts/render-bundle-size-comment.js
vendored
Normal file
227
.github/scripts/render-bundle-size-comment.js
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const prPath = process.argv[2];
|
||||
const basePath = process.argv[3];
|
||||
|
||||
if (!prPath || !basePath) {
|
||||
console.error(
|
||||
'Usage: node .github/scripts/render-bundle-size-comment.js <pr-sizes.json> <base-sizes.json>',
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function readJson(filePath) {
|
||||
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
}
|
||||
|
||||
function formatSize(bytes) {
|
||||
if (bytes == null) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
if (Math.abs(bytes) < 1024) {
|
||||
return `${bytes} B`;
|
||||
}
|
||||
|
||||
return `${(bytes / 1024).toFixed(2)} kB`;
|
||||
}
|
||||
|
||||
function formatSignedSize(bytes) {
|
||||
const absoluteBytes = Math.abs(bytes);
|
||||
|
||||
if (absoluteBytes < 1024) {
|
||||
return `${bytes >= 0 ? '+' : '-'}${absoluteBytes} B`;
|
||||
}
|
||||
|
||||
return `${bytes >= 0 ? '+' : '-'}${(absoluteBytes / 1024).toFixed(2)} kB`;
|
||||
}
|
||||
|
||||
function formatDiff(diff, baseValue) {
|
||||
if (diff === 0) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
const percentage =
|
||||
baseValue > 0
|
||||
? ` (${diff > 0 ? '+' : ''}${((diff / baseValue) * 100).toFixed(2)}%)`
|
||||
: '';
|
||||
|
||||
return `${formatSignedSize(diff)}${percentage}`;
|
||||
}
|
||||
|
||||
const BUNDLE_SIZE_BADGES = {
|
||||
deleted: ' 🗑️',
|
||||
new: ' 🆕',
|
||||
improved: ' 🎉',
|
||||
investigate: ' 🔍',
|
||||
};
|
||||
|
||||
function getChangeBadge(prValue, baseValue) {
|
||||
if (prValue == null) {
|
||||
return BUNDLE_SIZE_BADGES.deleted;
|
||||
}
|
||||
|
||||
if (baseValue == null) {
|
||||
return BUNDLE_SIZE_BADGES.new;
|
||||
}
|
||||
|
||||
if (baseValue <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const percentage = ((prValue - baseValue) / baseValue) * 100;
|
||||
|
||||
if (percentage <= -10) {
|
||||
return BUNDLE_SIZE_BADGES.improved;
|
||||
}
|
||||
|
||||
if (percentage >= 5) {
|
||||
return BUNDLE_SIZE_BADGES.investigate;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function getPackageBadge(prTotal, baseTotal) {
|
||||
if (baseTotal === 0 && prTotal > 0) {
|
||||
return BUNDLE_SIZE_BADGES.new;
|
||||
}
|
||||
|
||||
if (baseTotal <= 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const percentage = ((prTotal - baseTotal) / baseTotal) * 100;
|
||||
|
||||
if (percentage <= -10) {
|
||||
return BUNDLE_SIZE_BADGES.improved;
|
||||
}
|
||||
|
||||
if (percentage >= 5) {
|
||||
return BUNDLE_SIZE_BADGES.investigate;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function getPackageName(filePath) {
|
||||
const match = filePath.match(/^packages\/([^/]+)\//);
|
||||
return match ? match[1] : '(root)';
|
||||
}
|
||||
|
||||
function escapeHtml(value) {
|
||||
return value
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/\|/g, '|')
|
||||
.replace(/\r?\n/g, ' ');
|
||||
}
|
||||
|
||||
function formatCode(value) {
|
||||
return `<code>${escapeHtml(String(value))}</code>`;
|
||||
}
|
||||
|
||||
function getFileLabel(filePath, packageName) {
|
||||
const packagePrefix = `packages/${packageName}/dist/`;
|
||||
|
||||
if (packageName !== '(root)' && filePath.startsWith(packagePrefix)) {
|
||||
return filePath.slice(packagePrefix.length);
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
const prSizes = readJson(prPath);
|
||||
const baseSizes = readJson(basePath);
|
||||
|
||||
const allFiles = [
|
||||
...new Set([...Object.keys(prSizes), ...Object.keys(baseSizes)]),
|
||||
].sort();
|
||||
const changedFiles = allFiles.filter(
|
||||
(filePath) => prSizes[filePath] !== baseSizes[filePath],
|
||||
);
|
||||
|
||||
if (changedFiles.length === 0) {
|
||||
process.stdout.write('## Bundle Size Changes\n\nNo bundle size changes.\n');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const totalPrSize = allFiles.reduce(
|
||||
(sum, filePath) => sum + (prSizes[filePath] ?? 0),
|
||||
0,
|
||||
);
|
||||
const totalBaseSize = allFiles.reduce(
|
||||
(sum, filePath) => sum + (baseSizes[filePath] ?? 0),
|
||||
0,
|
||||
);
|
||||
const totalDiff = totalPrSize - totalBaseSize;
|
||||
|
||||
const filesByPackage = new Map();
|
||||
|
||||
for (const filePath of changedFiles) {
|
||||
const packageName = getPackageName(filePath);
|
||||
const files = filesByPackage.get(packageName) ?? [];
|
||||
files.push(filePath);
|
||||
filesByPackage.set(packageName, files);
|
||||
}
|
||||
|
||||
const sections = [...filesByPackage.entries()]
|
||||
.sort(([left], [right]) => left.localeCompare(right))
|
||||
.map(([packageName, files]) => {
|
||||
const packagePrSize = files.reduce(
|
||||
(sum, filePath) => sum + (prSizes[filePath] ?? 0),
|
||||
0,
|
||||
);
|
||||
const packageBaseSize = files.reduce(
|
||||
(sum, filePath) => sum + (baseSizes[filePath] ?? 0),
|
||||
0,
|
||||
);
|
||||
const packageDiff = packagePrSize - packageBaseSize;
|
||||
const packageBadge = getPackageBadge(packagePrSize, packageBaseSize);
|
||||
|
||||
const rows = files
|
||||
.map((filePath) => {
|
||||
const prSize = prSizes[filePath];
|
||||
const baseSize = baseSizes[filePath];
|
||||
const fileDiff = (prSizes[filePath] ?? 0) - (baseSizes[filePath] ?? 0);
|
||||
|
||||
return `| ${formatCode(
|
||||
getFileLabel(filePath, packageName),
|
||||
)} | ${formatSize(baseSize)} | ${formatSize(prSize)} | ${formatDiff(
|
||||
fileDiff,
|
||||
baseSize ?? 0,
|
||||
)}${getChangeBadge(prSize, baseSize)} |`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return [
|
||||
'<details>',
|
||||
`<summary>${formatCode(packageName)}${packageBadge} - ${formatSize(
|
||||
packageBaseSize,
|
||||
)} -> ${formatSize(packagePrSize)} (${formatDiff(
|
||||
packageDiff,
|
||||
packageBaseSize,
|
||||
)})</summary>`,
|
||||
'',
|
||||
'| File | Base | PR | Diff |',
|
||||
'|------|------|----|------|',
|
||||
rows,
|
||||
'',
|
||||
'</details>',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
const body = [
|
||||
'## Bundle Size Changes',
|
||||
'',
|
||||
`**Size change:** ${formatDiff(
|
||||
totalDiff,
|
||||
totalBaseSize,
|
||||
)} | **Total size:** ${formatSize(totalPrSize)}`,
|
||||
'',
|
||||
sections.join('\n\n'),
|
||||
'',
|
||||
].join('\n');
|
||||
|
||||
process.stdout.write(body);
|
||||
21
.github/workflows/ci-cd.yml
vendored
21
.github/workflows/ci-cd.yml
vendored
@@ -1,6 +1,12 @@
|
||||
name: Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
@@ -31,6 +37,9 @@ jobs:
|
||||
- name: Build Project
|
||||
run: NODE_OPTIONS='--max-old-space-size=4096' yarn build:all
|
||||
|
||||
- name: Install Playwright browsers
|
||||
run: cd packages/rrvideo && yarn playwright install chromium
|
||||
|
||||
- name: Check types
|
||||
run: yarn check-types
|
||||
|
||||
@@ -38,16 +47,6 @@ jobs:
|
||||
# run: PUPPETEER_EXECUTABLE_PATH=${{ steps.setup-chrome.outputs.chrome-path }} PUPPETEER_HEADLESS=true xvfb-run --server-args="-screen 0 1920x1080x24" yarn test
|
||||
run: PUPPETEER_HEADLESS=true xvfb-run --server-args="-screen 0 1920x1080x24" yarn test
|
||||
|
||||
- name: Check bundle sizes
|
||||
uses: preactjs/compressed-size-action@v2
|
||||
with:
|
||||
install-script: 'yarn install --frozen-lockfile'
|
||||
build-script: 'build:all'
|
||||
compression: 'none'
|
||||
pattern: '**/dist/*.{js,cjs,mjs,css}'
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: true
|
||||
|
||||
- name: Upload diff images to GitHub
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
|
||||
102
.github/workflows/eslint-check.yml
vendored
Normal file
102
.github/workflows/eslint-check.yml
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
name: ESLint Check
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
eslint_check_upload:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
name: ESLint Check and Report Upload
|
||||
|
||||
steps:
|
||||
- name: Checkout pull request head
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Checkout current branch
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'yarn'
|
||||
- name: Install Dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: true
|
||||
- name: Build Packages
|
||||
run: NODE_OPTIONS='--max-old-space-size=4096' yarn build:all
|
||||
- name: Eslint Check
|
||||
run: yarn turbo run lint
|
||||
- name: Save Code Linting Report JSON
|
||||
run: yarn lint:report
|
||||
# Continue to the next step even if this fails
|
||||
continue-on-error: true
|
||||
- name: Upload ESLint Report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: eslint_report.json
|
||||
path: eslint_report.json
|
||||
- name: Measure PR bundle sizes
|
||||
if: github.event_name == 'pull_request'
|
||||
run: node .github/scripts/measure-bundle-sizes.js pr-sizes.json
|
||||
- name: Upload PR bundle sizes
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr-sizes
|
||||
path: pr-sizes.json
|
||||
|
||||
bundle_size_build:
|
||||
# Only runs on PRs. Reuses the PR build from eslint_check_upload (via the
|
||||
# pr-sizes artifact) and only builds the base branch itself. The privileged
|
||||
# bundle-size-comment workflow then posts the PR comment without ever
|
||||
# executing fork code.
|
||||
if: github.event_name == 'pull_request'
|
||||
needs: eslint_check_upload
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
name: Build Base for Bundle Size Comparison
|
||||
steps:
|
||||
- name: Checkout workflow ref
|
||||
uses: actions/checkout@v4
|
||||
- name: Prepare bundle size helper
|
||||
run: |
|
||||
cp .github/scripts/measure-bundle-sizes.js /tmp/measure-bundle-sizes.js
|
||||
# --- Base branch ---
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.base_ref }}
|
||||
- name: Download PR bundle sizes
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pr-sizes
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'yarn'
|
||||
- name: Install base dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: true
|
||||
- name: Build base branch
|
||||
run: NODE_OPTIONS='--max-old-space-size=4096' yarn build:all
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: true
|
||||
- name: Measure base bundle sizes
|
||||
run: node /tmp/measure-bundle-sizes.js base-sizes.json
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bundle-size-data
|
||||
path: |
|
||||
pr-sizes.json
|
||||
base-sizes.json
|
||||
85
.github/workflows/pr-checks-privileged.yml
vendored
Normal file
85
.github/workflows/pr-checks-privileged.yml
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
name: PR Checks (privileged)
|
||||
|
||||
# Runs in the base-repo context (privileged) after eslint-check.yml completes.
|
||||
# Downloads pre-built artifacts and posts PR comments/annotations.
|
||||
# Never checks out or executes fork code.
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ['ESLint Check']
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout trusted workflow helpers
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.repository.default_branch }}
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: bundle-size-data
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
- name: Find PR number
|
||||
id: find-pr
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const run = context.payload.workflow_run;
|
||||
if (run.pull_requests && run.pull_requests.length > 0) {
|
||||
return run.pull_requests[0].number;
|
||||
}
|
||||
// Fallback for fork PRs (pull_requests is empty for forks)
|
||||
const { data: prs } = await github.rest.pulls.list({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
head: `${run.head_repository.full_name}:${run.head_branch}`,
|
||||
state: 'open',
|
||||
});
|
||||
if (prs.length === 0) {
|
||||
core.setFailed('Could not determine PR number');
|
||||
return;
|
||||
}
|
||||
return prs[0].number;
|
||||
result-encoding: string
|
||||
|
||||
- name: Render bundle size comment
|
||||
if: steps.find-pr.outputs.result
|
||||
run: |
|
||||
node .github/scripts/render-bundle-size-comment.js pr-sizes.json base-sizes.json > bundle-size-comment.md
|
||||
|
||||
- name: Post bundle size comment
|
||||
if: steps.find-pr.outputs.result
|
||||
uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405
|
||||
with:
|
||||
header: bundle-size
|
||||
path: bundle-size-comment.md
|
||||
number: ${{ steps.find-pr.outputs.result }}
|
||||
|
||||
annotate:
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: eslint_report.json
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
- name: Annotate Code Linting Results
|
||||
uses: ataylorme/eslint-annotate-action@5f4dc2e3af8d3c21b727edb597e5503510b1dc9c
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
report-json: 'eslint_report.json'
|
||||
56
.github/workflows/style-check.yml
vendored
56
.github/workflows/style-check.yml
vendored
@@ -1,60 +1,8 @@
|
||||
name: Code Style Check
|
||||
name: Prettier Check
|
||||
|
||||
on: [push, pull_request_target]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
eslint_check_upload:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
name: ESLint Check and Report Upload
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
ref: ${{ github.head_ref }}
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'yarn'
|
||||
- name: Install Dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
env:
|
||||
PUPPETEER_SKIP_DOWNLOAD: true
|
||||
- name: Build Packages
|
||||
run: NODE_OPTIONS='--max-old-space-size=4096' yarn build:all
|
||||
- name: Eslint Check
|
||||
run: yarn turbo run lint
|
||||
- name: Save Code Linting Report JSON
|
||||
run: yarn lint:report
|
||||
# Continue to the next step even if this fails
|
||||
continue-on-error: true
|
||||
- name: Upload ESLint Report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: eslint_report.json
|
||||
path: eslint_report.json
|
||||
|
||||
annotation:
|
||||
# Skip the annotation action in push events
|
||||
if: github.event_name == 'pull_request_target'
|
||||
permissions:
|
||||
checks: write
|
||||
needs: eslint_check_upload
|
||||
runs-on: ubuntu-latest
|
||||
name: ESLint Annotation
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: eslint_report.json
|
||||
- name: Annotate Code Linting Results
|
||||
uses: ataylorme/eslint-annotate-action@v2
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
report-json: 'eslint_report.json'
|
||||
|
||||
prettier_check:
|
||||
# In the forked PR, it's hard to format code and push to the branch directly, so the action only check the format correctness.
|
||||
if: github.event_name != 'push' && github.event.pull_request.head.repo.full_name != 'rrweb-io/rrweb'
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -16,6 +16,7 @@ temp
|
||||
# output of `yarn build`
|
||||
build
|
||||
dist
|
||||
umd
|
||||
|
||||
# turbo cache
|
||||
.turbo
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
[](https://join.slack.com/t/rrweb/shared_invite/zt-siwoc6hx-uWay3s2wyG8t5GpZVb8rWg)
|
||||
[](https://twitter.com/rrweb_io)
|
||||
[](https://www.reddit.com/r/rrweb)
|
||||

|
||||

|
||||

|
||||

|
||||
[](https://www.jsdelivr.com/package/npm/rrweb)
|
||||
|
||||
[中文文档](./README.zh_CN.md)
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
[](https://join.slack.com/t/rrweb/shared_invite/zt-siwoc6hx-uWay3s2wyG8t5GpZVb8rWg)
|
||||
[](https://www.reddit.com/r/rrweb)
|
||||

|
||||

|
||||

|
||||

|
||||
[](https://www.jsdelivr.com/package/npm/rrweb)
|
||||
|
||||
> 我已开通 Github Sponsor, 您可以通过赞助的形式帮助 rrweb 的开发。
|
||||
|
||||
@@ -6,7 +6,9 @@ There are some options for recording and replaying Canvas.
|
||||
Enable recording Canvas:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {},
|
||||
recordCanvas: true,
|
||||
});
|
||||
@@ -15,7 +17,9 @@ rrweb.record({
|
||||
Alternatively enable image snapshot recording of Canvas at a maximum of 15 frames per second:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {},
|
||||
recordCanvas: true,
|
||||
sampling: {
|
||||
@@ -32,7 +36,9 @@ rrweb.record({
|
||||
Enable replaying Canvas:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events, {
|
||||
UNSAFE_replayCanvas: true,
|
||||
});
|
||||
replayer.play();
|
||||
|
||||
@@ -5,7 +5,9 @@ Canvas 是一种特殊的 HTML 元素,默认情况下其内容不会被 rrweb
|
||||
录制时包含 Canvas 内的内容:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {},
|
||||
// 对 canvas 进行录制
|
||||
recordCanvas: true,
|
||||
@@ -15,7 +17,9 @@ rrweb.record({
|
||||
或者启用每秒 15 帧的 Canvas 图像快照记录:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {},
|
||||
recordCanvas: true,
|
||||
sampling: {
|
||||
@@ -32,7 +36,9 @@ rrweb.record({
|
||||
回放时对 Canvas 进行回放:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events, {
|
||||
UNSAFE_replayCanvas: true,
|
||||
});
|
||||
replayer.play();
|
||||
|
||||
@@ -8,10 +8,10 @@ This feature aims to provide developers with more information about the bug scen
|
||||
You can enable the logger using default option like this:
|
||||
|
||||
```js
|
||||
import rrweb from 'rrweb';
|
||||
import { record } from '@rrweb/record';
|
||||
import { getRecordConsolePlugin } from '@rrweb/rrweb-plugin-console-record';
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit: function emit(event) {
|
||||
// you should use console.log in this way to avoid errors.
|
||||
const defaultLog = console.log['__rrweb_original__']
|
||||
@@ -30,10 +30,10 @@ You should call console.log.\_\_rrweb_original\_\_() instead.
|
||||
You can also customize the behavior of logger like this:
|
||||
|
||||
```js
|
||||
import rrweb from 'rrweb';
|
||||
import { record } from '@rrweb/record';
|
||||
import { getRecordConsolePlugin } from '@rrweb/rrweb-plugin-console-record';
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit: function emit(event) {
|
||||
// you should use console.log in this way to avoid errors.
|
||||
const defaultLog = console.log['__rrweb_original__']
|
||||
@@ -70,10 +70,10 @@ All options are described below:
|
||||
If recorded events include data of console log type, we will automatically play them.
|
||||
|
||||
```js
|
||||
import rrweb from 'rrweb';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import { getReplayConsolePlugin } from '@rrweb/rrweb-plugin-console-replay';
|
||||
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
const replayer = new Replayer(events, {
|
||||
plugins: [
|
||||
getReplayConsolePlugin({
|
||||
level: ['info', 'log', 'warn', 'error'],
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
可以通过如下代码使用默认的配置选项
|
||||
|
||||
```js
|
||||
import rrweb from 'rrweb';
|
||||
import { record } from '@rrweb/record';
|
||||
import { getRecordConsolePlugin } from '@rrweb/rrweb-plugin-console-record';
|
||||
|
||||
rweb.record({
|
||||
record({
|
||||
emit: function emit(event) {
|
||||
// 如果要使用console来输出信息,请使用如下的写法
|
||||
const defaultLog = console.log['__rrweb_original__']
|
||||
@@ -29,10 +29,10 @@ rweb.record({
|
||||
你也可以定制录制 console 的选项
|
||||
|
||||
```js
|
||||
import rrweb from 'rrweb';
|
||||
import { record } from '@rrweb/record';
|
||||
import { getRecordConsolePlugin } from '@rrweb/rrweb-plugin-console-record';
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit: function emit(event) {
|
||||
// 如果要使用console来输出信息,请使用如下的写法
|
||||
const defaultLog = console.log['__rrweb_original__']
|
||||
@@ -69,10 +69,10 @@ rrweb.record({
|
||||
如果 replayer 传入的 events 中包含了 console 类型的数据,我们将自动播放这些数据。
|
||||
|
||||
```js
|
||||
import rrweb from 'rrweb';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import { getReplayConsolePlugin } from '@rrweb/rrweb-plugin-console-replay';
|
||||
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
const replayer = new Replayer(events, {
|
||||
plugins: [
|
||||
getReplayConsolePlugin({
|
||||
level: ['info', 'log', 'warn', 'error'],
|
||||
|
||||
@@ -8,7 +8,9 @@ Since if you allow recording cross origin iframes, any malicious website can emb
|
||||
Enable recording cross-origin iframes in your parent page:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {}, // all events will be emitted here, including events from cross origin iframes
|
||||
recordCrossOriginIframes: true,
|
||||
});
|
||||
@@ -17,7 +19,9 @@ rrweb.record({
|
||||
Enable replaying cross-origin iframes in your child page:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {}, // this is required for rrweb, but the child page will not emit any events
|
||||
recordCrossOriginIframes: true,
|
||||
});
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
在父页面中启用录制跨域 iframe:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {}, // 所有事件都将在此处发出,包括来自跨源 iframe 的事件
|
||||
recordCrossOriginIframes: true,
|
||||
});
|
||||
@@ -17,7 +19,9 @@ rrweb.record({
|
||||
在您的子页面中启用重放跨域 iframe:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {}, // 这是 rrweb 所必需的,但子页面不会发出任何事件
|
||||
recordCrossOriginIframes: true,
|
||||
});
|
||||
|
||||
@@ -5,19 +5,21 @@ You may need to record some custom events along with the rrweb events, and let t
|
||||
After starting the recording, we can call the `record.addCustomEvent` API to add a custom event.
|
||||
|
||||
```js
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
// start recording
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event) {
|
||||
...
|
||||
}
|
||||
})
|
||||
|
||||
// record some custom events at any time
|
||||
rrweb.record.addCustomEvent('submit-form', {
|
||||
record.addCustomEvent('submit-form', {
|
||||
name: 'Adam',
|
||||
age: 18
|
||||
})
|
||||
rrweb.record.addCustomEvent('some-error', {
|
||||
record.addCustomEvent('some-error', {
|
||||
error
|
||||
})
|
||||
```
|
||||
@@ -29,7 +31,9 @@ During the replay, we can add an event listener to custom events, or configure t
|
||||
**Listen to custom events**
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
replayer.on('custom-event', (event) => {
|
||||
console.log(event.tag, event.payload);
|
||||
|
||||
@@ -5,19 +5,21 @@
|
||||
开始录制后,我们就可以通过 `record.addCustomEvent` API 添加自定义事件:
|
||||
|
||||
```js
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
// 开始录制
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event) {
|
||||
...
|
||||
}
|
||||
})
|
||||
|
||||
// 在开始录制后的任意时间点记录自定义事件,例如:
|
||||
rrweb.record.addCustomEvent('submit-form', {
|
||||
record.addCustomEvent('submit-form', {
|
||||
name: '姓名',
|
||||
age: 18
|
||||
})
|
||||
rrweb.record.addCustomEvent('some-error', {
|
||||
record.addCustomEvent('some-error', {
|
||||
error
|
||||
})
|
||||
```
|
||||
@@ -29,7 +31,9 @@ rrweb.record.addCustomEvent('some-error', {
|
||||
**获取对应事件**
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
replayer.on('custom-event', (event) => {
|
||||
console.log(event.tag, event.payload);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# Customize the Replayer
|
||||
|
||||
When rrweb's Replayer and the [rrweb-player](../../packages/rrweb-player/) UI do not fit your need, you can customize your replayer UI.
|
||||
When `Replayer` and the [rrweb-player](../../packages/rrweb-player/) UI do not fit your need, you can customize your replayer UI.
|
||||
|
||||
There are several ways to do this:
|
||||
|
||||
1. Use [rrweb-player](../../packages/rrweb-player/), and customize its CSS.
|
||||
2. Use [rrweb-player](../../packages/rrweb-player/), and set `showController: false` to hide the controller UI. With this config, you can implement your controller UI.
|
||||
3. Use the `insertStyleRules` options to inject some CSS into the replay iframe.
|
||||
4. Develop a new replayer UI with rrweb's Replayer.
|
||||
4. Develop a new replayer UI with `Replayer`.
|
||||
|
||||
## Implement Your Controller UI
|
||||
|
||||
@@ -69,6 +69,6 @@ rrwebPlayer.addEventListener('ui-update-progress', (event) => {
|
||||
});
|
||||
```
|
||||
|
||||
## Develop a new replayer UI with rrweb's Replayer.
|
||||
## Develop a new replayer UI with `Replayer`.
|
||||
|
||||
Please refer [rrweb-player](https://github.com/rrweb-io/rrweb/tree/master/packages/rrweb-player/).
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# 自定义回放 UI
|
||||
|
||||
当 rrweb Replayer 和 [rrweb-player](../../packages/rrweb-player/) 的 UI 不能满足需求时,可以通过自定义回放 UI 制作属于你自己的回放器。
|
||||
当 `Replayer` 和 [rrweb-player](../../packages/rrweb-player/) 的 UI 不能满足需求时,可以通过自定义回放 UI 制作属于你自己的回放器。
|
||||
|
||||
你可以通过以下几种方式从不同角度自定义回放 UI:
|
||||
|
||||
1. 使用 [rrweb-player](../../packages/rrweb-player/) 时,通过覆盖 CSS 样式表定制 UI。
|
||||
2. 使用 [rrweb-player](../../packages/rrweb-player/) 时,通过 `showController: false` 隐藏控制器 UI,重新实现控制器 UI。
|
||||
3. 通过 `insertStyleRules` 在回放页面(iframe)内定制 CSS 样式。
|
||||
4. 基于 rrweb Replayer 开发自己的回放器 UI。
|
||||
4. 基于 `Replayer` 开发自己的回放器 UI。
|
||||
|
||||
## 实现控制器 UI
|
||||
|
||||
@@ -69,6 +69,6 @@ rrwebPlayer.addEventListener('ui-update-progress', (event) => {
|
||||
});
|
||||
```
|
||||
|
||||
## 基于 rrweb Replayer 开发自己的回放器 UI
|
||||
## 基于 `Replayer` 开发自己的回放器 UI
|
||||
|
||||
可以参照 [rrweb-player](https://github.com/rrweb-io/rrweb/tree/master/packages/rrweb-player/) 的方式进行开发。
|
||||
|
||||
@@ -42,7 +42,7 @@ By default, the UI could not interact during replay. But you can use API to enab
|
||||
|
||||
### Customize The Replayer
|
||||
|
||||
When rrweb's Replayer and the rrweb-player UI do not fit your need, you can customize your own replayer UI.
|
||||
When `Replayer` and the rrweb-player UI do not fit your need, you can customize your own replayer UI.
|
||||
|
||||
[link](./customize-replayer.md)
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
### 自定义回放 UI
|
||||
|
||||
当 rrweb Replayer 和 rrweb-player 的 UI 不能满足需求时,可以通过自定义回放 UI 制作属于你自己的回放器。
|
||||
当 `Replayer` 和 rrweb-player 的 UI 不能满足需求时,可以通过自定义回放 UI 制作属于你自己的回放器。
|
||||
|
||||
[链接](./customize-replayer.zh_CN.md)
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
By default, the UI could not interact during replay. But you can use API to enable/disable this programmatically.
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
// enable user interact with the UI
|
||||
replayer.enableInteract();
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
回放时的 UI 默认不可交互,但在特定场景下也可以通过 API 允许用户与回放场景进行交互。
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
// 允许用户在回放的 UI 中进行交互
|
||||
replayer.enableInteract();
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
If you want to replay the events in a real-time way, you can use the live mode API. This API is also useful for some real-time collaboration usage.
|
||||
|
||||
When you are using rrweb's Replayer to do a real-time replay, you need to configure `liveMode: true` and call the `startLive` API to enable the live mode.
|
||||
When you use `Replayer` for real-time replay, configure `liveMode: true` and call `startLive()` to enable live mode.
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer([], {
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer([], {
|
||||
liveMode: true,
|
||||
});
|
||||
replayer.startLive();
|
||||
@@ -22,7 +24,9 @@ function onReceive(event) {
|
||||
If you have an ongoing recording that already has events, and wish to initiate play from a 'live' time, it's also possible to use the `play` function, supplied with an offset which corresponds to the current time:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(EXISTING_EVENTS, {
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(EXISTING_EVENTS, {
|
||||
liveMode: true,
|
||||
});
|
||||
replayer.play(Date.now() - EXISTING_EVENTS[0].timestamp);
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
如果希望持续、实时地看到录制的数据,达到类似直播的效果,则可以使用实时回放 API。这个方式也适用于一些实时协同的场景。
|
||||
|
||||
使用 rrweb Replayer 进行实时回放时,需要传入 `liveMode: true` 配置,并通过 `startLive` API 启动直播模式。
|
||||
使用 `Replayer` 进行实时回放时,需要传入 `liveMode: true` 配置,并通过 `startLive` API 启动直播模式。
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer([], {
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer([], {
|
||||
liveMode: true,
|
||||
});
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@ Use the sampling config in the recording can reduce the storage size by dropping
|
||||
**Scenario 1**
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {},
|
||||
sampling: {
|
||||
// do not record mouse movement
|
||||
@@ -46,7 +48,9 @@ rrweb.record({
|
||||
**Scenario 2**
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {},
|
||||
sampling: {
|
||||
// Configure which kinds of mouse interaction should be recorded
|
||||
@@ -76,7 +80,7 @@ You can use it by passing it as the `packFn` in the recording.
|
||||
```js
|
||||
import { pack } from '@rrweb/packer';
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event) {},
|
||||
packFn: pack,
|
||||
});
|
||||
@@ -86,8 +90,9 @@ And you need to pass packer.unpack as the `unpackFn` in replaying.
|
||||
|
||||
```js
|
||||
import { unpack } from '@rrweb/packer';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
const replayer = new Replayer(events, {
|
||||
unpackFn: unpack,
|
||||
});
|
||||
```
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
**示例 1**
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {},
|
||||
sampling: {
|
||||
// 不录制鼠标移动事件
|
||||
@@ -46,7 +48,9 @@ rrweb.record({
|
||||
**示例 2**
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {},
|
||||
sampling: {
|
||||
// 定义不录制的鼠标交互事件类型,可以细粒度的开启或关闭对应交互录制
|
||||
@@ -74,9 +78,9 @@ rrweb 提供了一个基于 fflate 的简单压缩函数,在 [@rrweb/packer](.
|
||||
```js
|
||||
import { pack } from '@rrweb/packer';
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event) {},
|
||||
packFn: rrweb.pack,
|
||||
packFn: pack,
|
||||
});
|
||||
```
|
||||
|
||||
@@ -84,9 +88,10 @@ rrweb.record({
|
||||
|
||||
```js
|
||||
import { unpack } from '@rrweb/packer';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
unpackFn: rrweb.unpack,
|
||||
const replayer = new Replayer(events, {
|
||||
unpackFn: unpack,
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ When the size of the recorded events increased, load them in one request is not
|
||||
rrweb's API for loading async events is quite simple:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
replayer.addEvent(NEW_EVENT);
|
||||
```
|
||||
@@ -15,7 +17,9 @@ When calling the `addEvent` API to add a new event, rrweb will resolve its times
|
||||
If you need to load several events, you can do a loop like this:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
for (const event of NEW_EVENTS) {
|
||||
replayer.addEvent(event);
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
rrweb 中用于实现异步加载数据的 API 非常简单直观:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
replayer.addEvent(NEW_EVENT);
|
||||
```
|
||||
@@ -15,7 +17,9 @@ replayer.addEvent(NEW_EVENT);
|
||||
如果需要异步加载多个数据,只需这样使用:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
for (const event of NEW_EVENTS) {
|
||||
replayer.addEvent(event);
|
||||
|
||||
@@ -38,6 +38,8 @@ Both record and replay plugins have a type interface.
|
||||
#### record plugin
|
||||
|
||||
```ts
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
const exampleRecordPlugin: RecordPlugin<{ foo: string }> = {
|
||||
name: 'my-scope/example@1',
|
||||
observer(cb, options) {
|
||||
@@ -54,7 +56,7 @@ const exampleRecordPlugin: RecordPlugin<{ foo: string }> = {
|
||||
},
|
||||
};
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit: emit(event) {},
|
||||
plugins: [exampleRecordPlugin],
|
||||
});
|
||||
@@ -79,6 +81,8 @@ In this example, the record plugin will emit events like this:
|
||||
#### replay plugin
|
||||
|
||||
```ts
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const exampleReplayPlugin: ReplayPlugin = {
|
||||
handler(event, isSync, context) {
|
||||
if (event.type === EventType.Plugin) {
|
||||
@@ -90,7 +94,7 @@ const exampleReplayPlugin: ReplayPlugin = {
|
||||
},
|
||||
};
|
||||
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
const replayer = new Replayer(events, {
|
||||
plugins: [exampleReplayPlugin],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -38,6 +38,8 @@ export type ReplayPlugin = {
|
||||
#### 录制侧插件
|
||||
|
||||
```ts
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
const exampleRecordPlugin: RecordPlugin<{ foo: string }> = {
|
||||
name: 'my-scope/example@1',
|
||||
observer(cb, options) {
|
||||
@@ -54,7 +56,7 @@ const exampleRecordPlugin: RecordPlugin<{ foo: string }> = {
|
||||
},
|
||||
};
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit: emit(event) {},
|
||||
plugins: [exampleRecordPlugin],
|
||||
});
|
||||
@@ -79,6 +81,8 @@ rrweb.record({
|
||||
#### 回放侧插件
|
||||
|
||||
```ts
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const exampleReplayPlugin: ReplayPlugin = {
|
||||
handler(event, isSync, context) {
|
||||
if (event.type === EventType.Plugin) {
|
||||
@@ -90,7 +94,7 @@ const exampleReplayPlugin: ReplayPlugin = {
|
||||
},
|
||||
};
|
||||
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
const replayer = new Replayer(events, {
|
||||
plugins: [exampleReplayPlugin],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -5,7 +5,9 @@ Record and Replay is the most common use case, which is suitable for any scenari
|
||||
You only need a simple API call to record the website:
|
||||
|
||||
```js
|
||||
const stopFn = rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
const stopFn = record({
|
||||
emit(event) {
|
||||
// save the event
|
||||
},
|
||||
@@ -21,11 +23,13 @@ But you should guarantee:
|
||||
|
||||
You can use the `stopFn` to stop the recording.
|
||||
|
||||
The replay is also as simple as putting events into rrweb's Replayer.
|
||||
Replay is also as simple as passing events into `Replayer`.
|
||||
|
||||
```js
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const events = GET_YOUR_EVENTS;
|
||||
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
const replayer = new Replayer(events);
|
||||
replayer.play();
|
||||
```
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
仅需一个函数调用就可以录制当前页面:
|
||||
|
||||
```js
|
||||
const stopFn = rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
const stopFn = record({
|
||||
emit(event) {
|
||||
// 保存获取到的 event 数据
|
||||
},
|
||||
@@ -19,11 +21,13 @@ const stopFn = rrweb.record({
|
||||
|
||||
如果需要手动停止录制,可以调用返回的 `stopFn` 函数。
|
||||
|
||||
回放时只需要获取一段录制数据,并传入 rrweb 提供的 Replayer:
|
||||
回放时只需要获取一段录制数据,并传入 `Replayer`:
|
||||
|
||||
```js
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const events = GET_YOUR_EVENTS;
|
||||
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
const replayer = new Replayer(events);
|
||||
replayer.play();
|
||||
```
|
||||
|
||||
193
guide.md
193
guide.md
@@ -6,43 +6,119 @@
|
||||
|
||||
## Installation
|
||||
|
||||
### Direct `<script>` include
|
||||
| Goal | Recommended package(s) |
|
||||
| ------------------------------- | --------------------------------- |
|
||||
| Most projects (record + replay) | `@rrweb/record` + `@rrweb/replay` |
|
||||
| Single-package convenience | `@rrweb/all` |
|
||||
| Legacy compatibility only | `rrweb` |
|
||||
|
||||
You are recommended to install rrweb via jsdelivr's CDN service:
|
||||
In most production setups, recorder and replayer are deployed to different pages/apps. Use `@rrweb/record` on recorded pages and `@rrweb/replay` (or `rrweb-player`) on replay pages. Use `@rrweb/all` when you intentionally want one package for convenience (for example demos, tooling, or simplified setups).
|
||||
|
||||
### 1) Bundler / npm (Recommended)
|
||||
|
||||
```shell
|
||||
npm install @rrweb/record @rrweb/replay
|
||||
```
|
||||
|
||||
```js
|
||||
import { record } from '@rrweb/record';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import '@rrweb/replay/dist/style.css';
|
||||
```
|
||||
|
||||
Use `@rrweb/all` as a convenience package if you want a single import:
|
||||
|
||||
```shell
|
||||
npm install @rrweb/all
|
||||
```
|
||||
|
||||
```js
|
||||
import { record, Replayer } from '@rrweb/all';
|
||||
import '@rrweb/all/dist/style.css';
|
||||
```
|
||||
|
||||
`require(...)` / CommonJS remains available for compatibility via each package's `exports`/`main`, but ESM imports are the primary path for 2.x.
|
||||
|
||||
### 2) Browser Without Bundler (No-Build)
|
||||
|
||||
Use ES modules and import maps with jsDelivr `+esm`:
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/style.css"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.umd.min.cjs"></script>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@rrweb/record": "https://cdn.jsdelivr.net/npm/@rrweb/record@latest/+esm",
|
||||
"@rrweb/replay": "https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {
|
||||
console.log(event);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
Also, you can link to a specific version number that you can update manually:
|
||||
Or use `@rrweb/all` as a convenience browser ESM import:
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb@2.0.0-alpha.14/dist/rrweb.umd.min.cjs"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/all@latest/dist/style.css"
|
||||
/>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@rrweb/all": "https://cdn.jsdelivr.net/npm/@rrweb/all@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import { record, Replayer } from '@rrweb/all';
|
||||
</script>
|
||||
```
|
||||
|
||||
#### Only include the recorder code
|
||||
### 3) Legacy Direct `<script>` Include (UMD Fallback)
|
||||
|
||||
rrweb's code includes both the record and the replay parts. Most of the time you only need to include the record part into your targeted web Apps.
|
||||
This also can be done by using the `@rrweb/record` package and the CDN service:
|
||||
Use this only for compatibility with non-module environments.
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/@rrweb/record@latest/dist/record.umd.min.cjs"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb@2.0.0-alpha.20/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb@2.0.0-alpha.20/umd/rrweb.min.js"></script>
|
||||
```
|
||||
|
||||
The UMD build exposes global `rrweb`.
|
||||
|
||||
Legacy single-purpose UMD bundles:
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/@rrweb/record@2.0.0-alpha.20/umd/record.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@rrweb/replay@2.0.0-alpha.20/umd/replay.min.js"></script>
|
||||
```
|
||||
|
||||
The UMD globals are `rrwebRecord` and `rrwebReplay`.
|
||||
|
||||
#### Other packages
|
||||
|
||||
Besides the `rrweb` and `@rrweb/record` packages, rrweb also provides other packages for different usage.
|
||||
Besides the `@rrweb/record` and `@rrweb/replay` packages, rrweb also provides other packages for different usage.
|
||||
|
||||
- [rrweb](packages/rrweb): The core package of rrweb, including record and replay functions.
|
||||
- [rrweb-player](packages/rrweb-player): A GUI for rrweb, providing a timeline and buttons for things like pause, fast-forward, and speedup.
|
||||
- [rrweb-snapshot](packages/rrweb-snapshot): Handles snapshot and rebuilding features, converting the DOM and its state into a serializable data structure.
|
||||
- [rrdom](packages/rrdom): A virtual dom package rrweb.
|
||||
- [rrdom-nodejs](packages/rrdom-nodejs): The Node.js version of rrdom for server-side DOM operations.
|
||||
- [@rrweb/all](packages/all): A package that includes `rrweb` and `@rrweb/packer` for easy install.
|
||||
- [@rrweb/all](packages/all): A convenience package that includes `rrweb` and `@rrweb/packer`.
|
||||
- [@rrweb/record](packages/record): A package for recording rrweb sessions.
|
||||
- [@rrweb/replay](packages/replay): A package for replaying rrweb sessions.
|
||||
- [@rrweb/packer](packages/packer): A package for packing and unpacking rrweb data.
|
||||
@@ -57,14 +133,6 @@ Besides the `rrweb` and `@rrweb/record` packages, rrweb also provides other pack
|
||||
- [@rrweb/rrweb-plugin-canvas-webrtc-record](packages/plugins/rrweb-plugin-canvas-webrtc-record): A plugin for stream `<canvas>` via WebRTC.
|
||||
- [@rrweb/rrweb-plugin-canvas-webrtc-replay](packages/plugins/rrweb-plugin-canvas-webrtc-replay): A plugin for playing streamed `<canvas>` via WebRTC.
|
||||
|
||||
### NPM
|
||||
|
||||
```shell
|
||||
npm install --save rrweb
|
||||
```
|
||||
|
||||
rrweb provides both commonJS and ES modules bundles, which are easy to use with the popular bundlers.
|
||||
|
||||
### Compatibility Note
|
||||
|
||||
rrweb does **not** support IE11 and below because it uses the `MutationObserver` API which was supported by [these browsers](https://caniuse.com/#feat=mutationobserver).
|
||||
@@ -73,10 +141,14 @@ rrweb does **not** support IE11 and below because it uses the `MutationObserver`
|
||||
|
||||
### Record
|
||||
|
||||
The following sample code will use the variable `rrweb` which is the default exporter of this library.
|
||||
Use `record` from `@rrweb/record` in modern setups:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
```
|
||||
|
||||
```js
|
||||
record({
|
||||
emit(event) {
|
||||
// store the event in any way you like
|
||||
},
|
||||
@@ -88,7 +160,7 @@ During recording, the recorder will emit when there is some event incurred, all
|
||||
The `record` method returns a function which can be called to stop events from firing:
|
||||
|
||||
```js
|
||||
let stopFn = rrweb.record({
|
||||
let stopFn = record({
|
||||
emit(event) {
|
||||
if (events.length > 100) {
|
||||
// stop after 100 events
|
||||
@@ -103,7 +175,7 @@ A more real-world usage may look like this:
|
||||
```js
|
||||
let events = [];
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event) {
|
||||
// push event into the events array
|
||||
events.push(event);
|
||||
@@ -129,7 +201,7 @@ setInterval(save, 10 * 1000);
|
||||
|
||||
#### Options
|
||||
|
||||
The parameter of `rrweb.record` accepts the following options.
|
||||
The `record` function accepts the following options.
|
||||
|
||||
| key | default | description |
|
||||
| ------------------------ | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -182,7 +254,7 @@ By default, all the emitted events are required to replay a session and if you d
|
||||
// We use a two-dimensional array to store multiple events array
|
||||
const eventsMatrix = [[]];
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event, isCheckout) {
|
||||
// isCheckout is a flag to tell you the events has been checkout
|
||||
if (isCheckout) {
|
||||
@@ -217,7 +289,7 @@ Similarly, you can also configure `checkoutEveryNms` to capture the last N minut
|
||||
// We use a two-dimensional array to store multiple events array
|
||||
const eventsMatrix = [[]];
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event, isCheckout) {
|
||||
// isCheckout is a flag to tell you the events has been checkout
|
||||
if (isCheckout) {
|
||||
@@ -248,28 +320,36 @@ With the sample code above, you will finally get the last 5 to 10 minutes of eve
|
||||
|
||||
### Replay
|
||||
|
||||
You need to include the style sheet before replay:
|
||||
For bundler usage, include the style sheet in your app entry:
|
||||
|
||||
```js
|
||||
import '@rrweb/replay/dist/style.css';
|
||||
```
|
||||
|
||||
For browser/no-build usage, include the style sheet in HTML:
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/style.css"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/dist/style.css"
|
||||
/>
|
||||
```
|
||||
|
||||
And then initialize the replayer with the following code:
|
||||
And then initialize the replayer:
|
||||
|
||||
```js
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const events = YOUR_EVENTS;
|
||||
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
const replayer = new Replayer(events);
|
||||
replayer.play();
|
||||
```
|
||||
|
||||
#### Control the replayer by API
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
// play
|
||||
replayer.play();
|
||||
@@ -315,29 +395,48 @@ The replayer accepts options as its constructor's second parameter, and it has t
|
||||
|
||||
#### Use rrweb-player
|
||||
|
||||
Since rrweb's replayer ([@rrweb/replay](packages/replay/)) only provides a basic UI, you can choose [rrweb-player](packages/rrweb-player/) which is based on rrweb's public APIs but has a feature-rich replayer UI.
|
||||
Since `Replayer` from [@rrweb/replay](packages/replay/) only provides a basic UI, you can choose [rrweb-player](packages/rrweb-player/), which is based on rrweb's public APIs and provides a feature-rich replayer UI.
|
||||
|
||||
##### Installation
|
||||
|
||||
rrweb-player can also be included with `<script>`:
|
||||
Bundler / npm (recommended):
|
||||
|
||||
```shell
|
||||
npm install rrweb-player
|
||||
```
|
||||
|
||||
```js
|
||||
import rrwebPlayer from 'rrweb-player';
|
||||
import 'rrweb-player/dist/style.css';
|
||||
```
|
||||
|
||||
Browser without bundler (ESM + import maps):
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/index.js"></script>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"rrweb-player": "https://cdn.jsdelivr.net/npm/rrweb-player@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import rrwebPlayer from 'rrweb-player';
|
||||
</script>
|
||||
```
|
||||
|
||||
Or installed by using NPM:
|
||||
Legacy direct `<script>` include (UMD fallback):
|
||||
|
||||
```shell
|
||||
npm install --save rrweb-player
|
||||
```
|
||||
|
||||
```js
|
||||
import rrwebPlayer from 'rrweb-player';
|
||||
import 'rrweb-player/dist/style.css';
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb-player@2.0.0-alpha.20/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb-player@2.0.0-alpha.20/umd/rrweb-player.min.js"></script>
|
||||
```
|
||||
|
||||
##### Usage
|
||||
@@ -363,15 +462,15 @@ new rrwebPlayer({
|
||||
| speedOption | [1, 2, 4, 8] | speed options in UI |
|
||||
| showController | true | whether to show the controller UI |
|
||||
| tags | {} | customize the custom events style with a key-value map |
|
||||
| ... | - | all the rrweb Replayer options will be bypassed |
|
||||
| ... | - | all other Replayer options are forwarded |
|
||||
|
||||
#### Events
|
||||
|
||||
Developers may want to extend the rrweb's replayer or respond to its events. Such as giving notification when the replayer starts to skip inactive time.
|
||||
So rrweb expose a public API `on` which allow developers to listen to the events and customize the reactions, and it has the following events:
|
||||
Developers may want to extend the replayer or respond to its events, for example to notify users when inactive time starts being skipped.
|
||||
`Replayer` exposes a public API `on` that lets developers listen for events and customize behavior:
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
const replayer = new Replayer(events);
|
||||
replayer.on(EVENT_NAME, (payload) => {
|
||||
...
|
||||
})
|
||||
|
||||
190
guide.zh_CN.md
190
guide.zh_CN.md
@@ -4,42 +4,119 @@
|
||||
|
||||
## 安装
|
||||
|
||||
### 直接通过 `<script>` 引入
|
||||
| 目标 | 推荐包 |
|
||||
| ------------------------- | --------------------------------- |
|
||||
| 大多数项目(录制 + 回放) | `@rrweb/record` + `@rrweb/replay` |
|
||||
| 单包便捷接入 | `@rrweb/all` |
|
||||
| 仅遗留兼容 | `rrweb` |
|
||||
|
||||
推荐通过 jsdelivr 的 CDN 安装:
|
||||
在绝大多数生产架构中,录制端和回放端运行在不同的运行时/页面。请在被录制应用中安装 `@rrweb/record`,在回放应用中安装 `@rrweb/replay`(或 `rrweb-player`)。除非有明确的高级场景,一般不要在同一页面同时引入两者。
|
||||
|
||||
### 1) Bundler / npm(推荐)
|
||||
|
||||
```shell
|
||||
npm install @rrweb/record @rrweb/replay
|
||||
```
|
||||
|
||||
```js
|
||||
import { record } from '@rrweb/record';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import '@rrweb/replay/dist/style.css';
|
||||
```
|
||||
|
||||
如果你希望使用单一入口,也可以使用便捷包 `@rrweb/all`:
|
||||
|
||||
```shell
|
||||
npm install @rrweb/all
|
||||
```
|
||||
|
||||
```js
|
||||
import { record, Replayer } from '@rrweb/all';
|
||||
import '@rrweb/all/dist/style.css';
|
||||
```
|
||||
|
||||
`require(...)` / CommonJS 仍可作为兼容方案使用(由各包的 `exports`/`main` 提供),但 2.x 的主路径是 ESM。
|
||||
|
||||
### 2) 无 Bundler 的浏览器场景(推荐 no-build)
|
||||
|
||||
推荐使用 ES modules + import map + jsDelivr `+esm`:
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/style.css"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.umd.min.cjs"></script>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@rrweb/record": "https://cdn.jsdelivr.net/npm/@rrweb/record@latest/+esm",
|
||||
"@rrweb/replay": "https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import { record } from '@rrweb/record';
|
||||
|
||||
record({
|
||||
emit(event) {
|
||||
console.log(event);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
也可以在 URL 中指定具体的版本号,例如:
|
||||
也可以通过 `@rrweb/all` 便捷引入:
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb@2.0.0-alpha.14/dist/rrweb.umd.min.cjs"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/all@latest/dist/style.css"
|
||||
/>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@rrweb/all": "https://cdn.jsdelivr.net/npm/@rrweb/all@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import { record, Replayer } from '@rrweb/all';
|
||||
</script>
|
||||
```
|
||||
|
||||
#### 仅引入录制部分
|
||||
### 3) 传统直接 `<script>` 引入(Legacy / UMD 兼容)
|
||||
|
||||
rrweb 代码分为录制和回放两部分,大多数时候用户在被录制的应用中只需要引入录制部分代码。同样可以通过使用 @rrweb/record 包和 CDN 服务来实现:
|
||||
仅在不支持 ESM 的兼容场景中建议使用。
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/@rrweb/record@latest/dist/record.umd.min.cjs"></script>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb@2.0.0-alpha.20/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb@2.0.0-alpha.20/umd/rrweb.min.js"></script>
|
||||
```
|
||||
|
||||
该 UMD 构建会暴露全局变量 `rrweb`。
|
||||
|
||||
仅录制 / 仅回放的 UMD 兼容包:
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/@rrweb/record@2.0.0-alpha.20/umd/record.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@rrweb/replay@2.0.0-alpha.20/umd/replay.min.js"></script>
|
||||
```
|
||||
|
||||
对应全局变量分别是 `rrwebRecord` 和 `rrwebReplay`。
|
||||
|
||||
#### 其他包
|
||||
|
||||
除了 `rrweb` 和 `@rrweb/record` 包之外,rrweb 还提供了其他不同用途的包。
|
||||
除了 `@rrweb/record` 和 `@rrweb/replay` 包之外,rrweb 还提供了其他不同用途的包。
|
||||
|
||||
- [rrweb](packages/rrweb):rrweb 的核心包,包括录制和回放功能。
|
||||
- [rrweb-player](packages/rrweb-player):rrweb 的图形用户界面,提供时间线和暂停、快进、加速等按钮。
|
||||
- [rrweb-snapshot](packages/rrweb-snapshot):处理快照和重建功能,将 DOM 及其状态转换为可序列化的数据结构。
|
||||
- [rrdom](packages/rrdom):rrweb 的虚拟 dom 包。
|
||||
- [rrdom-nodejs](packages/rrdom-nodejs):用于服务器端 DOM 操作的 rrdom 的 Node.js 版本。
|
||||
- [@rrweb/all](packages/all):一个包含 `rrweb` 和 `@rrweb/packer`,便于安装的包。
|
||||
- [@rrweb/all](packages/all):一个包含 `rrweb` 和 `@rrweb/packer` 的便捷包。
|
||||
- [@rrweb/record](packages/record):一个用于录制 rrweb 会话的包。
|
||||
- [@rrweb/replay](packages/replay):一个用于回放 rrweb 会话的包。
|
||||
- [@rrweb/packer](packages/packer):一个用于打包和解包 rrweb 数据的包。
|
||||
@@ -54,14 +131,6 @@ rrweb 代码分为录制和回放两部分,大多数时候用户在被录制
|
||||
- [@rrweb/rrweb-plugin-canvas-webrtc-record](packages/plugins/rrweb-plugin-canvas-webrtc-record):一个用于通过 WebRTC 流式传输 `<canvas>` 的插件。
|
||||
- [@rrweb/rrweb-plugin-canvas-webrtc-replay](packages/plugins/rrweb-plugin-canvas-webrtc-replay):一个用于通过 WebRTC 播放流式 `<canvas>` 的插件。
|
||||
|
||||
### 通过 npm 引入
|
||||
|
||||
```shell
|
||||
npm install --save rrweb
|
||||
```
|
||||
|
||||
rrweb 同时提供 commonJS 和 ES modules 两种格式的打包文件,易于和常见的打包工具配合使用。
|
||||
|
||||
### 兼容性
|
||||
|
||||
由于使用 `MutationObserver` API,rrweb 不支持 IE11 以下的浏览器。可以从[这里](https://caniuse.com/#feat=mutationobserver)找到兼容的浏览器列表。
|
||||
@@ -70,10 +139,14 @@ rrweb 同时提供 commonJS 和 ES modules 两种格式的打包文件,易于
|
||||
|
||||
### 录制
|
||||
|
||||
如果通过 `<script>` 的方式仅引入录制部分,那么可以访问到全局变量 `rrwebRecord`,它和全量引入时的 `rrweb.record` 使用方式完全一致,以下示例代码将使用后者。
|
||||
现代用法建议直接使用 `@rrweb/record` 的 `record`:
|
||||
|
||||
```js
|
||||
rrweb.record({
|
||||
import { record } from '@rrweb/record';
|
||||
```
|
||||
|
||||
```js
|
||||
record({
|
||||
emit(event) {
|
||||
// 用任意方式存储 event
|
||||
},
|
||||
@@ -85,7 +158,7 @@ rrweb 在录制时会不断将各类 event 传递给配置的 emit 方法,你
|
||||
调用 `record` 方法将返回一个函数,调用该函数可以终止录制:
|
||||
|
||||
```js
|
||||
let stopFn = rrweb.record({
|
||||
let stopFn = record({
|
||||
emit(event) {
|
||||
if (events.length > 100) {
|
||||
// 当事件数量大于 100 时停止录制
|
||||
@@ -100,7 +173,7 @@ let stopFn = rrweb.record({
|
||||
```js
|
||||
let events = [];
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event) {
|
||||
// 将 event 存入 events 数组中
|
||||
events.push(event);
|
||||
@@ -126,7 +199,7 @@ setInterval(save, 10 * 1000);
|
||||
|
||||
#### 配置参数
|
||||
|
||||
`rrweb.record(config)` 的 config 部分接受以下参数
|
||||
`record(config)` 的 config 部分接受以下参数
|
||||
|
||||
| key | 默认值 | 功能 |
|
||||
| ------------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -178,7 +251,7 @@ setInterval(save, 10 * 1000);
|
||||
// 使用二维数组来存放多个 event 数组
|
||||
const eventsMatrix = [[]];
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event, isCheckout) {
|
||||
// isCheckout 是一个标识,告诉你重新制作了快照
|
||||
if (isCheckout) {
|
||||
@@ -213,7 +286,7 @@ window.onerror = function () {
|
||||
// 使用二维数组来存放多个 event 数组
|
||||
const eventsMatrix = [[]];
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit(event, isCheckout) {
|
||||
// isCheckout 是一个标识,告诉你重新制作了快照
|
||||
if (isCheckout) {
|
||||
@@ -244,28 +317,36 @@ window.onerror = function () {
|
||||
|
||||
### 回放
|
||||
|
||||
回放时需要引入对应的 CSS 文件:
|
||||
在 bundler 场景下,可在入口文件中引入 CSS:
|
||||
|
||||
```js
|
||||
import '@rrweb/replay/dist/style.css';
|
||||
```
|
||||
|
||||
在浏览器 no-build 场景下,也可以在 HTML 中引入 CSS:
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/style.css"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/dist/style.css"
|
||||
/>
|
||||
```
|
||||
|
||||
再通过以下 JS 代码初始化 replayer:
|
||||
然后通过以下 JS 代码初始化 replayer:
|
||||
|
||||
```js
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
|
||||
const events = YOUR_EVENTS;
|
||||
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
const replayer = new Replayer(events);
|
||||
replayer.play();
|
||||
```
|
||||
|
||||
#### 使用 API 控制回放
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
const replayer = new Replayer(events);
|
||||
|
||||
// 播放
|
||||
replayer.play();
|
||||
@@ -285,7 +366,7 @@ replayer.destroy();
|
||||
|
||||
#### 配置参数
|
||||
|
||||
可以通过 `new rrweb.Replayer(events, options)` 的方式向 rrweb 传递回放时的配置参数,具体配置如下:
|
||||
可以通过 `new Replayer(events, options)` 的方式向 rrweb 传递回放时的配置参数,具体配置如下:
|
||||
|
||||
| key | 默认值 | 功能 |
|
||||
| ------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -313,25 +394,44 @@ rrweb 自带的回放只提供所有的 JS API 以及最基本的 UI,如果需
|
||||
|
||||
##### 安装
|
||||
|
||||
rrweb-player 同样可以使用 CDN 方式安装:
|
||||
Bundler / npm(推荐):
|
||||
|
||||
```shell
|
||||
npm install rrweb-player
|
||||
```
|
||||
|
||||
```js
|
||||
import rrwebPlayer from 'rrweb-player';
|
||||
import 'rrweb-player/dist/style.css';
|
||||
```
|
||||
|
||||
无 bundler 的浏览器场景(ESM + import maps):
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/index.js"></script>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"rrweb-player": "https://cdn.jsdelivr.net/npm/rrweb-player@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import rrwebPlayer from 'rrweb-player';
|
||||
</script>
|
||||
```
|
||||
|
||||
或者通过 npm 安装:
|
||||
Legacy 直接 `<script>` 引入(UMD 兼容):
|
||||
|
||||
```shell
|
||||
npm install --save rrweb-player
|
||||
```
|
||||
|
||||
```js
|
||||
import rrwebPlayer from 'rrweb-player';
|
||||
import 'rrweb-player/dist/style.css';
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb-player@2.0.0-alpha.20/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb-player@2.0.0-alpha.20/umd/rrweb-player.min.js"></script>
|
||||
```
|
||||
|
||||
##### 使用
|
||||
@@ -359,16 +459,16 @@ new rrwebPlayer({
|
||||
| speedOption | [1, 2, 4, 8] | 倍速播放可选值 |
|
||||
| showController | true | 是否显示播放器控制 UI |
|
||||
| tags | {} | 可以以 key value 的形式展示自定义事件在时间轴上的颜色 |
|
||||
| ... | - | 其它所有 rrweb Replayer 的配置参数均可透传 |
|
||||
| ... | - | 其它所有 Replayer 的配置参数均可透传 |
|
||||
|
||||
#### 事件
|
||||
|
||||
开发者可能希望监听回放时的各类事件,例如在跳过无用户操作的时间时给用户一些提示。
|
||||
|
||||
rrweb 的 Replayer 提供了 `on` API 用于提供该功能
|
||||
Replayer 提供了 `on` API 用于实现该功能
|
||||
|
||||
```js
|
||||
const replayer = new rrweb.Replayer(events);
|
||||
const replayer = new Replayer(events);
|
||||
replayer.on(EVENT_NAME, (payload) => {
|
||||
...
|
||||
})
|
||||
|
||||
329
index.html
Normal file
329
index.html
Normal file
@@ -0,0 +1,329 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>rrweb 示例</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Arial, sans-serif;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
border-bottom: 3px solid #007bff;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
.panel {
|
||||
flex: 1;
|
||||
border: 1px solid #ddd;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
background: white;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
.test-area {
|
||||
min-height: 300px;
|
||||
border: 2px dashed #007bff;
|
||||
padding: 20px;
|
||||
margin: 15px 0;
|
||||
border-radius: 8px;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
button {
|
||||
padding: 12px 24px;
|
||||
margin: 8px;
|
||||
cursor: pointer;
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
button:hover {
|
||||
background: #0056b3;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0,123,255,0.4);
|
||||
}
|
||||
button:disabled {
|
||||
background: #6c757d;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.record-btn {
|
||||
background: #28a745;
|
||||
min-width: 120px;
|
||||
}
|
||||
.record-btn:hover {
|
||||
background: #1e7e34;
|
||||
}
|
||||
.stop-btn {
|
||||
background: #dc3545;
|
||||
min-width: 120px;
|
||||
}
|
||||
.stop-btn:hover {
|
||||
background: #b02a37;
|
||||
}
|
||||
.status-bar {
|
||||
padding: 15px;
|
||||
margin: 15px 0;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
.status-bar.idle {
|
||||
background: #e2e3e5;
|
||||
color: #383d41;
|
||||
}
|
||||
.status-bar.recording {
|
||||
background: #d4edda;
|
||||
color: #155724;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.7; }
|
||||
}
|
||||
.info-box {
|
||||
padding: 15px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.info-box h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.info-box ul {
|
||||
margin: 10px 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🎥 rrweb 录制与回放</h1>
|
||||
|
||||
<div class="container">
|
||||
<div class="panel">
|
||||
<h2>📹 录制区域</h2>
|
||||
<div class="test-area">
|
||||
<h3 style="margin-top:0;">在此区域进行操作</h3>
|
||||
<p>点击按钮、输入文字,所有操作都会被记录:</p>
|
||||
|
||||
<button onclick="changeColor()">🎨 随机变色</button>
|
||||
<button onclick="addCounter()">🔢 添加计数器</button>
|
||||
<button onclick="showAlert()">💬 测试弹窗</button>
|
||||
|
||||
<div id="counters" style="display:flex; gap:10px; flex-wrap:wrap; margin-top:15px;"></div>
|
||||
</div>
|
||||
|
||||
<div id="status-bar" class="status-bar idle">
|
||||
⚪ 等待录制
|
||||
</div>
|
||||
|
||||
<div style="margin: 15px 0;">
|
||||
<button id="start-btn" class="record-btn" onclick="startRecording()">▶ 开始录制</button>
|
||||
<button id="stop-btn" class="stop-btn" onclick="stopRecording()" disabled>⏹ 停止录制</button>
|
||||
<button onclick="clearAll()">🗑️ 清空</button>
|
||||
</div>
|
||||
|
||||
<div class="info-box">
|
||||
<h3>✨ 功能说明</h3>
|
||||
<ul>
|
||||
<li>点击"开始录制"开始记录</li>
|
||||
<li>点击"停止录制"结束记录</li>
|
||||
<li>右侧会自动回放录制的操作</li>
|
||||
<li>支持播放速度控制</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<h2>▶️ 回放区域</h2>
|
||||
<div id="replayer" style="width:100%; height:400px; border:2px solid #007bff; border-radius:8px; background:#f8f9fa;"></div>
|
||||
<div class="info-box" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
|
||||
<h3>🎬 回放控制</h3>
|
||||
<p>播放器提供完整控制:</p>
|
||||
<ul>
|
||||
<li>时间轴拖动:点击任意位置跳转</li>
|
||||
<li>播放/暂停:控制播放状态</li>
|
||||
<li>速度控制:0.5x、1x、2x、4x</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- rrweb CDN - 使用非模块化版本 -->
|
||||
<link rel="stylesheet" href="./packages/rrweb-player/dist/style.css">
|
||||
<script src="./packages/rrweb/dist/rrweb.umd.cjs"></script>
|
||||
<script src="./packages/rrweb-player/dist/rrweb-player.umd.cjs"></script>
|
||||
|
||||
<script>
|
||||
let events = [];
|
||||
let stopRecordingFn = null;
|
||||
let player = null;
|
||||
|
||||
// 等待 rrweb 加载完成
|
||||
function initWhenReady() {
|
||||
if (
|
||||
typeof rrweb !== 'undefined' &&
|
||||
typeof rrweb.record === 'function' &&
|
||||
typeof rrwebPlayer !== 'undefined'
|
||||
) {
|
||||
console.log('rrweb 与 rrweb-player 已加载,准备就绪');
|
||||
setupButtons();
|
||||
} else {
|
||||
console.log('等待 rrweb / rrweb-player 加载...');
|
||||
setTimeout(initWhenReady, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function getPlayerConstructor() {
|
||||
if (typeof rrwebPlayer === 'function') {
|
||||
return rrwebPlayer;
|
||||
}
|
||||
if (rrwebPlayer && typeof rrwebPlayer.Player === 'function') {
|
||||
return rrwebPlayer.Player;
|
||||
}
|
||||
if (rrwebPlayer && typeof rrwebPlayer.default === 'function') {
|
||||
return rrwebPlayer.default;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function setupButtons() {
|
||||
document.getElementById('start-btn').onclick = startRecording;
|
||||
document.getElementById('stop-btn').onclick = stopRecording;
|
||||
}
|
||||
|
||||
function destroyPlayer() {
|
||||
const target = document.getElementById('replayer');
|
||||
if (player && typeof player.$destroy === 'function') {
|
||||
player.$destroy();
|
||||
}
|
||||
player = null;
|
||||
target.innerHTML = '';
|
||||
}
|
||||
|
||||
function renderReplay() {
|
||||
if (!events.length) {
|
||||
return;
|
||||
}
|
||||
const PlayerConstructor = getPlayerConstructor();
|
||||
if (!PlayerConstructor) {
|
||||
throw new Error('rrweb-player 未正确加载');
|
||||
}
|
||||
destroyPlayer();
|
||||
const target = document.getElementById('replayer');
|
||||
player = new PlayerConstructor({
|
||||
target,
|
||||
props: {
|
||||
events,
|
||||
autoPlay: true,
|
||||
showController: true,
|
||||
speed: 1,
|
||||
speedOption: [0.5, 1, 2, 4],
|
||||
width: 1000,
|
||||
height: 400,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 开始录制
|
||||
function startRecording() {
|
||||
events = [];
|
||||
destroyPlayer();
|
||||
try {
|
||||
stopRecordingFn = rrweb.record({
|
||||
emit(event) {
|
||||
events.push(event);
|
||||
},
|
||||
recordCanvas: true,
|
||||
recordCrossOriginIframes: true,
|
||||
recordAfter: 'DOMContentLoaded',
|
||||
ignoreSelector: '.status-bar, .info-box, #replayer',
|
||||
});
|
||||
updateStatus('🔴 正在录制...', 'recording');
|
||||
document.getElementById('start-btn').disabled = true;
|
||||
document.getElementById('stop-btn').disabled = false;
|
||||
console.log('录制已启动');
|
||||
} catch (error) {
|
||||
updateStatus('⚪ 等待录制', 'idle');
|
||||
console.error('启动录制失败:', error);
|
||||
alert('启动录制失败: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 停止录制
|
||||
function stopRecording() {
|
||||
if (typeof stopRecordingFn === 'function') {
|
||||
stopRecordingFn();
|
||||
stopRecordingFn = null;
|
||||
updateStatus(`✅ 已录制 ${events.length} 个事件`, 'idle');
|
||||
document.getElementById('start-btn').disabled = false;
|
||||
document.getElementById('stop-btn').disabled = true;
|
||||
try {
|
||||
renderReplay();
|
||||
console.log('回放已初始化');
|
||||
} catch (error) {
|
||||
console.error('初始化回放失败:', error);
|
||||
alert('初始化回放失败: ' + error.message);
|
||||
return;
|
||||
}
|
||||
console.log('录制完成,事件数量:', events.length);
|
||||
console.log('事件列表:', events);
|
||||
alert(`录制完成!\n共记录了 ${events.length} 个事件。\n请在右侧查看回放与控制条。`);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
function updateStatus(text, type) {
|
||||
const statusEl = document.getElementById('status-bar');
|
||||
statusEl.className = `status-bar ${type}`;
|
||||
statusEl.textContent = text;
|
||||
}
|
||||
|
||||
// 测试函数
|
||||
function changeColor() {
|
||||
const colors = ['#f8f9fa', '#e3f2fd', '#fff3cd', '#d1ecf1d', '#f8d7da', '#d6d8db', '#cce5ff', '#e2d9f7'];
|
||||
document.querySelector('.test-area').style.background = colors[Math.floor(Math.random() * colors.length)];
|
||||
}
|
||||
|
||||
function addCounter() {
|
||||
const counters = document.getElementById('counters');
|
||||
const count = counters.children.length;
|
||||
const div = document.createElement('div');
|
||||
div.style.cssText = 'padding:10px 20px; background:white; border:2px solid #007bff; border-radius:8px; font-size:24px; font-weight:bold; cursor:pointer;';
|
||||
div.innerHTML = `<span>#${count + 1}</span>`;
|
||||
div.onclick = function() {
|
||||
const span = this.querySelector('span');
|
||||
span.innerText = parseInt(span.innerText) + 1;
|
||||
};
|
||||
counters.appendChild(div);
|
||||
}
|
||||
|
||||
function showAlert() {
|
||||
alert('这是一个测试弹窗!\nrrweb 会记录并回放这个弹窗操作。');
|
||||
}
|
||||
|
||||
function clearAll() {
|
||||
events = [];
|
||||
destroyPlayer();
|
||||
updateStatus('⚪ 等待录制', 'idle');
|
||||
}
|
||||
|
||||
// 开始初始化
|
||||
setTimeout(initWhenReady, 100);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +1,15 @@
|
||||
# @rrweb/all
|
||||
|
||||
Convenience package that includes a bundle of rrweb packages.
|
||||
For most new integrations, prefer `@rrweb/record` + `@rrweb/replay` first, and use `@rrweb/all` when you want a single-package setup.
|
||||
|
||||
| Use case | Package choice |
|
||||
| --------------------------------------------------- | --------------------------------- |
|
||||
| Most new apps (explicit record/replay dependencies) | `@rrweb/record` + `@rrweb/replay` |
|
||||
| Quick setup with one import | `@rrweb/all` |
|
||||
| Legacy compatibility | `rrweb` |
|
||||
|
||||
In most production setups, recorder and replayer are deployed to different pages/apps. Use `@rrweb/record` on recorded pages and `@rrweb/replay` (or `rrweb-player`) on replay pages. Use `@rrweb/all` when you intentionally want one package for convenience (for example demos, tooling, or simplified setups).
|
||||
|
||||
Includes the following packages:
|
||||
|
||||
@@ -11,19 +20,47 @@ Includes the following packages:
|
||||
|
||||
## Installation
|
||||
|
||||
### 1) Bundler / npm
|
||||
|
||||
```bash
|
||||
npm install @rrweb/all
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import { record, replay, pack, unpack } from '@rrweb/all';
|
||||
|
||||
// use record, replay, pack, unpack as you would with the individual packages.
|
||||
import { record, Replayer, pack, unpack } from '@rrweb/all';
|
||||
import '@rrweb/all/dist/style.css';
|
||||
```
|
||||
|
||||
See the [guide](../../guide.md) for more info on rrweb.
|
||||
For API details and examples, see the [guide](../../guide.md).
|
||||
|
||||
### 2) Browser Without Bundler (ESM + import maps)
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/all@latest/dist/style.css"
|
||||
/>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@rrweb/all": "https://cdn.jsdelivr.net/npm/@rrweb/all@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import { record, Replayer, pack, unpack } from '@rrweb/all';
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3) Legacy Direct `<script>` Include (UMD fallback)
|
||||
|
||||
Use this only for compatibility with non-module environments.
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/@rrweb/all@latest/umd/all.min.js"></script>
|
||||
```
|
||||
|
||||
The legacy UMD global is `rrweb`, so you will need to prefix the example APIs, e.g. `rrweb.record`, `new rrweb.Replayer(...)`, `rrweb.pack`, and `rrweb.unpack`, rather than using these functions directly.
|
||||
|
||||
## Sponsors
|
||||
|
||||
|
||||
@@ -44,13 +44,14 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"build",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"puppeteer": "^20.9.0",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1",
|
||||
"vitest": "^1.4.0",
|
||||
"typescript": "^5.4.5"
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
"package.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1",
|
||||
"vitest": "^1.4.0",
|
||||
"typescript": "^5.4.5"
|
||||
|
||||
@@ -13,8 +13,8 @@ https://user-images.githubusercontent.com/4106/186701616-fd71a107-5d53-423c-ba09
|
||||
```js
|
||||
// Record side
|
||||
|
||||
import rrweb from 'rrweb';
|
||||
import { RRWebPluginCanvasWebRTCRecord } from 'rrweb-plugin-canvas-webrtc-record';
|
||||
import { record } from '@rrweb/record';
|
||||
import { RRWebPluginCanvasWebRTCRecord } from '@rrweb/rrweb-plugin-canvas-webrtc-record';
|
||||
|
||||
const webRTCRecordPlugin = new RRWebPluginCanvasWebRTCRecord({
|
||||
signalSendCallback: (msg) => {
|
||||
@@ -24,7 +24,7 @@ const webRTCRecordPlugin = new RRWebPluginCanvasWebRTCRecord({
|
||||
},
|
||||
});
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit: (event) => {
|
||||
// send these events to the `replayer.addEvent(event)`, how you do that is up to you
|
||||
// you can send them to a server for example which can then send them to the replayer
|
||||
@@ -42,8 +42,8 @@ rrweb.record({
|
||||
|
||||
```js
|
||||
// Replay side
|
||||
import rrweb from 'rrweb';
|
||||
import { RRWebPluginCanvasWebRTCReplay } from 'rrweb-plugin-canvas-webrtc-replay';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import { RRWebPluginCanvasWebRTCReplay } from '@rrweb/rrweb-plugin-canvas-webrtc-replay';
|
||||
|
||||
const webRTCReplayPlugin = new RRWebPluginCanvasWebRTCReplay({
|
||||
canvasFoundCallback(canvas, context) {
|
||||
@@ -59,7 +59,7 @@ const webRTCReplayPlugin = new RRWebPluginCanvasWebRTCReplay({
|
||||
},
|
||||
});
|
||||
|
||||
const replayer = new rrweb.Replayer([], {
|
||||
const replayer = new Replayer([], {
|
||||
UNSAFE_replayCanvas: true, // turn canvas replay on!
|
||||
liveMode: true, // live mode is needed to stream events to the replayer
|
||||
plugins: [webRTCReplayPlugin.initPlugin()],
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -45,7 +46,7 @@
|
||||
"devDependencies": {
|
||||
"rrweb": "^2.0.0-alpha.20",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -13,7 +13,7 @@ https://user-images.githubusercontent.com/4106/186701616-fd71a107-5d53-423c-ba09
|
||||
```js
|
||||
// Record side
|
||||
|
||||
import rrweb from 'rrweb';
|
||||
import { record } from '@rrweb/record';
|
||||
import { RRWebPluginCanvasWebRTCRecord } from '@rrweb/rrweb-plugin-canvas-webrtc-record';
|
||||
|
||||
const webRTCRecordPlugin = new RRWebPluginCanvasWebRTCRecord({
|
||||
@@ -24,7 +24,7 @@ const webRTCRecordPlugin = new RRWebPluginCanvasWebRTCRecord({
|
||||
},
|
||||
});
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit: (event) => {
|
||||
// send these events to the `replayer.addEvent(event)`, how you do that is up to you
|
||||
// you can send them to a server for example which can then send them to the replayer
|
||||
@@ -42,7 +42,7 @@ rrweb.record({
|
||||
|
||||
```js
|
||||
// Replay side
|
||||
import rrweb from 'rrweb';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import { RRWebPluginCanvasWebRTCReplay } from '@rrweb/rrweb-plugin-canvas-webrtc-replay';
|
||||
|
||||
const webRTCReplayPlugin = new RRWebPluginCanvasWebRTCReplay({
|
||||
@@ -59,7 +59,7 @@ const webRTCReplayPlugin = new RRWebPluginCanvasWebRTCReplay({
|
||||
},
|
||||
});
|
||||
|
||||
const replayer = new rrweb.Replayer([], {
|
||||
const replayer = new Replayer([], {
|
||||
UNSAFE_replayCanvas: true, // turn canvas replay on!
|
||||
liveMode: true, // live mode is needed to stream events to the replayer
|
||||
plugins: [webRTCReplayPlugin.initPlugin()],
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -45,7 +46,7 @@
|
||||
"devDependencies": {
|
||||
"rrweb": "^2.0.0-alpha.20",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -47,7 +48,7 @@
|
||||
"devDependencies": {
|
||||
"rrweb": "^2.0.0-alpha.20",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1",
|
||||
"vitest": "^1.4.0",
|
||||
"puppeteer": "^20.9.0"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -46,7 +47,7 @@
|
||||
"@rrweb/rrweb-plugin-console-record": "^2.0.0-alpha.20",
|
||||
"rrweb": "^2.0.0-alpha.20",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -12,10 +12,10 @@ npm install @rrweb/rrweb-plugin-sequential-id-record
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import rrweb from 'rrweb';
|
||||
import { record } from '@rrweb/record';
|
||||
import { getRecordSequentialIdPlugin } from '@rrweb/rrweb-plugin-sequential-id-record';
|
||||
|
||||
rrweb.record({
|
||||
record({
|
||||
emit: function emit(event) {
|
||||
// send events to server
|
||||
},
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -45,7 +46,7 @@
|
||||
"devDependencies": {
|
||||
"rrweb": "^2.0.0-alpha.20",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -12,10 +12,10 @@ npm install @rrweb/rrweb-plugin-sequential-id-replay
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import rrweb from 'rrweb';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import { getReplaySequentialIdPlugin } from '@rrweb/rrweb-plugin-sequential-id-replay';
|
||||
|
||||
const replayer = new rrweb.Replayer(events, {
|
||||
const replayer = new Replayer(events, {
|
||||
plugins: [
|
||||
getReplaySequentialIdPlugin({
|
||||
// make sure this is the same as the record side
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -46,7 +47,7 @@
|
||||
"@rrweb/rrweb-plugin-sequential-id-record": "^2.0.0-alpha.20",
|
||||
"rrweb": "^2.0.0-alpha.20",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -5,10 +5,41 @@ See the [guide](../../guide.md) for more info on rrweb.
|
||||
|
||||
## Installation
|
||||
|
||||
### 1) Bundler / npm (Recommended)
|
||||
|
||||
```bash
|
||||
npm install @rrweb/record
|
||||
```
|
||||
|
||||
```js
|
||||
import { record } from '@rrweb/record';
|
||||
```
|
||||
|
||||
### 2) Browser Without Bundler (ESM + import maps)
|
||||
|
||||
```html
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@rrweb/record": "https://cdn.jsdelivr.net/npm/@rrweb/record@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import { record } from '@rrweb/record';
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3) Legacy Direct `<script>` Include (UMD fallback)
|
||||
|
||||
Use this only for compatibility with non-module environments.
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/@rrweb/record@latest/umd/record.min.js"></script>
|
||||
```
|
||||
|
||||
The legacy UMD global is `rrwebRecord`.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
|
||||
@@ -44,12 +44,13 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"puppeteer": "^20.9.0",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1",
|
||||
"vitest": "^1.4.0",
|
||||
"typescript": "^5.4.5"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import path from 'path';
|
||||
import config from '../../vite.config.default';
|
||||
|
||||
export default config(path.resolve(__dirname, 'src/index.ts'), 'rrweb');
|
||||
export default config(path.resolve(__dirname, 'src/index.ts'), 'rrwebRecord');
|
||||
|
||||
@@ -5,14 +5,55 @@ See the [guide](../../guide.md) for more info on rrweb.
|
||||
|
||||
## Installation
|
||||
|
||||
### 1) Bundler / npm (Recommended)
|
||||
|
||||
```bash
|
||||
npm install @rrweb/replay
|
||||
```
|
||||
|
||||
```js
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import '@rrweb/replay/dist/style.css';
|
||||
```
|
||||
|
||||
### 2) Browser Without Bundler (ESM + import maps)
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/dist/style.css"
|
||||
/>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@rrweb/replay": "https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3) Legacy Direct `<script>` Include (UMD fallback)
|
||||
|
||||
Use this only for compatibility with non-module environments.
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/umd/replay.min.js"></script>
|
||||
```
|
||||
|
||||
The legacy UMD global is `rrwebReplay`.
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import '@rrweb/replay/dist/style.css';
|
||||
|
||||
const replayer = new Replayer(events, {
|
||||
// options
|
||||
|
||||
@@ -45,12 +45,13 @@
|
||||
"./dist/style.css": "./dist/style.css"
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"puppeteer": "^20.9.0",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1",
|
||||
"vitest": "^1.4.0",
|
||||
"typescript": "^5.4.5"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import path from 'path';
|
||||
import config from '../../vite.config.default';
|
||||
|
||||
export default config(path.resolve(__dirname, 'src/index.ts'), 'rrweb');
|
||||
export default config(path.resolve(__dirname, 'src/index.ts'), 'rrwebReplay');
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -46,7 +47,7 @@
|
||||
"compare-versions": "^4.1.3",
|
||||
"eslint": "^8.15.0",
|
||||
"puppeteer": "^9.1.1",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1",
|
||||
"vitest": "^1.4.0",
|
||||
"typescript": "^5.4.5"
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -48,7 +49,7 @@
|
||||
"eslint": "^8.15.0",
|
||||
"puppeteer": "^17.1.3",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -57,22 +57,27 @@ function getHtml(events: Array<eventWithTime>, config?: RRvideoConfig): string {
|
||||
)};
|
||||
/*-->*/
|
||||
const userConfig = ${JSON.stringify(config?.rrwebPlayer || {})};
|
||||
window.replayer = new rrwebPlayer.Player({
|
||||
target: document.body,
|
||||
width: userConfig.width,
|
||||
height: userConfig.height,
|
||||
props: {
|
||||
...userConfig,
|
||||
events,
|
||||
showController: false,
|
||||
},
|
||||
});
|
||||
window.replayer.addEventListener('finish', () => window.onReplayFinish());
|
||||
window.replayer.addEventListener('ui-update-progress', (payload)=> window.onReplayProgressUpdate
|
||||
(payload));
|
||||
window.replayer.addEventListener('resize',()=>document.querySelector('.replayer-wrapper').style.transform = 'scale(${
|
||||
(config?.resolutionRatio ?? 1) * MaxScaleValue
|
||||
}) translate(-50%, -50%)');
|
||||
try {
|
||||
window.replayer = new rrwebPlayer({
|
||||
target: document.body,
|
||||
props: {
|
||||
...userConfig,
|
||||
events,
|
||||
showController: false,
|
||||
autoPlay: false,
|
||||
},
|
||||
});
|
||||
window.replayer.addEventListener('finish', () => window.onReplayFinish());
|
||||
window.replayer.addEventListener('ui-update-progress', (payload)=> window.onReplayProgressUpdate(payload));
|
||||
window.replayer.addEventListener('resize', () => document.querySelector('.replayer-wrapper').style.transform = 'scale(${
|
||||
(config?.resolutionRatio ?? 1) * MaxScaleValue
|
||||
}) translate(-50%, -50%)');
|
||||
// Start playback after event listeners are attached
|
||||
window.replayer.play();
|
||||
} catch (error) {
|
||||
console.error('Error initializing replayer:', error);
|
||||
window.onReplayFinish();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -139,6 +144,16 @@ export async function transformToVideo(options: RRvideoConfig) {
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto('about:blank');
|
||||
// Listen to console messages from the page
|
||||
page.on('console', (msg) => {
|
||||
console.log('[PAGE CONSOLE]', msg.type(), msg.text());
|
||||
});
|
||||
|
||||
// Listen to page errors
|
||||
page.on('pageerror', (error) => {
|
||||
console.error('[PAGE ERROR]', error.message);
|
||||
});
|
||||
|
||||
await page.exposeFunction(
|
||||
'onReplayProgressUpdate',
|
||||
(data: { payload: number }) => {
|
||||
@@ -147,12 +162,41 @@ export async function transformToVideo(options: RRvideoConfig) {
|
||||
);
|
||||
|
||||
// Wait for the replay to finish
|
||||
await new Promise<void>(
|
||||
(resolve) =>
|
||||
void page
|
||||
.exposeFunction('onReplayFinish', () => resolve())
|
||||
.then(() => page.setContent(getHtml(events, config))),
|
||||
);
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const timeoutBuffer = 120000; // 2 minute timeout buffer
|
||||
const videoStartTime = events[0]?.timestamp;
|
||||
const videoEndTime = events[events.length - 1]?.timestamp;
|
||||
const videoDuration = videoEndTime - videoStartTime;
|
||||
const videoPlaybackSpeed = options.rrwebPlayer?.speed || 1;
|
||||
const expectedPlaybackTime = videoDuration / videoPlaybackSpeed;
|
||||
console.log(
|
||||
`[DEBUG] Expected playback time: ${expectedPlaybackTime}ms (video duration: ${videoDuration}ms, playback speed: ${videoPlaybackSpeed}x)`,
|
||||
);
|
||||
const totalTimeout = expectedPlaybackTime + timeoutBuffer;
|
||||
const timeout = setTimeout(() => {
|
||||
console.error('[DEBUG] Replay timeout - finish event never fired');
|
||||
reject(new Error('Replay timeout'));
|
||||
}, totalTimeout); // playback + 2 minute timeout
|
||||
|
||||
void page
|
||||
.exposeFunction('onReplayFinish', () => {
|
||||
console.log('[DEBUG] Replay finished');
|
||||
clearTimeout(timeout);
|
||||
resolve();
|
||||
})
|
||||
.then(() => {
|
||||
console.log('[DEBUG] Setting page content');
|
||||
return page.setContent(getHtml(events, config));
|
||||
})
|
||||
.then(() => {
|
||||
console.log('[DEBUG] Page content set successfully');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('[DEBUG] Error setting page content:', err);
|
||||
clearTimeout(timeout);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
const videoPath = (await page.video()?.path()) || '';
|
||||
const cleanFiles = async (videoPath: string) => {
|
||||
await fs.remove(videoPath);
|
||||
|
||||
@@ -18,18 +18,19 @@ describe('should be able to run cli', () => {
|
||||
await fs.remove(path.resolve(__dirname, './generated'));
|
||||
});
|
||||
|
||||
const execOptions = { stdio: 'pipe', timeout: 60_000 } as const;
|
||||
const execOptions = { timeout: 60_000 } as const;
|
||||
const execOptionsWithOutput = { ...execOptions, stdio: 'inherit' } as const;
|
||||
|
||||
it('should throw error without input path', () => {
|
||||
expect(() => {
|
||||
execSync('node ./build/cli.js', execOptions);
|
||||
execSync('node ./build/cli.js', { ...execOptions, stdio: 'pipe' });
|
||||
}).toThrowError(/.*please pass --input to your rrweb events file.*/);
|
||||
});
|
||||
|
||||
it('should generate a video without output path', () => {
|
||||
execSync(
|
||||
'node ./build/cli.js --input ./test/generated/example.json',
|
||||
execOptions,
|
||||
execOptionsWithOutput,
|
||||
);
|
||||
const outputFile = path.resolve(__dirname, '../rrvideo-output.webm');
|
||||
expect(fs.existsSync(outputFile)).toBe(true);
|
||||
@@ -40,7 +41,7 @@ describe('should be able to run cli', () => {
|
||||
const outputFile = path.resolve(__dirname, './generated/output.webm');
|
||||
execSync(
|
||||
`node ./build/cli.js --input ./test/generated/example.json --output ${outputFile}`,
|
||||
execOptions,
|
||||
execOptionsWithOutput,
|
||||
);
|
||||
expect(fs.existsSync(outputFile)).toBe(true);
|
||||
fs.removeSync(outputFile);
|
||||
|
||||
824
packages/rrweb-player/.svelte-kit/ambient.d.ts
vendored
824
packages/rrweb-player/.svelte-kit/ambient.d.ts
vendored
@@ -26,261 +26,179 @@
|
||||
* ```
|
||||
*/
|
||||
declare module '$env/static/private' {
|
||||
export const SUDO_GID: string;
|
||||
export const GITHUB_STATE: string;
|
||||
export const COPILOT_AGENT_ACTION: string;
|
||||
export const npm_package_scripts_test_cross_platform_build: string;
|
||||
export const npm_package_devDependencies_rollup: string;
|
||||
export const npm_package_devDependencies__types_node: string;
|
||||
export const COPILOT_AGENT_START_TIME_SEC: string;
|
||||
export const CURL_CA_BUNDLE: string;
|
||||
export const DOTNET_NOLOGO: string;
|
||||
export const npm_package_devDependencies_vitest: string;
|
||||
export const MAIL: string;
|
||||
export const NODE_EXTRA_CA_CERTS: string;
|
||||
export const USER: string;
|
||||
export const npm_package_bin_svelte_kit: string;
|
||||
export const npm_package_dependencies_sirv: string;
|
||||
export const npm_package_dependencies_sade: string;
|
||||
export const npm_package_dependencies_mrmime: string;
|
||||
export const npm_package_dependencies_magic_string: string;
|
||||
export const npm_config_version_commit_hooks: string;
|
||||
export const npm_config_user_agent: string;
|
||||
export const SHOULD_CONTINUE: string;
|
||||
export const CI: string;
|
||||
export const npm_package_scripts_generate_version: string;
|
||||
export const npm_package_dependencies__types_cookie: string;
|
||||
export const npm_config_bin_links: string;
|
||||
export const XDG_SESSION_TYPE: string;
|
||||
export const RUNNER_ENVIRONMENT: string;
|
||||
export const GITHUB_ENV: string;
|
||||
export const COPILOT_AGENT_ONLINE_EVALUATION_DISABLED: string;
|
||||
export const PIPX_HOME: string;
|
||||
export const npm_node_execpath: string;
|
||||
export const npm_package_devDependencies_vite: string;
|
||||
export const npm_package_devDependencies__sveltejs_vite_plugin_svelte: string;
|
||||
export const npm_config_init_version: string;
|
||||
export const JAVA_HOME_8_X64: string;
|
||||
export const SHLVL: string;
|
||||
export const npm_package_exports___node_types: string;
|
||||
export const npm_package_files_0: string;
|
||||
export const COPILOT_AGENT_RUNTIME_VERSION: string;
|
||||
export const ACLOCAL_PATH: string;
|
||||
export const ALLUSERSPROFILE: string;
|
||||
export const ANTHROPIC_AUTH_TOKEN: string;
|
||||
export const ANTHROPIC_BASE_URL: string;
|
||||
export const APPDATA: string;
|
||||
export const CLAUDECODE: string;
|
||||
export const CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: string;
|
||||
export const CLAUDE_CODE_ENTRYPOINT: string;
|
||||
export const COMMONPROGRAMFILES: string;
|
||||
export const CommonProgramW6432: string;
|
||||
export const COMPUTERNAME: string;
|
||||
export const COMSPEC: string;
|
||||
export const CONFIG_SITE: string;
|
||||
export const COREPACK_ENABLE_AUTO_PIN: string;
|
||||
export const DISPLAY: string;
|
||||
export const DriverData: string;
|
||||
export const EXEPATH: string;
|
||||
export const GIT_EDITOR: string;
|
||||
export const HOME: string;
|
||||
export const OLDPWD: string;
|
||||
export const npm_package_files_1: string;
|
||||
export const npm_package_repository_directory: string;
|
||||
export const RUNNER_TEMP: string;
|
||||
export const GITHUB_EVENT_PATH: string;
|
||||
export const CAROOT: string;
|
||||
export const COPILOT_AGENT_FIREWALL_RULESET_ALLOW_LIST: string;
|
||||
export const npm_package_files_2: string;
|
||||
export const JAVA_HOME_11_X64: string;
|
||||
export const COPILOT_AGENT_MCP_SERVER_TEMP: string;
|
||||
export const PIPX_BIN_DIR: string;
|
||||
export const GITHUB_REPOSITORY_OWNER: string;
|
||||
export const npm_package_engines_node: string;
|
||||
export const npm_package_exports___vite_import: string;
|
||||
export const npm_package_files_3: string;
|
||||
export const npm_package_devDependencies_svelte_preprocess: string;
|
||||
export const npm_config_init_license: string;
|
||||
export const GRADLE_HOME: string;
|
||||
export const ANDROID_NDK_LATEST_HOME: string;
|
||||
export const JAVA_HOME_21_X64: string;
|
||||
export const GITHUB_RETENTION_DAYS: string;
|
||||
export const npm_package_files_4: string;
|
||||
export const npm_config_version_tag_prefix: string;
|
||||
export const GITHUB_REPOSITORY_OWNER_ID: string;
|
||||
export const POWERSHELL_DISTRIBUTION_CHANNEL: string;
|
||||
export const SSL_CERT_FILE: string;
|
||||
export const AZURE_EXTENSION_DIR: string;
|
||||
export const GITHUB_HEAD_REF: string;
|
||||
export const npm_package_scripts_check: string;
|
||||
export const npm_package_files_5: string;
|
||||
export const npm_package_dependencies_tiny_glob: string;
|
||||
export const SYSTEMD_EXEC_PID: string;
|
||||
export const DBUS_SESSION_BUS_ADDRESS: string;
|
||||
export const npm_package_scripts_postinstall: string;
|
||||
export const npm_package_files_6: string;
|
||||
export const GITHUB_GRAPHQL_URL: string;
|
||||
export const GITHUB_DOWNLOADS_URL: string;
|
||||
export const npm_package_devDependencies_typescript: string;
|
||||
export const npm_package_devDependencies__types_connect: string;
|
||||
export const npm_package_description: string;
|
||||
export const JAVA_HOME_25_X64: string;
|
||||
export const NVM_DIR: string;
|
||||
export const npm_package_readmeFilename: string;
|
||||
export const npm_package_types: string;
|
||||
export const npm_package_homepage: string;
|
||||
export const DOTNET_SKIP_FIRST_TIME_EXPERIENCE: string;
|
||||
export const COPILOT_JOB_EVENT_TYPE: string;
|
||||
export const JAVA_HOME_17_X64: string;
|
||||
export const ImageVersion: string;
|
||||
export const SUDO_UID: string;
|
||||
export const npm_package_exports___hooks_types: string;
|
||||
export const npm_package_devDependencies__playwright_test: string;
|
||||
export const BLACKBIRD_MODE: string;
|
||||
export const LOGNAME: string;
|
||||
export const COPILOT_AGENT_PR_COMMIT_COUNT: string;
|
||||
export const RUNNER_OS: string;
|
||||
export const GITHUB_API_URL: string;
|
||||
export const GOROOT_1_22_X64: string;
|
||||
export const COPILOT_AGENT_COMMIT_LOGIN: string;
|
||||
export const SWIFT_PATH: string;
|
||||
export const npm_package_type: string;
|
||||
export const COPILOT_USE_SESSIONS: string;
|
||||
export const CHROMEWEBDRIVER: string;
|
||||
export const COPILOT_AGENT_CONTENT_FILTER_MODE: string;
|
||||
export const GOROOT_1_23_X64: string;
|
||||
export const JOURNAL_STREAM: string;
|
||||
export const GITHUB_WORKFLOW: string;
|
||||
export const _: string;
|
||||
export const COPILOT_AGENT_BRANCH_NAME: string;
|
||||
export const MEMORY_PRESSURE_WATCH: string;
|
||||
export const XDG_SESSION_CLASS: string;
|
||||
export const GOROOT_1_24_X64: string;
|
||||
export const npm_package_scripts_lint: string;
|
||||
export const npm_config_registry: string;
|
||||
export const ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE: string;
|
||||
export const COPILOT_AGENT_FIREWALL_ENABLE_RULESET_ALLOW_LIST: string;
|
||||
export const GOROOT_1_25_X64: string;
|
||||
export const GITHUB_RUN_ID: string;
|
||||
export const TERM: string;
|
||||
export const XDG_SESSION_ID: string;
|
||||
export const GITHUB_REF_TYPE: string;
|
||||
export const BOOTSTRAP_HASKELL_NONINTERACTIVE: string;
|
||||
export const GITHUB_WORKFLOW_SHA: string;
|
||||
export const GITHUB_BASE_REF: string;
|
||||
export const ImageOS: string;
|
||||
export const COPILOT_MCP_ENABLED: string;
|
||||
export const npm_package_exports___import: string;
|
||||
export const npm_package_devDependencies_dts_buddy: string;
|
||||
export const npm_package_dependencies_kleur: string;
|
||||
export const npm_package_dependencies_devalue: string;
|
||||
export const npm_config_ignore_scripts: string;
|
||||
export const COPILOT_AGENT_CALLBACK_URL: string;
|
||||
export const GITHUB_WORKFLOW_REF: string;
|
||||
export const GITHUB_ACTION_REPOSITORY: string;
|
||||
export const ENABLE_RUNNER_TRACING: string;
|
||||
export const npm_package_exports___package_json: string;
|
||||
export const npm_package_peerDependencies_svelte: string;
|
||||
export const PATH: string;
|
||||
export const NODE: string;
|
||||
export const COPILOT_AGENT_INJECTED_SECRET_NAMES: string;
|
||||
export const ANT_HOME: string;
|
||||
export const DOTNET_MULTILEVEL_LOOKUP: string;
|
||||
export const RUNNER_TRACKING_ID: string;
|
||||
export const INVOCATION_ID: string;
|
||||
export const RUNNER_TOOL_CACHE: string;
|
||||
export const GITHUB_UPLOADS_URL: string;
|
||||
export const REQUESTS_CA_BUNDLE: string;
|
||||
export const npm_package_repository_type: string;
|
||||
export const npm_package_name: string;
|
||||
export const GITHUB_ACTION: string;
|
||||
export const GITHUB_RUN_NUMBER: string;
|
||||
export const GITHUB_TRIGGERING_ACTOR: string;
|
||||
export const COPILOT_EXPERIMENTS: string;
|
||||
export const RUNNER_ARCH: string;
|
||||
export const XDG_RUNTIME_DIR: string;
|
||||
export const AGENT_TOOLSDIRECTORY: string;
|
||||
export const npm_package_scripts_test_integration: string;
|
||||
export const npm_package_exports___node_polyfills_import: string;
|
||||
export const npm_package_devDependencies__types_set_cookie_parser: string;
|
||||
export const SSL_CERT_DIR: string;
|
||||
export const npm_package_scripts_test_unit: string;
|
||||
export const npm_package_exports___vite_types: string;
|
||||
export const npm_config_ignore_path: string;
|
||||
export const LANG: string;
|
||||
export const VCPKG_INSTALLATION_ROOT: string;
|
||||
export const CONDA: string;
|
||||
export const RUNNER_NAME: string;
|
||||
export const XDG_CONFIG_HOME: string;
|
||||
export const GITHUB_REF_NAME: string;
|
||||
export const GITHUB_REPOSITORY: string;
|
||||
export const npm_lifecycle_script: string;
|
||||
export const npm_package_scripts_test_cross_platform_dev: string;
|
||||
export const SUDO_COMMAND: string;
|
||||
export const ANDROID_NDK_ROOT: string;
|
||||
export const GITHUB_ACTION_REF: string;
|
||||
export const DEBIAN_FRONTEND: string;
|
||||
export const npm_package_scripts_test: string;
|
||||
export const npm_package_dependencies_esm_env: string;
|
||||
export const npm_config_version_git_message: string;
|
||||
export const SHELL: string;
|
||||
export const GITHUB_REPOSITORY_ID: string;
|
||||
export const GITHUB_ACTIONS: string;
|
||||
export const CPD_SAVE_TRAJECTORY_OUTPUT: string;
|
||||
export const npm_lifecycle_event: string;
|
||||
export const npm_package_repository_url: string;
|
||||
export const npm_package_version: string;
|
||||
export const GITHUB_REF_PROTECTED: string;
|
||||
export const npm_config_argv: string;
|
||||
export const npm_package_scripts_generate_types: string;
|
||||
export const npm_package_scripts_check_all: string;
|
||||
export const npm_package_devDependencies_svelte: string;
|
||||
export const npm_package_dependencies_cookie: string;
|
||||
export const GITHUB_WORKSPACE: string;
|
||||
export const SUDO_USER: string;
|
||||
export const ACCEPT_EULA: string;
|
||||
export const DOTNET_SYSTEM_NET_DISABLEIPV6: string;
|
||||
export const GITHUB_JOB: string;
|
||||
export const YARN_IGNORE_PATH: string;
|
||||
export const npm_package_exports___node_import: string;
|
||||
export const GITHUB_SHA: string;
|
||||
export const GITHUB_RUN_ATTEMPT: string;
|
||||
export const COPILOT_AGENT_DEBUG: string;
|
||||
export const npm_package_devDependencies__types_sade: string;
|
||||
export const npm_config_version_git_tag: string;
|
||||
export const npm_config_version_git_sign: string;
|
||||
export const GITHUB_REF: string;
|
||||
export const COPILOT_AGENT_ISSUE_NUMBER: string;
|
||||
export const COPILOT_AGENT_SOURCE_ENVIRONMENT: string;
|
||||
export const GITHUB_ACTOR: string;
|
||||
export const FIREWALL_RULESET_CONTENT: string;
|
||||
export const ANDROID_SDK_ROOT: string;
|
||||
export const npm_package_license: string;
|
||||
export const npm_config_strict_ssl: string;
|
||||
export const npm_package_scripts_format: string;
|
||||
export const GITHUB_PATH: string;
|
||||
export const HOMEDRIVE: string;
|
||||
export const HOMEPATH: string;
|
||||
export const HOSTNAME: string;
|
||||
export const INFOPATH: string;
|
||||
export const INIT_CWD: string;
|
||||
export const JAVA_HOME: string;
|
||||
export const PWD: string;
|
||||
export const GITHUB_ACTOR_ID: string;
|
||||
export const RUNNER_WORKSPACE: string;
|
||||
export const LANG: string;
|
||||
export const LOCALAPPDATA: string;
|
||||
export const LOGONSERVER: string;
|
||||
export const MANPATH: string;
|
||||
export const MINGW_CHOST: string;
|
||||
export const MINGW_PACKAGE_PREFIX: string;
|
||||
export const MINGW_PREFIX: string;
|
||||
export const MSYSTEM: string;
|
||||
export const MSYSTEM_CARCH: string;
|
||||
export const MSYSTEM_CHOST: string;
|
||||
export const MSYSTEM_PREFIX: string;
|
||||
export const NODE: string;
|
||||
export const NoDefaultCurrentDirectoryInExePath: string;
|
||||
export const npm_config_argv: string;
|
||||
export const npm_config_bin_links: string;
|
||||
export const npm_config_ignore_optional: string;
|
||||
export const npm_config_ignore_path: string;
|
||||
export const npm_config_ignore_scripts: string;
|
||||
export const npm_config_init_license: string;
|
||||
export const npm_config_init_version: string;
|
||||
export const npm_config_registry: string;
|
||||
export const npm_config_save_prefix: string;
|
||||
export const npm_config_strict_ssl: string;
|
||||
export const npm_config_user_agent: string;
|
||||
export const npm_config_version_commit_hooks: string;
|
||||
export const npm_config_version_git_message: string;
|
||||
export const npm_config_version_git_sign: string;
|
||||
export const npm_config_version_git_tag: string;
|
||||
export const npm_config_version_tag_prefix: string;
|
||||
export const npm_execpath: string;
|
||||
export const npm_lifecycle_event: string;
|
||||
export const npm_lifecycle_script: string;
|
||||
export const npm_node_execpath: string;
|
||||
export const npm_package_bin_svelte_kit: string;
|
||||
export const npm_package_dependencies_cookie: string;
|
||||
export const npm_package_dependencies_devalue: string;
|
||||
export const npm_package_dependencies_esm_env: string;
|
||||
export const npm_package_dependencies_import_meta_resolve: string;
|
||||
export const npm_package_dependencies_kleur: string;
|
||||
export const npm_package_dependencies_magic_string: string;
|
||||
export const npm_package_dependencies_mrmime: string;
|
||||
export const npm_package_dependencies_sade: string;
|
||||
export const npm_package_dependencies_set_cookie_parser: string;
|
||||
export const COPILOT_AGENT_PR_NUMBER: string;
|
||||
export const HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS: string;
|
||||
export const GITHUB_EVENT_NAME: string;
|
||||
export const HOMEBREW_NO_AUTO_UPDATE: string;
|
||||
export const ANDROID_HOME: string;
|
||||
export const GITHUB_SERVER_URL: string;
|
||||
export const GECKOWEBDRIVER: string;
|
||||
export const GHCUP_INSTALL_BASE_PREFIX: string;
|
||||
export const GITHUB_OUTPUT: string;
|
||||
export const npm_package_dependencies_sirv: string;
|
||||
export const npm_package_dependencies_tiny_glob: string;
|
||||
export const npm_package_dependencies__types_cookie: string;
|
||||
export const npm_package_description: string;
|
||||
export const npm_package_devDependencies_dts_buddy: string;
|
||||
export const npm_package_devDependencies_rollup: string;
|
||||
export const npm_package_devDependencies_svelte: string;
|
||||
export const npm_package_devDependencies_svelte_preprocess: string;
|
||||
export const npm_package_devDependencies_typescript: string;
|
||||
export const npm_package_devDependencies_vite: string;
|
||||
export const npm_package_devDependencies_vitest: string;
|
||||
export const npm_package_devDependencies__playwright_test: string;
|
||||
export const npm_package_devDependencies__sveltejs_vite_plugin_svelte: string;
|
||||
export const npm_package_devDependencies__types_connect: string;
|
||||
export const npm_package_devDependencies__types_node: string;
|
||||
export const npm_package_devDependencies__types_sade: string;
|
||||
export const npm_package_devDependencies__types_set_cookie_parser: string;
|
||||
export const npm_package_engines_node: string;
|
||||
export const npm_package_exports___hooks_import: string;
|
||||
export const npm_package_exports___hooks_types: string;
|
||||
export const npm_package_exports___import: string;
|
||||
export const npm_package_exports___node_import: string;
|
||||
export const npm_package_exports___node_polyfills_import: string;
|
||||
export const npm_package_exports___node_polyfills_types: string;
|
||||
export const npm_package_exports___node_types: string;
|
||||
export const npm_package_exports___package_json: string;
|
||||
export const npm_package_exports___types: string;
|
||||
export const EDGEWEBDRIVER: string;
|
||||
export const COPILOT_EXPERIMENT_ASSIGNMENT_CONTEXT: string;
|
||||
export const npm_package_exports___vite_import: string;
|
||||
export const npm_package_exports___vite_types: string;
|
||||
export const npm_package_files_0: string;
|
||||
export const npm_package_files_1: string;
|
||||
export const npm_package_files_2: string;
|
||||
export const npm_package_files_3: string;
|
||||
export const npm_package_files_4: string;
|
||||
export const npm_package_files_5: string;
|
||||
export const npm_package_files_6: string;
|
||||
export const npm_package_homepage: string;
|
||||
export const npm_package_license: string;
|
||||
export const npm_package_name: string;
|
||||
export const npm_package_peerDependencies_svelte: string;
|
||||
export const npm_package_peerDependencies_vite: string;
|
||||
export const npm_package_peerDependencies__sveltejs_vite_plugin_svelte: string;
|
||||
export const npm_config_save_prefix: string;
|
||||
export const npm_config_ignore_optional: string;
|
||||
export const ANDROID_NDK: string;
|
||||
export const SGX_AESM_ADDR: string;
|
||||
export const CHROME_BIN: string;
|
||||
export const npm_package_readmeFilename: string;
|
||||
export const npm_package_repository_directory: string;
|
||||
export const npm_package_repository_type: string;
|
||||
export const npm_package_repository_url: string;
|
||||
export const npm_package_scripts_check: string;
|
||||
export const npm_package_scripts_check_all: string;
|
||||
export const npm_package_scripts_format: string;
|
||||
export const npm_package_scripts_generate_types: string;
|
||||
export const npm_package_scripts_generate_version: string;
|
||||
export const npm_package_scripts_lint: string;
|
||||
export const npm_package_scripts_postinstall: string;
|
||||
export const npm_package_scripts_test: string;
|
||||
export const npm_package_scripts_test_cross_platform_build: string;
|
||||
export const npm_package_scripts_test_cross_platform_dev: string;
|
||||
export const npm_package_scripts_test_integration: string;
|
||||
export const npm_package_scripts_test_unit: string;
|
||||
export const npm_package_type: string;
|
||||
export const npm_package_types: string;
|
||||
export const npm_package_version: string;
|
||||
export const NUMBER_OF_PROCESSORS: string;
|
||||
export const OLDPWD: string;
|
||||
export const OneDrive: string;
|
||||
export const ORIGINAL_PATH: string;
|
||||
export const ORIGINAL_TEMP: string;
|
||||
export const ORIGINAL_TMP: string;
|
||||
export const OS: string;
|
||||
export const OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: string;
|
||||
export const PATH: string;
|
||||
export const PATHEXT: string;
|
||||
export const PKG_CONFIG_PATH: string;
|
||||
export const PKG_CONFIG_SYSTEM_INCLUDE_PATH: string;
|
||||
export const PKG_CONFIG_SYSTEM_LIBRARY_PATH: string;
|
||||
export const PLINK_PROTOCOL: string;
|
||||
export const PROCESSOR_ARCHITECTURE: string;
|
||||
export const PROCESSOR_IDENTIFIER: string;
|
||||
export const PROCESSOR_LEVEL: string;
|
||||
export const PROCESSOR_REVISION: string;
|
||||
export const ProgramData: string;
|
||||
export const PROGRAMFILES: string;
|
||||
export const ProgramW6432: string;
|
||||
export const PROMPT: string;
|
||||
export const PSModulePath: string;
|
||||
export const PUBLIC: string;
|
||||
export const PUPPETEER_SKIP_DOWNLOAD: string;
|
||||
export const SELENIUM_JAR_PATH: string;
|
||||
export const MEMORY_PRESSURE_WRITE: string;
|
||||
export const COPILOT_AGENT_COMMIT_EMAIL: string;
|
||||
export const COPILOT_AGENT_FIREWALL_LOG_FILE: string;
|
||||
export const COPILOT_FEATURE_FLAGS: string;
|
||||
export const npm_package_exports___node_polyfills_types: string;
|
||||
export const INIT_CWD: string;
|
||||
export const COPILOT_API_URL: string;
|
||||
export const ANDROID_NDK_HOME: string;
|
||||
export const GITHUB_STEP_SUMMARY: string;
|
||||
export const COPILOT_AGENT_BASE_COMMIT: string;
|
||||
export const COPILOT_AGENT_TIMEOUT_MIN: string;
|
||||
export const npm_package_exports___hooks_import: string;
|
||||
export const npm_package_dependencies_import_meta_resolve: string;
|
||||
export const PWD: string;
|
||||
export const SHELL: string;
|
||||
export const SHLVL: string;
|
||||
export const SSH_ASKPASS: string;
|
||||
export const SYSTEMDRIVE: string;
|
||||
export const SYSTEMROOT: string;
|
||||
export const TEMP: string;
|
||||
export const TERM: string;
|
||||
export const TMP: string;
|
||||
export const TMPDIR: string;
|
||||
export const USERDOMAIN: string;
|
||||
export const USERDOMAIN_ROAMINGPROFILE: string;
|
||||
export const USERNAME: string;
|
||||
export const USERPROFILE: string;
|
||||
export const VS140COMNTOOLS: string;
|
||||
export const WINDIR: string;
|
||||
export const WXDRIVE_START_ARGS: string;
|
||||
export const YARN_IGNORE_PATH: string;
|
||||
export const ZES_ENABLE_SYSMAN: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,261 +230,179 @@ declare module '$env/static/public' {
|
||||
*/
|
||||
declare module '$env/dynamic/private' {
|
||||
export const env: {
|
||||
SUDO_GID: string;
|
||||
GITHUB_STATE: string;
|
||||
COPILOT_AGENT_ACTION: string;
|
||||
npm_package_scripts_test_cross_platform_build: string;
|
||||
npm_package_devDependencies_rollup: string;
|
||||
npm_package_devDependencies__types_node: string;
|
||||
COPILOT_AGENT_START_TIME_SEC: string;
|
||||
CURL_CA_BUNDLE: string;
|
||||
DOTNET_NOLOGO: string;
|
||||
npm_package_devDependencies_vitest: string;
|
||||
MAIL: string;
|
||||
NODE_EXTRA_CA_CERTS: string;
|
||||
USER: string;
|
||||
npm_package_bin_svelte_kit: string;
|
||||
npm_package_dependencies_sirv: string;
|
||||
npm_package_dependencies_sade: string;
|
||||
npm_package_dependencies_mrmime: string;
|
||||
npm_package_dependencies_magic_string: string;
|
||||
npm_config_version_commit_hooks: string;
|
||||
npm_config_user_agent: string;
|
||||
SHOULD_CONTINUE: string;
|
||||
CI: string;
|
||||
npm_package_scripts_generate_version: string;
|
||||
npm_package_dependencies__types_cookie: string;
|
||||
npm_config_bin_links: string;
|
||||
XDG_SESSION_TYPE: string;
|
||||
RUNNER_ENVIRONMENT: string;
|
||||
GITHUB_ENV: string;
|
||||
COPILOT_AGENT_ONLINE_EVALUATION_DISABLED: string;
|
||||
PIPX_HOME: string;
|
||||
npm_node_execpath: string;
|
||||
npm_package_devDependencies_vite: string;
|
||||
npm_package_devDependencies__sveltejs_vite_plugin_svelte: string;
|
||||
npm_config_init_version: string;
|
||||
JAVA_HOME_8_X64: string;
|
||||
SHLVL: string;
|
||||
npm_package_exports___node_types: string;
|
||||
npm_package_files_0: string;
|
||||
COPILOT_AGENT_RUNTIME_VERSION: string;
|
||||
ACLOCAL_PATH: string;
|
||||
ALLUSERSPROFILE: string;
|
||||
ANTHROPIC_AUTH_TOKEN: string;
|
||||
ANTHROPIC_BASE_URL: string;
|
||||
APPDATA: string;
|
||||
CLAUDECODE: string;
|
||||
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: string;
|
||||
CLAUDE_CODE_ENTRYPOINT: string;
|
||||
COMMONPROGRAMFILES: string;
|
||||
CommonProgramW6432: string;
|
||||
COMPUTERNAME: string;
|
||||
COMSPEC: string;
|
||||
CONFIG_SITE: string;
|
||||
COREPACK_ENABLE_AUTO_PIN: string;
|
||||
DISPLAY: string;
|
||||
DriverData: string;
|
||||
EXEPATH: string;
|
||||
GIT_EDITOR: string;
|
||||
HOME: string;
|
||||
OLDPWD: string;
|
||||
npm_package_files_1: string;
|
||||
npm_package_repository_directory: string;
|
||||
RUNNER_TEMP: string;
|
||||
GITHUB_EVENT_PATH: string;
|
||||
CAROOT: string;
|
||||
COPILOT_AGENT_FIREWALL_RULESET_ALLOW_LIST: string;
|
||||
npm_package_files_2: string;
|
||||
JAVA_HOME_11_X64: string;
|
||||
COPILOT_AGENT_MCP_SERVER_TEMP: string;
|
||||
PIPX_BIN_DIR: string;
|
||||
GITHUB_REPOSITORY_OWNER: string;
|
||||
npm_package_engines_node: string;
|
||||
npm_package_exports___vite_import: string;
|
||||
npm_package_files_3: string;
|
||||
npm_package_devDependencies_svelte_preprocess: string;
|
||||
npm_config_init_license: string;
|
||||
GRADLE_HOME: string;
|
||||
ANDROID_NDK_LATEST_HOME: string;
|
||||
JAVA_HOME_21_X64: string;
|
||||
GITHUB_RETENTION_DAYS: string;
|
||||
npm_package_files_4: string;
|
||||
npm_config_version_tag_prefix: string;
|
||||
GITHUB_REPOSITORY_OWNER_ID: string;
|
||||
POWERSHELL_DISTRIBUTION_CHANNEL: string;
|
||||
SSL_CERT_FILE: string;
|
||||
AZURE_EXTENSION_DIR: string;
|
||||
GITHUB_HEAD_REF: string;
|
||||
npm_package_scripts_check: string;
|
||||
npm_package_files_5: string;
|
||||
npm_package_dependencies_tiny_glob: string;
|
||||
SYSTEMD_EXEC_PID: string;
|
||||
DBUS_SESSION_BUS_ADDRESS: string;
|
||||
npm_package_scripts_postinstall: string;
|
||||
npm_package_files_6: string;
|
||||
GITHUB_GRAPHQL_URL: string;
|
||||
GITHUB_DOWNLOADS_URL: string;
|
||||
npm_package_devDependencies_typescript: string;
|
||||
npm_package_devDependencies__types_connect: string;
|
||||
npm_package_description: string;
|
||||
JAVA_HOME_25_X64: string;
|
||||
NVM_DIR: string;
|
||||
npm_package_readmeFilename: string;
|
||||
npm_package_types: string;
|
||||
npm_package_homepage: string;
|
||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: string;
|
||||
COPILOT_JOB_EVENT_TYPE: string;
|
||||
JAVA_HOME_17_X64: string;
|
||||
ImageVersion: string;
|
||||
SUDO_UID: string;
|
||||
npm_package_exports___hooks_types: string;
|
||||
npm_package_devDependencies__playwright_test: string;
|
||||
BLACKBIRD_MODE: string;
|
||||
LOGNAME: string;
|
||||
COPILOT_AGENT_PR_COMMIT_COUNT: string;
|
||||
RUNNER_OS: string;
|
||||
GITHUB_API_URL: string;
|
||||
GOROOT_1_22_X64: string;
|
||||
COPILOT_AGENT_COMMIT_LOGIN: string;
|
||||
SWIFT_PATH: string;
|
||||
npm_package_type: string;
|
||||
COPILOT_USE_SESSIONS: string;
|
||||
CHROMEWEBDRIVER: string;
|
||||
COPILOT_AGENT_CONTENT_FILTER_MODE: string;
|
||||
GOROOT_1_23_X64: string;
|
||||
JOURNAL_STREAM: string;
|
||||
GITHUB_WORKFLOW: string;
|
||||
_: string;
|
||||
COPILOT_AGENT_BRANCH_NAME: string;
|
||||
MEMORY_PRESSURE_WATCH: string;
|
||||
XDG_SESSION_CLASS: string;
|
||||
GOROOT_1_24_X64: string;
|
||||
npm_package_scripts_lint: string;
|
||||
npm_config_registry: string;
|
||||
ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE: string;
|
||||
COPILOT_AGENT_FIREWALL_ENABLE_RULESET_ALLOW_LIST: string;
|
||||
GOROOT_1_25_X64: string;
|
||||
GITHUB_RUN_ID: string;
|
||||
TERM: string;
|
||||
XDG_SESSION_ID: string;
|
||||
GITHUB_REF_TYPE: string;
|
||||
BOOTSTRAP_HASKELL_NONINTERACTIVE: string;
|
||||
GITHUB_WORKFLOW_SHA: string;
|
||||
GITHUB_BASE_REF: string;
|
||||
ImageOS: string;
|
||||
COPILOT_MCP_ENABLED: string;
|
||||
npm_package_exports___import: string;
|
||||
npm_package_devDependencies_dts_buddy: string;
|
||||
npm_package_dependencies_kleur: string;
|
||||
npm_package_dependencies_devalue: string;
|
||||
npm_config_ignore_scripts: string;
|
||||
COPILOT_AGENT_CALLBACK_URL: string;
|
||||
GITHUB_WORKFLOW_REF: string;
|
||||
GITHUB_ACTION_REPOSITORY: string;
|
||||
ENABLE_RUNNER_TRACING: string;
|
||||
npm_package_exports___package_json: string;
|
||||
npm_package_peerDependencies_svelte: string;
|
||||
PATH: string;
|
||||
NODE: string;
|
||||
COPILOT_AGENT_INJECTED_SECRET_NAMES: string;
|
||||
ANT_HOME: string;
|
||||
DOTNET_MULTILEVEL_LOOKUP: string;
|
||||
RUNNER_TRACKING_ID: string;
|
||||
INVOCATION_ID: string;
|
||||
RUNNER_TOOL_CACHE: string;
|
||||
GITHUB_UPLOADS_URL: string;
|
||||
REQUESTS_CA_BUNDLE: string;
|
||||
npm_package_repository_type: string;
|
||||
npm_package_name: string;
|
||||
GITHUB_ACTION: string;
|
||||
GITHUB_RUN_NUMBER: string;
|
||||
GITHUB_TRIGGERING_ACTOR: string;
|
||||
COPILOT_EXPERIMENTS: string;
|
||||
RUNNER_ARCH: string;
|
||||
XDG_RUNTIME_DIR: string;
|
||||
AGENT_TOOLSDIRECTORY: string;
|
||||
npm_package_scripts_test_integration: string;
|
||||
npm_package_exports___node_polyfills_import: string;
|
||||
npm_package_devDependencies__types_set_cookie_parser: string;
|
||||
SSL_CERT_DIR: string;
|
||||
npm_package_scripts_test_unit: string;
|
||||
npm_package_exports___vite_types: string;
|
||||
npm_config_ignore_path: string;
|
||||
LANG: string;
|
||||
VCPKG_INSTALLATION_ROOT: string;
|
||||
CONDA: string;
|
||||
RUNNER_NAME: string;
|
||||
XDG_CONFIG_HOME: string;
|
||||
GITHUB_REF_NAME: string;
|
||||
GITHUB_REPOSITORY: string;
|
||||
npm_lifecycle_script: string;
|
||||
npm_package_scripts_test_cross_platform_dev: string;
|
||||
SUDO_COMMAND: string;
|
||||
ANDROID_NDK_ROOT: string;
|
||||
GITHUB_ACTION_REF: string;
|
||||
DEBIAN_FRONTEND: string;
|
||||
npm_package_scripts_test: string;
|
||||
npm_package_dependencies_esm_env: string;
|
||||
npm_config_version_git_message: string;
|
||||
SHELL: string;
|
||||
GITHUB_REPOSITORY_ID: string;
|
||||
GITHUB_ACTIONS: string;
|
||||
CPD_SAVE_TRAJECTORY_OUTPUT: string;
|
||||
npm_lifecycle_event: string;
|
||||
npm_package_repository_url: string;
|
||||
npm_package_version: string;
|
||||
GITHUB_REF_PROTECTED: string;
|
||||
npm_config_argv: string;
|
||||
npm_package_scripts_generate_types: string;
|
||||
npm_package_scripts_check_all: string;
|
||||
npm_package_devDependencies_svelte: string;
|
||||
npm_package_dependencies_cookie: string;
|
||||
GITHUB_WORKSPACE: string;
|
||||
SUDO_USER: string;
|
||||
ACCEPT_EULA: string;
|
||||
DOTNET_SYSTEM_NET_DISABLEIPV6: string;
|
||||
GITHUB_JOB: string;
|
||||
YARN_IGNORE_PATH: string;
|
||||
npm_package_exports___node_import: string;
|
||||
GITHUB_SHA: string;
|
||||
GITHUB_RUN_ATTEMPT: string;
|
||||
COPILOT_AGENT_DEBUG: string;
|
||||
npm_package_devDependencies__types_sade: string;
|
||||
npm_config_version_git_tag: string;
|
||||
npm_config_version_git_sign: string;
|
||||
GITHUB_REF: string;
|
||||
COPILOT_AGENT_ISSUE_NUMBER: string;
|
||||
COPILOT_AGENT_SOURCE_ENVIRONMENT: string;
|
||||
GITHUB_ACTOR: string;
|
||||
FIREWALL_RULESET_CONTENT: string;
|
||||
ANDROID_SDK_ROOT: string;
|
||||
npm_package_license: string;
|
||||
npm_config_strict_ssl: string;
|
||||
npm_package_scripts_format: string;
|
||||
GITHUB_PATH: string;
|
||||
HOMEDRIVE: string;
|
||||
HOMEPATH: string;
|
||||
HOSTNAME: string;
|
||||
INFOPATH: string;
|
||||
INIT_CWD: string;
|
||||
JAVA_HOME: string;
|
||||
PWD: string;
|
||||
GITHUB_ACTOR_ID: string;
|
||||
RUNNER_WORKSPACE: string;
|
||||
LANG: string;
|
||||
LOCALAPPDATA: string;
|
||||
LOGONSERVER: string;
|
||||
MANPATH: string;
|
||||
MINGW_CHOST: string;
|
||||
MINGW_PACKAGE_PREFIX: string;
|
||||
MINGW_PREFIX: string;
|
||||
MSYSTEM: string;
|
||||
MSYSTEM_CARCH: string;
|
||||
MSYSTEM_CHOST: string;
|
||||
MSYSTEM_PREFIX: string;
|
||||
NODE: string;
|
||||
NoDefaultCurrentDirectoryInExePath: string;
|
||||
npm_config_argv: string;
|
||||
npm_config_bin_links: string;
|
||||
npm_config_ignore_optional: string;
|
||||
npm_config_ignore_path: string;
|
||||
npm_config_ignore_scripts: string;
|
||||
npm_config_init_license: string;
|
||||
npm_config_init_version: string;
|
||||
npm_config_registry: string;
|
||||
npm_config_save_prefix: string;
|
||||
npm_config_strict_ssl: string;
|
||||
npm_config_user_agent: string;
|
||||
npm_config_version_commit_hooks: string;
|
||||
npm_config_version_git_message: string;
|
||||
npm_config_version_git_sign: string;
|
||||
npm_config_version_git_tag: string;
|
||||
npm_config_version_tag_prefix: string;
|
||||
npm_execpath: string;
|
||||
npm_lifecycle_event: string;
|
||||
npm_lifecycle_script: string;
|
||||
npm_node_execpath: string;
|
||||
npm_package_bin_svelte_kit: string;
|
||||
npm_package_dependencies_cookie: string;
|
||||
npm_package_dependencies_devalue: string;
|
||||
npm_package_dependencies_esm_env: string;
|
||||
npm_package_dependencies_import_meta_resolve: string;
|
||||
npm_package_dependencies_kleur: string;
|
||||
npm_package_dependencies_magic_string: string;
|
||||
npm_package_dependencies_mrmime: string;
|
||||
npm_package_dependencies_sade: string;
|
||||
npm_package_dependencies_set_cookie_parser: string;
|
||||
COPILOT_AGENT_PR_NUMBER: string;
|
||||
HOMEBREW_CLEANUP_PERIODIC_FULL_DAYS: string;
|
||||
GITHUB_EVENT_NAME: string;
|
||||
HOMEBREW_NO_AUTO_UPDATE: string;
|
||||
ANDROID_HOME: string;
|
||||
GITHUB_SERVER_URL: string;
|
||||
GECKOWEBDRIVER: string;
|
||||
GHCUP_INSTALL_BASE_PREFIX: string;
|
||||
GITHUB_OUTPUT: string;
|
||||
npm_package_dependencies_sirv: string;
|
||||
npm_package_dependencies_tiny_glob: string;
|
||||
npm_package_dependencies__types_cookie: string;
|
||||
npm_package_description: string;
|
||||
npm_package_devDependencies_dts_buddy: string;
|
||||
npm_package_devDependencies_rollup: string;
|
||||
npm_package_devDependencies_svelte: string;
|
||||
npm_package_devDependencies_svelte_preprocess: string;
|
||||
npm_package_devDependencies_typescript: string;
|
||||
npm_package_devDependencies_vite: string;
|
||||
npm_package_devDependencies_vitest: string;
|
||||
npm_package_devDependencies__playwright_test: string;
|
||||
npm_package_devDependencies__sveltejs_vite_plugin_svelte: string;
|
||||
npm_package_devDependencies__types_connect: string;
|
||||
npm_package_devDependencies__types_node: string;
|
||||
npm_package_devDependencies__types_sade: string;
|
||||
npm_package_devDependencies__types_set_cookie_parser: string;
|
||||
npm_package_engines_node: string;
|
||||
npm_package_exports___hooks_import: string;
|
||||
npm_package_exports___hooks_types: string;
|
||||
npm_package_exports___import: string;
|
||||
npm_package_exports___node_import: string;
|
||||
npm_package_exports___node_polyfills_import: string;
|
||||
npm_package_exports___node_polyfills_types: string;
|
||||
npm_package_exports___node_types: string;
|
||||
npm_package_exports___package_json: string;
|
||||
npm_package_exports___types: string;
|
||||
EDGEWEBDRIVER: string;
|
||||
COPILOT_EXPERIMENT_ASSIGNMENT_CONTEXT: string;
|
||||
npm_package_exports___vite_import: string;
|
||||
npm_package_exports___vite_types: string;
|
||||
npm_package_files_0: string;
|
||||
npm_package_files_1: string;
|
||||
npm_package_files_2: string;
|
||||
npm_package_files_3: string;
|
||||
npm_package_files_4: string;
|
||||
npm_package_files_5: string;
|
||||
npm_package_files_6: string;
|
||||
npm_package_homepage: string;
|
||||
npm_package_license: string;
|
||||
npm_package_name: string;
|
||||
npm_package_peerDependencies_svelte: string;
|
||||
npm_package_peerDependencies_vite: string;
|
||||
npm_package_peerDependencies__sveltejs_vite_plugin_svelte: string;
|
||||
npm_config_save_prefix: string;
|
||||
npm_config_ignore_optional: string;
|
||||
ANDROID_NDK: string;
|
||||
SGX_AESM_ADDR: string;
|
||||
CHROME_BIN: string;
|
||||
npm_package_readmeFilename: string;
|
||||
npm_package_repository_directory: string;
|
||||
npm_package_repository_type: string;
|
||||
npm_package_repository_url: string;
|
||||
npm_package_scripts_check: string;
|
||||
npm_package_scripts_check_all: string;
|
||||
npm_package_scripts_format: string;
|
||||
npm_package_scripts_generate_types: string;
|
||||
npm_package_scripts_generate_version: string;
|
||||
npm_package_scripts_lint: string;
|
||||
npm_package_scripts_postinstall: string;
|
||||
npm_package_scripts_test: string;
|
||||
npm_package_scripts_test_cross_platform_build: string;
|
||||
npm_package_scripts_test_cross_platform_dev: string;
|
||||
npm_package_scripts_test_integration: string;
|
||||
npm_package_scripts_test_unit: string;
|
||||
npm_package_type: string;
|
||||
npm_package_types: string;
|
||||
npm_package_version: string;
|
||||
NUMBER_OF_PROCESSORS: string;
|
||||
OLDPWD: string;
|
||||
OneDrive: string;
|
||||
ORIGINAL_PATH: string;
|
||||
ORIGINAL_TEMP: string;
|
||||
ORIGINAL_TMP: string;
|
||||
OS: string;
|
||||
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: string;
|
||||
PATH: string;
|
||||
PATHEXT: string;
|
||||
PKG_CONFIG_PATH: string;
|
||||
PKG_CONFIG_SYSTEM_INCLUDE_PATH: string;
|
||||
PKG_CONFIG_SYSTEM_LIBRARY_PATH: string;
|
||||
PLINK_PROTOCOL: string;
|
||||
PROCESSOR_ARCHITECTURE: string;
|
||||
PROCESSOR_IDENTIFIER: string;
|
||||
PROCESSOR_LEVEL: string;
|
||||
PROCESSOR_REVISION: string;
|
||||
ProgramData: string;
|
||||
PROGRAMFILES: string;
|
||||
ProgramW6432: string;
|
||||
PROMPT: string;
|
||||
PSModulePath: string;
|
||||
PUBLIC: string;
|
||||
PUPPETEER_SKIP_DOWNLOAD: string;
|
||||
SELENIUM_JAR_PATH: string;
|
||||
MEMORY_PRESSURE_WRITE: string;
|
||||
COPILOT_AGENT_COMMIT_EMAIL: string;
|
||||
COPILOT_AGENT_FIREWALL_LOG_FILE: string;
|
||||
COPILOT_FEATURE_FLAGS: string;
|
||||
npm_package_exports___node_polyfills_types: string;
|
||||
INIT_CWD: string;
|
||||
COPILOT_API_URL: string;
|
||||
ANDROID_NDK_HOME: string;
|
||||
GITHUB_STEP_SUMMARY: string;
|
||||
COPILOT_AGENT_BASE_COMMIT: string;
|
||||
COPILOT_AGENT_TIMEOUT_MIN: string;
|
||||
npm_package_exports___hooks_import: string;
|
||||
npm_package_dependencies_import_meta_resolve: string;
|
||||
PWD: string;
|
||||
SHELL: string;
|
||||
SHLVL: string;
|
||||
SSH_ASKPASS: string;
|
||||
SYSTEMDRIVE: string;
|
||||
SYSTEMROOT: string;
|
||||
TEMP: string;
|
||||
TERM: string;
|
||||
TMP: string;
|
||||
TMPDIR: string;
|
||||
USERDOMAIN: string;
|
||||
USERDOMAIN_ROAMINGPROFILE: string;
|
||||
USERNAME: string;
|
||||
USERPROFILE: string;
|
||||
VS140COMNTOOLS: string;
|
||||
WINDIR: string;
|
||||
WXDRIVE_START_ARGS: string;
|
||||
YARN_IGNORE_PATH: string;
|
||||
ZES_ENABLE_SYSMAN: string;
|
||||
[key: `PUBLIC_${string}`]: undefined;
|
||||
[key: `${string}`]: string | undefined;
|
||||
}
|
||||
|
||||
@@ -12,25 +12,46 @@ rrweb-player uses rrweb's Replayer under the hood, but as Replayer doesn't inclu
|
||||
|
||||
## Installation
|
||||
|
||||
rrweb-player can also be included with `<script>`:
|
||||
### 1) Bundler / npm (Recommended)
|
||||
|
||||
```shell
|
||||
npm install rrweb-player
|
||||
```
|
||||
|
||||
```js
|
||||
import rrwebPlayer from 'rrweb-player';
|
||||
import 'rrweb-player/dist/style.css';
|
||||
```
|
||||
|
||||
### 2) Browser Without Bundler (ESM + import maps)
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/index.umd.cjs"></script>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"rrweb-player": "https://cdn.jsdelivr.net/npm/rrweb-player@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import rrwebPlayer from 'rrweb-player';
|
||||
</script>
|
||||
```
|
||||
|
||||
Or installed by using NPM:
|
||||
### 3) Legacy Direct `<script>` Include (UMD fallback)
|
||||
|
||||
```shell
|
||||
npm install --save rrweb-player
|
||||
```
|
||||
Use this only for compatibility with non-module environments.
|
||||
|
||||
```js
|
||||
import rrwebPlayer from 'rrweb-player';
|
||||
import 'rrweb-player/dist/style.css';
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb-player@latest/umd/rrweb-player.min.js"></script>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"svelte-preprocess": "^5.0.3",
|
||||
"svelte2tsx": "^0.7.30",
|
||||
"tslib": "^2.0.0",
|
||||
"vite": "^5.3.1"
|
||||
"vite": "^6.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tsconfig/svelte": "^1.0.0",
|
||||
@@ -51,6 +51,7 @@
|
||||
"./dist/style.css": "./dist/style.css"
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
|
||||
@@ -28,6 +28,15 @@
|
||||
export let inactiveColor: NonNullable<RRwebPlayerOptions['props']['inactiveColor']> = '#D4D4D4';
|
||||
|
||||
let replayer: Replayer;
|
||||
const pendingEventListeners: Array<{
|
||||
event: string;
|
||||
handler: (detail: unknown) => unknown;
|
||||
}> = [];
|
||||
const controllerEvents = new Set([
|
||||
'ui-update-current-time',
|
||||
'ui-update-progress',
|
||||
'ui-update-player-state',
|
||||
]);
|
||||
|
||||
export const getMirror = () => replayer.getMirror();
|
||||
|
||||
@@ -83,14 +92,13 @@
|
||||
event: string,
|
||||
handler: (detail: unknown) => unknown,
|
||||
) => {
|
||||
if (!replayer) {
|
||||
pendingEventListeners.push({ event, handler });
|
||||
return;
|
||||
}
|
||||
replayer.on(event, handler);
|
||||
switch (event) {
|
||||
case 'ui-update-current-time':
|
||||
case 'ui-update-progress':
|
||||
case 'ui-update-player-state':
|
||||
controller.$on(event, ({ detail }) => handler(detail));
|
||||
default:
|
||||
break;
|
||||
if (controllerEvents.has(event) && controller) {
|
||||
controller.$on(event, ({ detail }) => handler(detail));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -130,6 +138,14 @@
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
const debugTarget = window as Window & {
|
||||
__rrwebPlayerDebug?: Record<string, unknown>;
|
||||
};
|
||||
debugTarget.__rrwebPlayerDebug = {
|
||||
stage: 'mounted',
|
||||
hasFrame: !!frame,
|
||||
eventsLength: events?.length,
|
||||
};
|
||||
// runtime type check
|
||||
if (speedOption !== undefined && typeOf(speedOption) !== 'array') {
|
||||
throw new Error('speedOption must be array');
|
||||
@@ -157,8 +173,23 @@
|
||||
unpackFn: unpack,
|
||||
...$$props,
|
||||
});
|
||||
debugTarget.__rrwebPlayerDebug = {
|
||||
...debugTarget.__rrwebPlayerDebug,
|
||||
stage: 'replayer-created',
|
||||
hasWrapper: !!replayer.wrapper,
|
||||
hasIframe: !!replayer.iframe,
|
||||
};
|
||||
|
||||
pendingEventListeners.splice(0).forEach(({ event, handler }) => {
|
||||
replayer.on(event, handler);
|
||||
});
|
||||
|
||||
replayer.on('resize', (dimension) => {
|
||||
debugTarget.__rrwebPlayerDebug = {
|
||||
...debugTarget.__rrwebPlayerDebug,
|
||||
stage: 'resized',
|
||||
dimension,
|
||||
};
|
||||
updateScale(
|
||||
replayer.wrapper,
|
||||
dimension as { width: number; height: number },
|
||||
|
||||
@@ -34,6 +34,9 @@ function viteSvelteDts(): Plugin {
|
||||
console.log('Generating .d.ts files for Svelte components...');
|
||||
|
||||
const { input } = options;
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
if (typeof input === 'string') {
|
||||
await generateDts(input);
|
||||
} else if (Array.isArray(input)) {
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -63,7 +64,7 @@
|
||||
"ts-node": "^7.0.1",
|
||||
"tslib": "^1.9.3",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1",
|
||||
"vitest": "^1.4.0"
|
||||
},
|
||||
|
||||
@@ -19,12 +19,85 @@ rrweb refers to 'record and replay the web', which is a tool for recording and r
|
||||
|
||||
[**🍳 Recipes 🍳**](../../docs/recipes/index.md)
|
||||
|
||||
## Installation
|
||||
|
||||
`rrweb` is kept mainly for backward compatibility. For new integrations, prefer package-specific entrypoints (`@rrweb/record` and `@rrweb/replay`) first, or use `@rrweb/all` as a convenience package.
|
||||
|
||||
### 1) Bundler / npm (Recommended)
|
||||
|
||||
For new projects:
|
||||
|
||||
```shell
|
||||
npm install @rrweb/record @rrweb/replay
|
||||
```
|
||||
|
||||
```js
|
||||
import { record } from '@rrweb/record';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
import '@rrweb/replay/dist/style.css';
|
||||
```
|
||||
|
||||
Convenience single-package option:
|
||||
|
||||
```shell
|
||||
npm install @rrweb/all
|
||||
```
|
||||
|
||||
```js
|
||||
import { record, Replayer, pack, unpack } from '@rrweb/all';
|
||||
import '@rrweb/all/dist/style.css';
|
||||
```
|
||||
|
||||
Legacy compatibility package:
|
||||
|
||||
```shell
|
||||
npm install rrweb
|
||||
```
|
||||
|
||||
```js
|
||||
import { record, Replayer } from 'rrweb';
|
||||
import 'rrweb/dist/style.css';
|
||||
```
|
||||
|
||||
### 2) Browser Without Bundler (ESM + import maps)
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/dist/style.css"
|
||||
/>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"@rrweb/record": "https://cdn.jsdelivr.net/npm/@rrweb/record@latest/+esm",
|
||||
"@rrweb/replay": "https://cdn.jsdelivr.net/npm/@rrweb/replay@latest/+esm"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
import { record } from '@rrweb/record';
|
||||
import { Replayer } from '@rrweb/replay';
|
||||
</script>
|
||||
```
|
||||
|
||||
### 3) Legacy Direct `<script>` Include (UMD fallback)
|
||||
|
||||
Use this only for compatibility with non-module environments; modern browsers support the importmap method [since 2023](https://caniuse.com/?search=import+map)
|
||||
|
||||
```html
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/style.css"
|
||||
/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb@latest/umd/rrweb.min.js"></script>
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
**[rrweb](https://github.com/rrweb-io/rrweb)** mainly includes two funtions:
|
||||
|
||||
- **Record**: The record function is used to record all the mutations in the DOM
|
||||
- **Replay**: The replay function is to replay the recorded mutations one by one according to the corresponding timestamp.
|
||||
- **Replayer**: The replay function is to replay the recorded mutations one by one according to the corresponding timestamp.
|
||||
|
||||
## Roadmap
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
"./dist/style.css": "./dist/style.css"
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
@@ -76,7 +77,7 @@
|
||||
"ts-node": "^10.9.1",
|
||||
"tslib": "^2.3.1",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
import typescript from 'rollup-plugin-typescript2';
|
||||
import esbuild from 'rollup-plugin-esbuild';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import postcss from 'rollup-plugin-postcss';
|
||||
import renameNodeModules from 'rollup-plugin-rename-node-modules';
|
||||
import webWorkerLoader from 'rollup-plugin-web-worker-loader';
|
||||
import pkg from './package.json';
|
||||
|
||||
function toRecordPath(path) {
|
||||
return path
|
||||
.replace(/^([\w]+)\//, '$1/record/')
|
||||
.replace('rrweb', 'rrweb-record');
|
||||
}
|
||||
|
||||
function toRecordPackPath(path) {
|
||||
return path
|
||||
.replace(/^([\w]+)\//, '$1/record/')
|
||||
.replace('rrweb', 'rrweb-record-pack');
|
||||
}
|
||||
|
||||
function toReplayPath(path) {
|
||||
return path
|
||||
.replace(/^([\w]+)\//, '$1/replay/')
|
||||
.replace('rrweb', 'rrweb-replay');
|
||||
}
|
||||
|
||||
function toReplayUnpackPath(path) {
|
||||
return path
|
||||
.replace(/^([\w]+)\//, '$1/replay/')
|
||||
.replace('rrweb', 'rrweb-replay-unpack');
|
||||
}
|
||||
|
||||
function toAllPath(path) {
|
||||
return path.replace('rrweb', 'rrweb-all');
|
||||
}
|
||||
|
||||
function toPluginPath(pluginName, stage) {
|
||||
return (path) =>
|
||||
path
|
||||
.replace(/^([\w]+)\//, '$1/plugins/')
|
||||
.replace('rrweb', `${pluginName}-${stage}`);
|
||||
}
|
||||
|
||||
function toMinPath(path) {
|
||||
return path.replace(/\.js$/, '.min.js');
|
||||
}
|
||||
|
||||
const baseConfigs = [
|
||||
// all in one
|
||||
{
|
||||
input: './src/entries/all.ts',
|
||||
name: 'rrweb',
|
||||
pathFn: toAllPath,
|
||||
esm: true,
|
||||
},
|
||||
// record only
|
||||
{
|
||||
input: './src/record/index.ts',
|
||||
name: 'rrwebRecord',
|
||||
pathFn: toRecordPath,
|
||||
},
|
||||
// record and pack
|
||||
{
|
||||
input: './src/entries/record-pack.ts',
|
||||
name: 'rrwebRecord',
|
||||
pathFn: toRecordPackPath,
|
||||
},
|
||||
// replay only
|
||||
{
|
||||
input: './src/replay/index.ts',
|
||||
name: 'rrwebReplay',
|
||||
pathFn: toReplayPath,
|
||||
},
|
||||
// replay and unpack
|
||||
{
|
||||
input: './src/entries/replay-unpack.ts',
|
||||
name: 'rrwebReplay',
|
||||
pathFn: toReplayUnpackPath,
|
||||
},
|
||||
// record and replay
|
||||
{
|
||||
input: './src/index.ts',
|
||||
name: 'rrweb',
|
||||
pathFn: (p) => p,
|
||||
},
|
||||
// plugins
|
||||
{
|
||||
input: './src/plugins/console/record/index.ts',
|
||||
name: 'rrwebConsoleRecord',
|
||||
pathFn: toPluginPath('console', 'record'),
|
||||
},
|
||||
{
|
||||
input: './src/plugins/canvas-webrtc/record/index.ts',
|
||||
name: 'rrwebCanvasWebRTCRecord',
|
||||
pathFn: toPluginPath('canvas-webrtc', 'record'),
|
||||
},
|
||||
{
|
||||
input: './src/plugins/canvas-webrtc/replay/index.ts',
|
||||
name: 'rrwebCanvasWebRTCReplay',
|
||||
pathFn: toPluginPath('canvas-webrtc', 'replay'),
|
||||
},
|
||||
{
|
||||
input: './src/plugins/console/replay/index.ts',
|
||||
name: 'rrwebConsoleReplay',
|
||||
pathFn: toPluginPath('console', 'replay'),
|
||||
},
|
||||
{
|
||||
input: './src/plugins/sequential-id/record/index.ts',
|
||||
name: 'rrwebSequentialIdRecord',
|
||||
pathFn: toPluginPath('sequential-id', 'record'),
|
||||
},
|
||||
{
|
||||
input: './src/plugins/sequential-id/replay/index.ts',
|
||||
name: 'rrwebSequentialIdReplay',
|
||||
pathFn: toPluginPath('sequential-id', 'replay'),
|
||||
},
|
||||
];
|
||||
|
||||
let configs = [];
|
||||
|
||||
function getPlugins(options = {}) {
|
||||
const { minify = false, sourceMap = false } = options;
|
||||
return [
|
||||
resolve({ browser: true }),
|
||||
webWorkerLoader({
|
||||
targetPlatform: 'browser',
|
||||
inline: true,
|
||||
preserveSource: true,
|
||||
sourceMap,
|
||||
}),
|
||||
esbuild({
|
||||
minify,
|
||||
}),
|
||||
postcss({
|
||||
extract: true,
|
||||
inject: false,
|
||||
minimize: minify,
|
||||
sourceMap,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
for (const c of baseConfigs) {
|
||||
const basePlugins = [
|
||||
resolve({ browser: true }),
|
||||
|
||||
// supports bundling `web-worker:..filename`
|
||||
webWorkerLoader({
|
||||
targetPlatform: 'browser',
|
||||
inline: true,
|
||||
preserveSource: true,
|
||||
}),
|
||||
|
||||
typescript(),
|
||||
];
|
||||
const plugins = basePlugins.concat(
|
||||
postcss({
|
||||
extract: false,
|
||||
inject: false,
|
||||
}),
|
||||
);
|
||||
// browser
|
||||
configs.push({
|
||||
input: c.input,
|
||||
plugins: getPlugins(),
|
||||
output: [
|
||||
{
|
||||
name: c.name,
|
||||
format: 'iife',
|
||||
file: c.pathFn(pkg.unpkg),
|
||||
},
|
||||
],
|
||||
});
|
||||
// browser + minify
|
||||
configs.push({
|
||||
input: c.input,
|
||||
plugins: getPlugins({ minify: true, sourceMap: true }),
|
||||
output: [
|
||||
{
|
||||
name: c.name,
|
||||
format: 'iife',
|
||||
file: toMinPath(c.pathFn(pkg.unpkg)),
|
||||
sourcemap: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
// CommonJS
|
||||
configs.push({
|
||||
input: c.input,
|
||||
plugins,
|
||||
output: [
|
||||
{
|
||||
format: 'cjs',
|
||||
file: c.pathFn('lib/rrweb.cjs'),
|
||||
},
|
||||
],
|
||||
});
|
||||
if (c.esm) {
|
||||
// ES module
|
||||
configs.push({
|
||||
input: c.input,
|
||||
plugins,
|
||||
preserveModules: true,
|
||||
output: [
|
||||
{
|
||||
format: 'esm',
|
||||
dir: 'es/rrweb',
|
||||
plugins: [renameNodeModules('ext')],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.BROWSER_ONLY) {
|
||||
const browserOnlyBaseConfigs = [
|
||||
{
|
||||
input: './src/index.ts',
|
||||
name: 'rrweb',
|
||||
pathFn: (p) => p,
|
||||
},
|
||||
{
|
||||
input: './src/entries/all.ts',
|
||||
name: 'rrweb',
|
||||
pathFn: toAllPath,
|
||||
},
|
||||
{
|
||||
input: './src/plugins/console/record/index.ts',
|
||||
name: 'rrwebConsoleRecord',
|
||||
pathFn: toPluginPath('console', 'record'),
|
||||
},
|
||||
{
|
||||
input: './src/plugins/canvas-webrtc/record/index.ts',
|
||||
name: 'rrwebCanvasWebRTCRecord',
|
||||
pathFn: toPluginPath('canvas-webrtc', 'record'),
|
||||
},
|
||||
{
|
||||
input: './src/plugins/canvas-webrtc/replay/index.ts',
|
||||
name: 'rrwebCanvasWebRTCReplay',
|
||||
pathFn: toPluginPath('canvas-webrtc', 'replay'),
|
||||
},
|
||||
];
|
||||
|
||||
configs = [];
|
||||
|
||||
for (const c of browserOnlyBaseConfigs) {
|
||||
configs.push({
|
||||
input: c.input,
|
||||
plugins: getPlugins(),
|
||||
output: [
|
||||
{
|
||||
name: c.name,
|
||||
format: 'iife',
|
||||
file: c.pathFn(pkg.unpkg),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default configs;
|
||||
@@ -20,9 +20,14 @@ const emitter = new EventEmitter();
|
||||
|
||||
async function injectRecording(frame, serverURL) {
|
||||
try {
|
||||
await frame.addScriptTag({ url: `${serverURL}/rrweb.umd.cjs` });
|
||||
await frame.addScriptTag({
|
||||
url: `${serverURL}/plugins/rrweb-plugin-canvas-webrtc-record.js`,
|
||||
path: path.resolve(__dirname, '../dist/rrweb.umd.cjs'),
|
||||
});
|
||||
await frame.addScriptTag({
|
||||
path: path.resolve(
|
||||
__dirname,
|
||||
'../../plugins/rrweb-plugin-canvas-webrtc-record/dist/rrweb-plugin-canvas-webrtc-record.umd.cjs',
|
||||
),
|
||||
});
|
||||
await frame.evaluate(() => {
|
||||
const win = window;
|
||||
@@ -80,9 +85,14 @@ async function startReplay(page, serverURL, recordedPage) {
|
||||
}, id);
|
||||
});
|
||||
|
||||
await page.addScriptTag({ url: `${serverURL}/rrweb.umd.cjs` });
|
||||
await page.addScriptTag({
|
||||
url: `${serverURL}/plugins/rrweb-plugin-canvas-webrtc-replay.js`,
|
||||
path: path.resolve(__dirname, '../dist/rrweb.umd.cjs'),
|
||||
});
|
||||
await page.addScriptTag({
|
||||
path: path.resolve(
|
||||
__dirname,
|
||||
'../../plugins/rrweb-plugin-canvas-webrtc-replay/dist/rrweb-plugin-canvas-webrtc-replay.umd.cjs',
|
||||
),
|
||||
});
|
||||
|
||||
return page.evaluate(() => {
|
||||
@@ -130,13 +140,18 @@ void (async () => {
|
||||
server = await startServer();
|
||||
serverURL = getServerURL(server);
|
||||
|
||||
const { url } = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'url',
|
||||
message: `Enter the url you want to record, e.g ${defaultURL}: `,
|
||||
},
|
||||
]);
|
||||
const autoUrl = process.env.RRWEB_STREAM_URL;
|
||||
let url = autoUrl;
|
||||
if (!url) {
|
||||
const answers = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'url',
|
||||
message: `Enter the url you want to record, e.g ${defaultURL}: `,
|
||||
},
|
||||
]);
|
||||
url = answers.url;
|
||||
}
|
||||
|
||||
await record(url);
|
||||
|
||||
@@ -163,6 +178,7 @@ void (async () => {
|
||||
const replayingBrowser = await puppeteer.launch({
|
||||
headless: false,
|
||||
devtools,
|
||||
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH,
|
||||
defaultViewport: {
|
||||
width: 1600,
|
||||
height: 900,
|
||||
@@ -184,6 +200,7 @@ void (async () => {
|
||||
const recordingBrowser = await puppeteer.launch({
|
||||
headless: false,
|
||||
devtools,
|
||||
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH,
|
||||
defaultViewport: {
|
||||
width: 1600,
|
||||
height: 900,
|
||||
|
||||
@@ -37,7 +37,10 @@ export const startServer = (defaultPort = 3030) =>
|
||||
try {
|
||||
const data = fs.readFileSync(pathname);
|
||||
const ext = path.parse(pathname).ext;
|
||||
res.setHeader('Content-type', mimeType[ext] || 'text/plain');
|
||||
const contentType = /\.js$/.test(sanitizePath)
|
||||
? 'text/javascript'
|
||||
: mimeType[ext] || 'text/plain';
|
||||
res.setHeader('Content-type', contentType);
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-type');
|
||||
|
||||
@@ -2026,14 +2026,14 @@ export class Replayer {
|
||||
}
|
||||
});
|
||||
|
||||
if (data.replace)
|
||||
if (typeof data.replace === 'string')
|
||||
try {
|
||||
void styleSheet.replace?.(data.replace);
|
||||
} catch (e) {
|
||||
// for safety
|
||||
}
|
||||
|
||||
if (data.replaceSync)
|
||||
if (typeof data.replaceSync === 'string')
|
||||
try {
|
||||
styleSheet.replaceSync?.(data.replaceSync);
|
||||
} catch (e) {
|
||||
|
||||
211
packages/rrweb/test/events/adopted-style-sheet-empty-replace.ts
Normal file
211
packages/rrweb/test/events/adopted-style-sheet-empty-replace.ts
Normal file
@@ -0,0 +1,211 @@
|
||||
import { EventType, IncrementalSource } from '@rrweb/types';
|
||||
import type { eventWithTime } from '@rrweb/types';
|
||||
|
||||
/**
|
||||
* Test events for validating that empty string replace/replaceSync clears stylesheets.
|
||||
* This tests the fix for the bug where `if (data.replace)` would skip empty strings.
|
||||
*/
|
||||
const now = Date.now();
|
||||
export const emptyReplaceSyncEvents: eventWithTime[] = [
|
||||
{
|
||||
type: EventType.Meta,
|
||||
data: {
|
||||
href: 'about:blank',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
},
|
||||
timestamp: now,
|
||||
},
|
||||
{
|
||||
type: EventType.FullSnapshot,
|
||||
data: {
|
||||
node: {
|
||||
type: 0,
|
||||
childNodes: [
|
||||
{
|
||||
type: 1,
|
||||
name: 'html',
|
||||
publicId: '',
|
||||
systemId: '',
|
||||
id: 2,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'html',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'head',
|
||||
attributes: {},
|
||||
childNodes: [],
|
||||
id: 4,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'body',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'div',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: 'test element',
|
||||
id: 6,
|
||||
},
|
||||
],
|
||||
id: 5,
|
||||
},
|
||||
],
|
||||
id: 3,
|
||||
},
|
||||
],
|
||||
id: 7,
|
||||
},
|
||||
],
|
||||
id: 1,
|
||||
},
|
||||
initialOffset: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
},
|
||||
},
|
||||
timestamp: now + 100,
|
||||
},
|
||||
// Adopt a stylesheet with initial styles
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.AdoptedStyleSheet,
|
||||
id: 1,
|
||||
styles: [
|
||||
{
|
||||
styleId: 1,
|
||||
rules: [
|
||||
{
|
||||
rule: 'div { background: red; color: white; }',
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
styleIds: [1],
|
||||
},
|
||||
timestamp: now + 200,
|
||||
},
|
||||
// Clear stylesheet using replaceSync('') - this was the bug!
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.StyleSheetRule,
|
||||
styleId: 1,
|
||||
replaceSync: '',
|
||||
},
|
||||
timestamp: now + 300,
|
||||
},
|
||||
];
|
||||
|
||||
export const emptyReplaceEvents: eventWithTime[] = [
|
||||
{
|
||||
type: EventType.Meta,
|
||||
data: {
|
||||
href: 'about:blank',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
},
|
||||
timestamp: now,
|
||||
},
|
||||
{
|
||||
type: EventType.FullSnapshot,
|
||||
data: {
|
||||
node: {
|
||||
type: 0,
|
||||
childNodes: [
|
||||
{
|
||||
type: 1,
|
||||
name: 'html',
|
||||
publicId: '',
|
||||
systemId: '',
|
||||
id: 2,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'html',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'head',
|
||||
attributes: {},
|
||||
childNodes: [],
|
||||
id: 4,
|
||||
},
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'body',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 2,
|
||||
tagName: 'div',
|
||||
attributes: {},
|
||||
childNodes: [
|
||||
{
|
||||
type: 3,
|
||||
textContent: 'test element',
|
||||
id: 6,
|
||||
},
|
||||
],
|
||||
id: 5,
|
||||
},
|
||||
],
|
||||
id: 3,
|
||||
},
|
||||
],
|
||||
id: 7,
|
||||
},
|
||||
],
|
||||
id: 1,
|
||||
},
|
||||
initialOffset: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
},
|
||||
},
|
||||
timestamp: now + 100,
|
||||
},
|
||||
// Adopt a stylesheet with initial styles
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.AdoptedStyleSheet,
|
||||
id: 1,
|
||||
styles: [
|
||||
{
|
||||
styleId: 1,
|
||||
rules: [
|
||||
{
|
||||
rule: 'div { background: blue; color: yellow; }',
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
styleIds: [1],
|
||||
},
|
||||
timestamp: now + 200,
|
||||
},
|
||||
// Clear stylesheet using replace('') - this was the bug!
|
||||
{
|
||||
type: EventType.IncrementalSnapshot,
|
||||
data: {
|
||||
source: IncrementalSource.StyleSheetRule,
|
||||
styleId: 1,
|
||||
replace: '',
|
||||
},
|
||||
timestamp: now + 300,
|
||||
},
|
||||
];
|
||||
@@ -25,6 +25,10 @@ import StyleSheetTextMutation from './events/style-sheet-text-mutation';
|
||||
import canvasInIframe from './events/canvas-in-iframe';
|
||||
import adoptedStyleSheet from './events/adopted-style-sheet';
|
||||
import adoptedStyleSheetModification from './events/adopted-style-sheet-modification';
|
||||
import {
|
||||
emptyReplaceSyncEvents,
|
||||
emptyReplaceEvents,
|
||||
} from './events/adopted-style-sheet-empty-replace';
|
||||
import nestedStyleDeclarationEvents from './events/nested-style-declaration';
|
||||
import styleDeclarationMissingRuleEvents from './events/style-declaration-missing-rule';
|
||||
import documentReplacementEvents from './events/document-replacement';
|
||||
@@ -1066,14 +1070,76 @@ describe('replayer', function () {
|
||||
await check600ms();
|
||||
});
|
||||
|
||||
it('can replay StyleDeclaration events on nested CSS rules inside @media', async () => {
|
||||
it('can clear adopted stylesheets with empty replaceSync', async () => {
|
||||
await page.evaluate(`
|
||||
events = ${JSON.stringify(nestedStyleDeclarationEvents)};
|
||||
events = ${JSON.stringify(emptyReplaceSyncEvents)};
|
||||
|
||||
const { Replayer } = rrweb;
|
||||
var replayer = new Replayer(events, { showDebug: true });
|
||||
replayer.pause(0);
|
||||
`);
|
||||
|
||||
const iframe = await page.$('iframe');
|
||||
const contentDocument = await iframe!.contentFrame()!;
|
||||
|
||||
// At 250ms, stylesheet should have rules
|
||||
await page.evaluate('replayer.pause(250);');
|
||||
expect(
|
||||
await contentDocument!.evaluate(
|
||||
() =>
|
||||
document.adoptedStyleSheets.length === 1 &&
|
||||
document.adoptedStyleSheets[0].cssRules.length === 1,
|
||||
),
|
||||
).toBeTruthy();
|
||||
|
||||
// At 350ms, stylesheet should be empty after replaceSync('')
|
||||
await page.evaluate('replayer.pause(350);');
|
||||
expect(
|
||||
await contentDocument!.evaluate(
|
||||
() =>
|
||||
document.adoptedStyleSheets.length === 1 &&
|
||||
document.adoptedStyleSheets[0].cssRules.length === 0,
|
||||
),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('can clear adopted stylesheets with empty replace', async () => {
|
||||
await page.evaluate(`
|
||||
events = ${JSON.stringify(emptyReplaceEvents)};
|
||||
const { Replayer } = rrweb;
|
||||
var replayer = new Replayer(events, { showDebug: true });
|
||||
replayer.pause(0);
|
||||
`);
|
||||
|
||||
const iframe = await page.$('iframe');
|
||||
const contentDocument = await iframe!.contentFrame()!;
|
||||
|
||||
// At 250ms, stylesheet should have rules
|
||||
await page.evaluate('replayer.pause(250);');
|
||||
expect(
|
||||
await contentDocument!.evaluate(
|
||||
() =>
|
||||
document.adoptedStyleSheets.length === 1 &&
|
||||
document.adoptedStyleSheets[0].cssRules.length === 1,
|
||||
),
|
||||
).toBeTruthy();
|
||||
|
||||
// At 350ms, stylesheet should be empty after replace('')
|
||||
await page.evaluate('replayer.pause(350);');
|
||||
await contentDocument!.waitForFunction(
|
||||
() =>
|
||||
document.adoptedStyleSheets.length === 1 &&
|
||||
document.adoptedStyleSheets[0].cssRules.length === 0,
|
||||
);
|
||||
});
|
||||
|
||||
it('can replay StyleDeclaration events on nested CSS rules inside @media', async () => {
|
||||
await page.evaluate(`
|
||||
events = ${JSON.stringify(nestedStyleDeclarationEvents)};
|
||||
const { Replayer } = rrweb;
|
||||
var replayer = new Replayer(events, { showDebug: true });
|
||||
replayer.pause(0);
|
||||
`);
|
||||
// At 250ms, setProperty on [0, 0] should change background-color to red
|
||||
const bgColorAfterSet = await page.evaluate(`
|
||||
replayer.pause(250);
|
||||
|
||||
@@ -42,11 +42,12 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.9.1"
|
||||
},
|
||||
"browserslist": [
|
||||
|
||||
@@ -42,11 +42,12 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"umd",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"vite": "^5.2.8",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-dts": "^3.8.1"
|
||||
},
|
||||
"dependencies": {}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"semver": "^7.6.3",
|
||||
"type-fest": "^2.19.0",
|
||||
"vite": "^5.3.1",
|
||||
"vite": "^6.0.1",
|
||||
"vite-plugin-web-extension": "^4.1.3",
|
||||
"vite-plugin-zip-pack": "^1.2.2",
|
||||
"webextension-polyfill": "^0.10.0"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"globalDependencies": [
|
||||
".eslintrc.js",
|
||||
".prettierrc",
|
||||
"vite.config.defaults.ts",
|
||||
"vite.config.default.ts",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"globalPassThroughEnv": ["PUPPETEER_HEADLESS", "DISABLE_WORKER_INLINING"],
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/// <reference types="vite/client" />
|
||||
import dts from 'vite-plugin-dts';
|
||||
import { copyFileSync } from 'node:fs';
|
||||
import { copyFileSync, mkdirSync, existsSync } from 'node:fs';
|
||||
import { defineConfig, LibraryOptions, LibraryFormats, Plugin } from 'vite';
|
||||
import { build, Format } from 'esbuild';
|
||||
import { resolve } from 'path';
|
||||
import { resolve, dirname, relative, basename } from 'path';
|
||||
import { umdWrapper } from 'esbuild-plugin-umd-wrapper';
|
||||
import * as fs from 'node:fs';
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
@@ -51,22 +51,38 @@ function minifyAndUMDPlugin({
|
||||
outDir,
|
||||
});
|
||||
} else {
|
||||
const relativeOutputPath = relative(outputOptions.dir!, outputFilePath);
|
||||
const umdBasePath = resolve(
|
||||
dirname(outputOptions.dir!),
|
||||
'umd',
|
||||
relativeOutputPath,
|
||||
);
|
||||
const umdDir = dirname(umdBasePath);
|
||||
if (!existsSync(umdDir)) {
|
||||
mkdirSync(umdDir, { recursive: true });
|
||||
}
|
||||
const outUmd = `${outputFilePath}.umd.cjs`;
|
||||
await buildFile({
|
||||
name,
|
||||
input: inputFilePath,
|
||||
output: `${outputFilePath}.umd.cjs`,
|
||||
output: outUmd,
|
||||
minify: false,
|
||||
isCss: false,
|
||||
outDir,
|
||||
});
|
||||
// Workaround because jsdelivr does use correct mime types for .umd.cjs
|
||||
// More info: https://github.com/jsdelivr/jsdelivr/issues/18584 https://github.com/rrweb-io/rrweb/pull/1704
|
||||
copyFileSync(outUmd, `${umdBasePath}.js`);
|
||||
const outUmdMin = `${outputFilePath}.umd.min.cjs`;
|
||||
await buildFile({
|
||||
name,
|
||||
input: inputFilePath,
|
||||
output: `${outputFilePath}.umd.min.cjs`,
|
||||
output: outUmdMin,
|
||||
minify: true,
|
||||
isCss: false,
|
||||
outDir,
|
||||
});
|
||||
copyFileSync(outUmdMin, `${umdBasePath}.min.js`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,7 +119,7 @@ async function buildFile({
|
||||
}),
|
||||
],
|
||||
});
|
||||
const filename = output.replace(new RegExp(`^.+/(${outDir}/)`), '$1');
|
||||
const filename = relative(process.cwd(), output).split(/\\/g).join('/');
|
||||
console.log(filename);
|
||||
console.log(`${filename}.map`);
|
||||
}
|
||||
@@ -121,6 +137,7 @@ export default function (
|
||||
build: {
|
||||
// See https://vitejs.dev/guide/build.html#library-mode
|
||||
lib: {
|
||||
cssFileName: 'style', // maintain same file output name as Vite 5 after upgrade to 6
|
||||
entry,
|
||||
name,
|
||||
fileName,
|
||||
@@ -139,12 +156,6 @@ export default function (
|
||||
minify: false,
|
||||
|
||||
sourcemap: true,
|
||||
|
||||
// rollupOptions: {
|
||||
// output: {
|
||||
// manualChunks: {},
|
||||
// },
|
||||
// },
|
||||
},
|
||||
plugins: [
|
||||
dts({
|
||||
|
||||
415
yarn.lock
415
yarn.lock
@@ -1510,230 +1510,240 @@
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537"
|
||||
integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==
|
||||
|
||||
"@esbuild/aix-ppc64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f"
|
||||
integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==
|
||||
"@esbuild/aix-ppc64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461"
|
||||
integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==
|
||||
|
||||
"@esbuild/android-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9"
|
||||
integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==
|
||||
|
||||
"@esbuild/android-arm64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052"
|
||||
integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==
|
||||
"@esbuild/android-arm64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894"
|
||||
integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==
|
||||
|
||||
"@esbuild/android-arm@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995"
|
||||
integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==
|
||||
|
||||
"@esbuild/android-arm@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28"
|
||||
integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==
|
||||
"@esbuild/android-arm@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3"
|
||||
integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==
|
||||
|
||||
"@esbuild/android-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98"
|
||||
integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==
|
||||
|
||||
"@esbuild/android-x64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e"
|
||||
integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==
|
||||
"@esbuild/android-x64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb"
|
||||
integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==
|
||||
|
||||
"@esbuild/darwin-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb"
|
||||
integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==
|
||||
|
||||
"@esbuild/darwin-arm64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a"
|
||||
integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==
|
||||
"@esbuild/darwin-arm64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936"
|
||||
integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==
|
||||
|
||||
"@esbuild/darwin-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0"
|
||||
integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==
|
||||
|
||||
"@esbuild/darwin-x64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22"
|
||||
integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==
|
||||
"@esbuild/darwin-x64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9"
|
||||
integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911"
|
||||
integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e"
|
||||
integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==
|
||||
"@esbuild/freebsd-arm64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00"
|
||||
integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==
|
||||
|
||||
"@esbuild/freebsd-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c"
|
||||
integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==
|
||||
|
||||
"@esbuild/freebsd-x64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261"
|
||||
integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==
|
||||
"@esbuild/freebsd-x64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f"
|
||||
integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==
|
||||
|
||||
"@esbuild/linux-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5"
|
||||
integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==
|
||||
|
||||
"@esbuild/linux-arm64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b"
|
||||
integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==
|
||||
"@esbuild/linux-arm64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43"
|
||||
integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==
|
||||
|
||||
"@esbuild/linux-arm@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c"
|
||||
integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==
|
||||
|
||||
"@esbuild/linux-arm@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9"
|
||||
integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==
|
||||
"@esbuild/linux-arm@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736"
|
||||
integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==
|
||||
|
||||
"@esbuild/linux-ia32@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa"
|
||||
integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==
|
||||
|
||||
"@esbuild/linux-ia32@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2"
|
||||
integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==
|
||||
"@esbuild/linux-ia32@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5"
|
||||
integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==
|
||||
|
||||
"@esbuild/linux-loong64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5"
|
||||
integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==
|
||||
|
||||
"@esbuild/linux-loong64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df"
|
||||
integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==
|
||||
"@esbuild/linux-loong64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc"
|
||||
integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==
|
||||
|
||||
"@esbuild/linux-mips64el@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa"
|
||||
integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==
|
||||
|
||||
"@esbuild/linux-mips64el@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe"
|
||||
integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==
|
||||
"@esbuild/linux-mips64el@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb"
|
||||
integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==
|
||||
|
||||
"@esbuild/linux-ppc64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20"
|
||||
integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==
|
||||
|
||||
"@esbuild/linux-ppc64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4"
|
||||
integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==
|
||||
"@esbuild/linux-ppc64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412"
|
||||
integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==
|
||||
|
||||
"@esbuild/linux-riscv64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300"
|
||||
integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==
|
||||
|
||||
"@esbuild/linux-riscv64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc"
|
||||
integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==
|
||||
"@esbuild/linux-riscv64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694"
|
||||
integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==
|
||||
|
||||
"@esbuild/linux-s390x@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685"
|
||||
integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==
|
||||
|
||||
"@esbuild/linux-s390x@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de"
|
||||
integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==
|
||||
"@esbuild/linux-s390x@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577"
|
||||
integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==
|
||||
|
||||
"@esbuild/linux-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff"
|
||||
integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==
|
||||
|
||||
"@esbuild/linux-x64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0"
|
||||
integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==
|
||||
"@esbuild/linux-x64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz#8140c9b40da634d380b0b29c837a0b4267aff38f"
|
||||
integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==
|
||||
|
||||
"@esbuild/netbsd-arm64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6"
|
||||
integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==
|
||||
|
||||
"@esbuild/netbsd-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6"
|
||||
integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==
|
||||
|
||||
"@esbuild/netbsd-x64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047"
|
||||
integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==
|
||||
"@esbuild/netbsd-x64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz#7a3a97d77abfd11765a72f1c6f9b18f5396bcc40"
|
||||
integrity sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==
|
||||
|
||||
"@esbuild/openbsd-arm64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f"
|
||||
integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==
|
||||
|
||||
"@esbuild/openbsd-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf"
|
||||
integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==
|
||||
|
||||
"@esbuild/openbsd-x64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70"
|
||||
integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==
|
||||
"@esbuild/openbsd-x64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205"
|
||||
integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==
|
||||
|
||||
"@esbuild/sunos-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f"
|
||||
integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==
|
||||
|
||||
"@esbuild/sunos-x64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b"
|
||||
integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==
|
||||
"@esbuild/sunos-x64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6"
|
||||
integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==
|
||||
|
||||
"@esbuild/win32-arm64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90"
|
||||
integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==
|
||||
|
||||
"@esbuild/win32-arm64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d"
|
||||
integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==
|
||||
"@esbuild/win32-arm64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85"
|
||||
integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==
|
||||
|
||||
"@esbuild/win32-ia32@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23"
|
||||
integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==
|
||||
|
||||
"@esbuild/win32-ia32@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b"
|
||||
integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==
|
||||
"@esbuild/win32-ia32@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2"
|
||||
integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==
|
||||
|
||||
"@esbuild/win32-x64@0.20.2":
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc"
|
||||
integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
|
||||
|
||||
"@esbuild/win32-x64@0.21.5":
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c"
|
||||
integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==
|
||||
"@esbuild/win32-x64@0.24.2":
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b"
|
||||
integrity sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
|
||||
version "4.4.0"
|
||||
@@ -2300,81 +2310,176 @@
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27"
|
||||
integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.0.tgz#42a8e897c7b656adb4edebda3a8b83a57526452f"
|
||||
integrity sha512-G2fUQQANtBPsNwiVFg4zKiPQyjVKZCUdQUol53R8E71J7AsheRMV/Yv/nB8giOcOVqP7//eB5xPqieBYZe9bGg==
|
||||
|
||||
"@rollup/rollup-android-arm64@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203"
|
||||
integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==
|
||||
|
||||
"@rollup/rollup-android-arm64@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.0.tgz#846a73eef25b18ff94bac1e52acab6a7c7ac22fa"
|
||||
integrity sha512-qhFwQ+ljoymC+j5lXRv8DlaJYY/+8vyvYmVx074zrLsu5ZGWYsJNLjPPVJJjhZQpyAKUGPydOq9hRLLNvh1s3A==
|
||||
|
||||
"@rollup/rollup-darwin-arm64@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096"
|
||||
integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==
|
||||
|
||||
"@rollup/rollup-darwin-arm64@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.0.tgz#014ed37f1f7809fdf3442a6b689d3a074a844058"
|
||||
integrity sha512-44n/X3lAlWsEY6vF8CzgCx+LQaoqWGN7TzUfbJDiTIOjJm4+L2Yq+r5a8ytQRGyPqgJDs3Rgyo8eVL7n9iW6AQ==
|
||||
|
||||
"@rollup/rollup-darwin-x64@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c"
|
||||
integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==
|
||||
|
||||
"@rollup/rollup-darwin-x64@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.0.tgz#dde6ed3e56d0b34477fa56c4a199abe5d4b9846b"
|
||||
integrity sha512-F9ct0+ZX5Np6+ZDztxiGCIvlCaW87HBdHcozUfsHnj1WCUTBUubAoanhHUfnUHZABlElyRikI0mgcw/qdEm2VQ==
|
||||
|
||||
"@rollup/rollup-freebsd-arm64@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.0.tgz#8ad634f462a6b7e338257cf64c7baff99618a08e"
|
||||
integrity sha512-JpsGxLBB2EFXBsTLHfkZDsXSpSmKD3VxXCgBQtlPcuAqB8TlqtLcbeMhxXQkCDv1avgwNjF8uEIbq5p+Cee0PA==
|
||||
|
||||
"@rollup/rollup-freebsd-x64@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.0.tgz#9d4d1dbbafcb0354d52ba6515a43c7511dba8052"
|
||||
integrity sha512-wegiyBT6rawdpvnD9lmbOpx5Sph+yVZKHbhnSP9MqUEDX08G4UzMU+D87jrazGE7lRSyTRs6NEYHtzfkJ3FjjQ==
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8"
|
||||
integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.0.tgz#3bd5fcbab92a66e032faef1078915d1dbf27de7a"
|
||||
integrity sha512-3pA7xecItbgOs1A5H58dDvOUEboG5UfpTq3WzAdF54acBbUM+olDJAPkgj1GRJ4ZqE12DZ9/hNS2QZk166v92A==
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549"
|
||||
integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.0.tgz#a77838b9779931ce4fa01326b585eee130f51e60"
|
||||
integrity sha512-Y7XUZEVISGyge51QbYyYAEHwpGgmRrAxQXO3siyYo2kmaj72USSG8LtlQQgAtlGfxYiOwu+2BdbPjzEpcOpRmQ==
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577"
|
||||
integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.0.tgz#ec1b1901b82d57a20184adb61c725dd8991a0bf0"
|
||||
integrity sha512-r7/OTF5MqeBrZo5omPXcTnjvv1GsrdH8a8RerARvDFiDwFpDVDnJyByYM/nX+mvks8XXsgPUxkwe/ltaX2VH7w==
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c"
|
||||
integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.0.tgz#7aa23b45bf489b7204b5a542e857e134742141de"
|
||||
integrity sha512-HJbifC9vex9NqnlodV2BHVFNuzKL5OnsV2dvTw6e1dpZKkNjPG6WUq+nhEYV6Hv2Bv++BXkwcyoGlXnPrjAKXw==
|
||||
|
||||
"@rollup/rollup-linux-loongarch64-gnu@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.0.tgz#7bf0ebd8c5ad08719c3b4786be561d67f95654a7"
|
||||
integrity sha512-VAEzZTD63YglFlWwRj3taofmkV1V3xhebDXffon7msNz4b14xKsz7utO6F8F4cqt8K/ktTl9rm88yryvDpsfOw==
|
||||
|
||||
"@rollup/rollup-linux-powerpc64le-gnu@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf"
|
||||
integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==
|
||||
|
||||
"@rollup/rollup-linux-powerpc64le-gnu@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.0.tgz#e687dfcaf08124aafaaebecef0cc3986675cb9b6"
|
||||
integrity sha512-Sts5DST1jXAc9YH/iik1C9QRsLcCoOScf3dfbY5i4kH9RJpKxiTBXqm7qU5O6zTXBTEZry69bGszr3SMgYmMcQ==
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9"
|
||||
integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.0.tgz#19fce2594f9ce73d1cb0748baf8cd90a7bedc237"
|
||||
integrity sha512-qhlXeV9AqxIyY9/R1h1hBD6eMvQCO34ZmdYvry/K+/MBs6d1nRFLm6BOiITLVI+nFAAB9kUB6sdJRKyVHXnqZw==
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec"
|
||||
integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.0.tgz#fd99b335bb65c59beb7d15ae82be0aafa9883c19"
|
||||
integrity sha512-8ZGN7ExnV0qjXa155Rsfi6H8M4iBBwNLBM9lcVS+4NcSzOFaNqmt7djlox8pN1lWrRPMRRQ8NeDlozIGx3Omsw==
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942"
|
||||
integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.0.tgz#4e8c697bbaa2e2d7212bd42086746c8275721166"
|
||||
integrity sha512-VDzNHtLLI5s7xd/VubyS10mq6TxvZBp+4NRWoW+Hi3tgV05RtVm4qK99+dClwTN1McA6PHwob6DEJ6PlXbY83A==
|
||||
|
||||
"@rollup/rollup-linux-x64-musl@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d"
|
||||
integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==
|
||||
|
||||
"@rollup/rollup-linux-x64-musl@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.0.tgz#0d2f74bd9cfe0553f20f056760a95b293e849ab2"
|
||||
integrity sha512-qcb9qYDlkxz9DxJo7SDhWxTWV1gFuwznjbTiov289pASxlfGbaOD54mgbs9+z94VwrXtKTu+2RqwlSTbiOqxGg==
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf"
|
||||
integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.0.tgz#6534a09fcdd43103645155cedb5bfa65fbf2c23f"
|
||||
integrity sha512-pFDdotFDMXW2AXVbfdUEfidPAk/OtwE/Hd4eYMTNVVaCQ6Yl8et0meDaKNL63L44Haxv4UExpv9ydSf3aSayDg==
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54"
|
||||
integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.0.tgz#8222ccfecffd63a6b0ddbe417d8d959e4f2b11b3"
|
||||
integrity sha512-/TG7WfrCAjeRNDvI4+0AAMoHxea/USWhAzf9PVDFHbcqrQ7hMMKp4jZIy4VEjk72AAfN5k4TiSMRXRKf/0akSw==
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc@4.18.0":
|
||||
version "4.18.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4"
|
||||
integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc@4.32.0":
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.0.tgz#1a40b4792c08094b6479c48c90fe7f4b10ec2f54"
|
||||
integrity sha512-5hqO5S3PTEO2E5VjCePxv40gIgyS2KvO7E7/vvC/NbIW4SIRamkMr1hqj+5Y67fbBWv/bQLB6KelBQmXlyCjWA==
|
||||
|
||||
"@rushstack/node-core-library@4.0.2":
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-4.0.2.tgz#e26854a3314b279d57e8abdb4acce7797d02f554"
|
||||
@@ -2630,6 +2735,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
|
||||
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
|
||||
|
||||
"@types/estree@1.0.6":
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
|
||||
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
|
||||
"@types/filesystem@*":
|
||||
version "0.0.36"
|
||||
resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.36.tgz#7227c2d76bfed1b21819db310816c7821d303857"
|
||||
@@ -4909,34 +5018,36 @@ esbuild@^0.20.1:
|
||||
"@esbuild/win32-ia32" "0.20.2"
|
||||
"@esbuild/win32-x64" "0.20.2"
|
||||
|
||||
esbuild@^0.21.3:
|
||||
version "0.21.5"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d"
|
||||
integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==
|
||||
esbuild@^0.24.2:
|
||||
version "0.24.2"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.2.tgz#b5b55bee7de017bff5fb8a4e3e44f2ebe2c3567d"
|
||||
integrity sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==
|
||||
optionalDependencies:
|
||||
"@esbuild/aix-ppc64" "0.21.5"
|
||||
"@esbuild/android-arm" "0.21.5"
|
||||
"@esbuild/android-arm64" "0.21.5"
|
||||
"@esbuild/android-x64" "0.21.5"
|
||||
"@esbuild/darwin-arm64" "0.21.5"
|
||||
"@esbuild/darwin-x64" "0.21.5"
|
||||
"@esbuild/freebsd-arm64" "0.21.5"
|
||||
"@esbuild/freebsd-x64" "0.21.5"
|
||||
"@esbuild/linux-arm" "0.21.5"
|
||||
"@esbuild/linux-arm64" "0.21.5"
|
||||
"@esbuild/linux-ia32" "0.21.5"
|
||||
"@esbuild/linux-loong64" "0.21.5"
|
||||
"@esbuild/linux-mips64el" "0.21.5"
|
||||
"@esbuild/linux-ppc64" "0.21.5"
|
||||
"@esbuild/linux-riscv64" "0.21.5"
|
||||
"@esbuild/linux-s390x" "0.21.5"
|
||||
"@esbuild/linux-x64" "0.21.5"
|
||||
"@esbuild/netbsd-x64" "0.21.5"
|
||||
"@esbuild/openbsd-x64" "0.21.5"
|
||||
"@esbuild/sunos-x64" "0.21.5"
|
||||
"@esbuild/win32-arm64" "0.21.5"
|
||||
"@esbuild/win32-ia32" "0.21.5"
|
||||
"@esbuild/win32-x64" "0.21.5"
|
||||
"@esbuild/aix-ppc64" "0.24.2"
|
||||
"@esbuild/android-arm" "0.24.2"
|
||||
"@esbuild/android-arm64" "0.24.2"
|
||||
"@esbuild/android-x64" "0.24.2"
|
||||
"@esbuild/darwin-arm64" "0.24.2"
|
||||
"@esbuild/darwin-x64" "0.24.2"
|
||||
"@esbuild/freebsd-arm64" "0.24.2"
|
||||
"@esbuild/freebsd-x64" "0.24.2"
|
||||
"@esbuild/linux-arm" "0.24.2"
|
||||
"@esbuild/linux-arm64" "0.24.2"
|
||||
"@esbuild/linux-ia32" "0.24.2"
|
||||
"@esbuild/linux-loong64" "0.24.2"
|
||||
"@esbuild/linux-mips64el" "0.24.2"
|
||||
"@esbuild/linux-ppc64" "0.24.2"
|
||||
"@esbuild/linux-riscv64" "0.24.2"
|
||||
"@esbuild/linux-s390x" "0.24.2"
|
||||
"@esbuild/linux-x64" "0.24.2"
|
||||
"@esbuild/netbsd-arm64" "0.24.2"
|
||||
"@esbuild/netbsd-x64" "0.24.2"
|
||||
"@esbuild/openbsd-arm64" "0.24.2"
|
||||
"@esbuild/openbsd-x64" "0.24.2"
|
||||
"@esbuild/sunos-x64" "0.24.2"
|
||||
"@esbuild/win32-arm64" "0.24.2"
|
||||
"@esbuild/win32-ia32" "0.24.2"
|
||||
"@esbuild/win32-x64" "0.24.2"
|
||||
|
||||
escalade@^3.1.1, escalade@^3.1.2:
|
||||
version "3.1.2"
|
||||
@@ -7737,6 +7848,11 @@ nanoid@^3.3.7:
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||
|
||||
nanoid@^3.3.8:
|
||||
version "3.3.8"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
|
||||
integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
|
||||
|
||||
nanoid@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e"
|
||||
@@ -8195,6 +8311,11 @@ picocolors@^1.0.0, picocolors@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1"
|
||||
integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
|
||||
|
||||
picocolors@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
|
||||
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
@@ -8302,6 +8423,15 @@ postcss@^8.4.38:
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.2.0"
|
||||
|
||||
postcss@^8.4.49:
|
||||
version "8.5.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.1.tgz#e2272a1f8a807fafa413218245630b5db10a3214"
|
||||
integrity sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==
|
||||
dependencies:
|
||||
nanoid "^3.3.8"
|
||||
picocolors "^1.1.1"
|
||||
source-map-js "^1.2.1"
|
||||
|
||||
preferred-pm@^3.0.0:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/preferred-pm/-/preferred-pm-3.1.3.tgz#4125ea5154603136c3b6444e5f5c94ecf90e4916"
|
||||
@@ -8906,6 +9036,34 @@ rollup@^4.13.0:
|
||||
"@rollup/rollup-win32-x64-msvc" "4.18.0"
|
||||
fsevents "~2.3.2"
|
||||
|
||||
rollup@^4.23.0:
|
||||
version "4.32.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.32.0.tgz#c405bf6fca494d1999d9088f7736d7f03e5cac5a"
|
||||
integrity sha512-JmrhfQR31Q4AuNBjjAX4s+a/Pu/Q8Q9iwjWBsjRH1q52SPFE2NqRMK6fUZKKnvKO6id+h7JIRf0oYsph53eATg==
|
||||
dependencies:
|
||||
"@types/estree" "1.0.6"
|
||||
optionalDependencies:
|
||||
"@rollup/rollup-android-arm-eabi" "4.32.0"
|
||||
"@rollup/rollup-android-arm64" "4.32.0"
|
||||
"@rollup/rollup-darwin-arm64" "4.32.0"
|
||||
"@rollup/rollup-darwin-x64" "4.32.0"
|
||||
"@rollup/rollup-freebsd-arm64" "4.32.0"
|
||||
"@rollup/rollup-freebsd-x64" "4.32.0"
|
||||
"@rollup/rollup-linux-arm-gnueabihf" "4.32.0"
|
||||
"@rollup/rollup-linux-arm-musleabihf" "4.32.0"
|
||||
"@rollup/rollup-linux-arm64-gnu" "4.32.0"
|
||||
"@rollup/rollup-linux-arm64-musl" "4.32.0"
|
||||
"@rollup/rollup-linux-loongarch64-gnu" "4.32.0"
|
||||
"@rollup/rollup-linux-powerpc64le-gnu" "4.32.0"
|
||||
"@rollup/rollup-linux-riscv64-gnu" "4.32.0"
|
||||
"@rollup/rollup-linux-s390x-gnu" "4.32.0"
|
||||
"@rollup/rollup-linux-x64-gnu" "4.32.0"
|
||||
"@rollup/rollup-linux-x64-musl" "4.32.0"
|
||||
"@rollup/rollup-win32-arm64-msvc" "4.32.0"
|
||||
"@rollup/rollup-win32-ia32-msvc" "4.32.0"
|
||||
"@rollup/rollup-win32-x64-msvc" "4.32.0"
|
||||
fsevents "~2.3.2"
|
||||
|
||||
run-async@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/run-async/-/run-async-3.0.0.tgz#42a432f6d76c689522058984384df28be379daad"
|
||||
@@ -9259,6 +9417,11 @@ source-map-js@^1.0.1, source-map-js@^1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
|
||||
integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
|
||||
|
||||
source-map-js@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
|
||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||
|
||||
source-map-support@0.5.21, source-map-support@^0.5.6:
|
||||
version "0.5.21"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
|
||||
@@ -10365,14 +10528,14 @@ vite@^5.0.0, "vite@^5.0.0 || ^4.1.4":
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.3"
|
||||
|
||||
vite@^5.2.8, vite@^5.3.1:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.1.tgz#bb2ca6b5fd7483249d3e86b25026e27ba8a663e6"
|
||||
integrity sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==
|
||||
vite@^6.0.1:
|
||||
version "6.0.11"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-6.0.11.tgz#224497e93e940b34c3357c9ebf2ec20803091ed8"
|
||||
integrity sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==
|
||||
dependencies:
|
||||
esbuild "^0.21.3"
|
||||
postcss "^8.4.38"
|
||||
rollup "^4.13.0"
|
||||
esbuild "^0.24.2"
|
||||
postcss "^8.4.49"
|
||||
rollup "^4.23.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.3"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user