pw-sanitizer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +415 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +113 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/loader.d.ts +30 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +173 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +432 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validator.d.ts +34 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +95 -0
- package/dist/config/validator.js.map +1 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +190 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +82 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +122 -0
- package/dist/logger.js.map +1 -0
- package/dist/processors/html-report.d.ts +27 -0
- package/dist/processors/html-report.d.ts.map +1 -0
- package/dist/processors/html-report.js +220 -0
- package/dist/processors/html-report.js.map +1 -0
- package/dist/processors/screenshot.d.ts +37 -0
- package/dist/processors/screenshot.d.ts.map +1 -0
- package/dist/processors/screenshot.js +52 -0
- package/dist/processors/screenshot.js.map +1 -0
- package/dist/processors/trace-file.d.ts +29 -0
- package/dist/processors/trace-file.d.ts.map +1 -0
- package/dist/processors/trace-file.js +250 -0
- package/dist/processors/trace-file.js.map +1 -0
- package/dist/redact/json-walker.d.ts +28 -0
- package/dist/redact/json-walker.d.ts.map +1 -0
- package/dist/redact/json-walker.js +164 -0
- package/dist/redact/json-walker.js.map +1 -0
- package/dist/redact/matcher.d.ts +25 -0
- package/dist/redact/matcher.d.ts.map +1 -0
- package/dist/redact/matcher.js +130 -0
- package/dist/redact/matcher.js.map +1 -0
- package/dist/redact/pattern-loader.d.ts +25 -0
- package/dist/redact/pattern-loader.d.ts.map +1 -0
- package/dist/redact/pattern-loader.js +111 -0
- package/dist/redact/pattern-loader.js.map +1 -0
- package/dist/redact/pattern-registry.d.ts +17 -0
- package/dist/redact/pattern-registry.d.ts.map +1 -0
- package/dist/redact/pattern-registry.js +58 -0
- package/dist/redact/pattern-registry.js.map +1 -0
- package/dist/remove/detector.d.ts +22 -0
- package/dist/remove/detector.d.ts.map +1 -0
- package/dist/remove/detector.js +152 -0
- package/dist/remove/detector.js.map +1 -0
- package/dist/remove/remover.d.ts +18 -0
- package/dist/remove/remover.d.ts.map +1 -0
- package/dist/remove/remover.js +72 -0
- package/dist/remove/remover.js.map +1 -0
- package/dist/remove/rule-loader.d.ts +25 -0
- package/dist/remove/rule-loader.d.ts.map +1 -0
- package/dist/remove/rule-loader.js +110 -0
- package/dist/remove/rule-loader.js.map +1 -0
- package/dist/remove/rule-registry.d.ts +17 -0
- package/dist/remove/rule-registry.d.ts.map +1 -0
- package/dist/remove/rule-registry.js +58 -0
- package/dist/remove/rule-registry.js.map +1 -0
- package/dist/remove/timestamp-repair.d.ts +28 -0
- package/dist/remove/timestamp-repair.d.ts.map +1 -0
- package/dist/remove/timestamp-repair.js +157 -0
- package/dist/remove/timestamp-repair.js.map +1 -0
- package/dist/reporter.d.ts +44 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +180 -0
- package/dist/reporter.js.map +1 -0
- package/dist/teardown.d.ts +27 -0
- package/dist/teardown.d.ts.map +1 -0
- package/dist/teardown.js +42 -0
- package/dist/teardown.js.map +1 -0
- package/dist/utils.d.ts +36 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +112 -0
- package/dist/utils.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.repairTimestamps = repairTimestamps;
|
|
4
|
+
const logger_js_1 = require("../logger.js");
|
|
5
|
+
/**
|
|
6
|
+
* Repairs the event timeline after steps have been removed, so that the total
|
|
7
|
+
* duration reported in the Playwright UI remains coherent.
|
|
8
|
+
*
|
|
9
|
+
* For each removed event, the duration (`endTime - startTime`) that it occupied
|
|
10
|
+
* is redistributed to an adjacent event according to the chosen strategy:
|
|
11
|
+
*
|
|
12
|
+
* - **`'absorb-into-prev'`** *(default)*: the preceding event's `endTime` is
|
|
13
|
+
* extended by the removed duration. Falls back to shifting the following
|
|
14
|
+
* event's `startTime` if no preceding event exists.
|
|
15
|
+
* - **`'absorb-into-next'`**: the following event's `startTime` is shifted
|
|
16
|
+
* back by the removed duration. Falls back to extending the preceding
|
|
17
|
+
* event if no following event exists.
|
|
18
|
+
* - **`'gap'`**: no adjustment — a visible gap will appear in the timeline.
|
|
19
|
+
*
|
|
20
|
+
* After redistribution, events where `startTime > endTime` are detected and
|
|
21
|
+
* corrected (a warning is emitted for each such case).
|
|
22
|
+
*
|
|
23
|
+
* The input arrays are **never mutated** — a new events array is returned.
|
|
24
|
+
*
|
|
25
|
+
* @param events - The events array **after** step removal (output of {@link removeSteps}).
|
|
26
|
+
* @param removedEvents - The events that were removed (needed to determine their durations).
|
|
27
|
+
* @param strategy - The {@link TimestampStrategy} to apply.
|
|
28
|
+
* @returns A new array of events with adjusted timestamps.
|
|
29
|
+
*/
|
|
30
|
+
function repairTimestamps(events, removedEvents, strategy) {
|
|
31
|
+
if (strategy === 'gap' || removedEvents.length === 0) {
|
|
32
|
+
// No adjustment needed for 'gap' strategy
|
|
33
|
+
return recomputeSuiteTimes(events);
|
|
34
|
+
}
|
|
35
|
+
// Deep clone to ensure immutability
|
|
36
|
+
const result = events.map((e) => ({ ...e }));
|
|
37
|
+
// Process each removed event and adjust surrounding timestamps
|
|
38
|
+
for (const removed of removedEvents) {
|
|
39
|
+
const duration = removed.endTime - removed.startTime;
|
|
40
|
+
if (duration <= 0)
|
|
41
|
+
continue;
|
|
42
|
+
applyStrategy(result, removed, duration, strategy);
|
|
43
|
+
}
|
|
44
|
+
// Validate: no event should have startTime > endTime
|
|
45
|
+
for (const event of result) {
|
|
46
|
+
if (event.startTime > event.endTime) {
|
|
47
|
+
logger_js_1.logger.warn(`Timestamp repair created invalid duration for event ` +
|
|
48
|
+
`"${event.title ?? event.action ?? 'unknown'}": ` +
|
|
49
|
+
`startTime (${event.startTime}) > endTime (${event.endTime}). ` +
|
|
50
|
+
`Setting endTime = startTime.`);
|
|
51
|
+
event.endTime = event.startTime;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return recomputeSuiteTimes(result);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Applies a single timestamp redistribution for one removed event.
|
|
58
|
+
*
|
|
59
|
+
* Mutates the `events` array in place (only called on a cloned copy inside
|
|
60
|
+
* {@link repairTimestamps}).
|
|
61
|
+
*
|
|
62
|
+
* @param events - Shallow-cloned events array to mutate.
|
|
63
|
+
* @param removed - The event that was deleted.
|
|
64
|
+
* @param duration - The duration (`endTime - startTime`) of the removed event in ms.
|
|
65
|
+
* @param strategy - Which adjacent event should absorb the duration.
|
|
66
|
+
*/
|
|
67
|
+
function applyStrategy(events, removed, duration, strategy) {
|
|
68
|
+
if (strategy === 'absorb-into-prev') {
|
|
69
|
+
// Find the event that ended just before or at the removed event's start
|
|
70
|
+
const prev = findPrecedingEvent(events, removed.startTime);
|
|
71
|
+
if (prev) {
|
|
72
|
+
prev.endTime += duration;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Fallback: absorb into next
|
|
76
|
+
const next = findFollowingEvent(events, removed.endTime);
|
|
77
|
+
if (next) {
|
|
78
|
+
next.startTime -= duration;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else if (strategy === 'absorb-into-next') {
|
|
83
|
+
const next = findFollowingEvent(events, removed.endTime);
|
|
84
|
+
if (next) {
|
|
85
|
+
next.startTime -= duration;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Fallback: absorb into prev
|
|
89
|
+
const prev = findPrecedingEvent(events, removed.startTime);
|
|
90
|
+
if (prev) {
|
|
91
|
+
prev.endTime += duration;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Finds the event whose `endTime` is closest to (and no greater than) `time`.
|
|
98
|
+
*
|
|
99
|
+
* Used by the `'absorb-into-prev'` strategy to locate the last event that
|
|
100
|
+
* finished at or before the start of the removed event.
|
|
101
|
+
*
|
|
102
|
+
* @param events - The list of remaining events.
|
|
103
|
+
* @param time - The reference timestamp (`removedEvent.startTime`).
|
|
104
|
+
* @returns The best preceding event, or `undefined` if none qualifies.
|
|
105
|
+
*/
|
|
106
|
+
function findPrecedingEvent(events, time) {
|
|
107
|
+
let best;
|
|
108
|
+
let bestDiff = Infinity;
|
|
109
|
+
for (const event of events) {
|
|
110
|
+
const diff = time - event.endTime;
|
|
111
|
+
if (diff >= 0 && diff < bestDiff) {
|
|
112
|
+
bestDiff = diff;
|
|
113
|
+
best = event;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return best;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Finds the event whose `startTime` is closest to (and no less than) `time`.
|
|
120
|
+
*
|
|
121
|
+
* Used by the `'absorb-into-next'` strategy to locate the first event that
|
|
122
|
+
* starts at or after the end of the removed event.
|
|
123
|
+
*
|
|
124
|
+
* @param events - The list of remaining events.
|
|
125
|
+
* @param time - The reference timestamp (`removedEvent.endTime`).
|
|
126
|
+
* @returns The best following event, or `undefined` if none qualifies.
|
|
127
|
+
*/
|
|
128
|
+
function findFollowingEvent(events, time) {
|
|
129
|
+
let best;
|
|
130
|
+
let bestDiff = Infinity;
|
|
131
|
+
for (const event of events) {
|
|
132
|
+
const diff = event.startTime - time;
|
|
133
|
+
if (diff >= 0 && diff < bestDiff) {
|
|
134
|
+
bestDiff = diff;
|
|
135
|
+
best = event;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return best;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Placeholder for suite-level timestamp recomputation.
|
|
142
|
+
*
|
|
143
|
+
* Suite-level `startTime` / `endTime` aggregation is handled by the Playwright
|
|
144
|
+
* report viewer from the leaf event timestamps; callers may perform their own
|
|
145
|
+
* recomputation after this function returns.
|
|
146
|
+
*
|
|
147
|
+
* @param events - The events array (returned as-is for empty arrays).
|
|
148
|
+
* @returns The same events array.
|
|
149
|
+
*/
|
|
150
|
+
function recomputeSuiteTimes(events) {
|
|
151
|
+
// Nothing to recompute if empty
|
|
152
|
+
if (events.length === 0)
|
|
153
|
+
return events;
|
|
154
|
+
// Suite-level times will be recomputed by callers if needed
|
|
155
|
+
return events;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=timestamp-repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timestamp-repair.js","sourceRoot":"","sources":["../../src/remove/timestamp-repair.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { SanitizerConfig, ProcessResult, SanitizationSummary } from './config/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Aggregates the per-file {@link ProcessResult}s into a single
|
|
4
|
+
* {@link SanitizationSummary} for display and/or JSON export.
|
|
5
|
+
*
|
|
6
|
+
* Aggregation includes:
|
|
7
|
+
* - Total redaction occurrence counts, broken down by pattern ID.
|
|
8
|
+
* - Total step-removal counts, broken down by rule label (with file counts).
|
|
9
|
+
* - Timestamp repair count and the strategy that was used.
|
|
10
|
+
* - Output mode and destination directory from the config.
|
|
11
|
+
*
|
|
12
|
+
* @param results - Per-file results from {@link sanitize} / {@link processHtmlReport} / {@link processTraceFile}.
|
|
13
|
+
* @param config - The sanitizer configuration used for this run.
|
|
14
|
+
* @param patternsLoaded - Number of distinct redact patterns that were active.
|
|
15
|
+
* @param rulesLoaded - Number of distinct removal rules that were active.
|
|
16
|
+
* @param safetyWarnings - Any safety-guard warning messages collected during processing.
|
|
17
|
+
* @returns A fully populated {@link SanitizationSummary}.
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateSummary(results: ProcessResult[], config: SanitizerConfig, patternsLoaded: number, rulesLoaded: number, safetyWarnings: string[]): SanitizationSummary;
|
|
20
|
+
/**
|
|
21
|
+
* Renders a {@link SanitizationSummary} as a formatted table to `stdout`.
|
|
22
|
+
*
|
|
23
|
+
* The output includes:
|
|
24
|
+
* - File counts (HTML reports + trace files).
|
|
25
|
+
* - Per-pattern redaction counts (tree-style, with `├─` / `└─` connectors).
|
|
26
|
+
* - Per-rule removal counts and file coverage.
|
|
27
|
+
* - Timestamp repair count and strategy.
|
|
28
|
+
* - Any safety-guard warnings.
|
|
29
|
+
* - Output mode and destination directory.
|
|
30
|
+
*
|
|
31
|
+
* @param summary - The summary to render (typically from {@link generateSummary}).
|
|
32
|
+
*/
|
|
33
|
+
export declare function printSummary(summary: SanitizationSummary): void;
|
|
34
|
+
/**
|
|
35
|
+
* Serialises a {@link SanitizationSummary} to a JSON file at the given path.
|
|
36
|
+
*
|
|
37
|
+
* Creates parent directories as needed. The JSON is pretty-printed with
|
|
38
|
+
* 2-space indentation for human readability.
|
|
39
|
+
*
|
|
40
|
+
* @param summary - The summary to serialise.
|
|
41
|
+
* @param filePath - Destination file path (absolute or relative to `cwd`).
|
|
42
|
+
*/
|
|
43
|
+
export declare function writeSummaryFile(summary: SanitizationSummary, filePath: string): void;
|
|
44
|
+
//# sourceMappingURL=reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAG3B;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,EAAE,EACxB,MAAM,EAAE,eAAe,EACvB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EAAE,GACvB,mBAAmB,CA8ErB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAqD/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,MAAM,GACf,IAAI,CAKN"}
|
package/dist/reporter.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateSummary = generateSummary;
|
|
37
|
+
exports.printSummary = printSummary;
|
|
38
|
+
exports.writeSummaryFile = writeSummaryFile;
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
const logger_js_1 = require("./logger.js");
|
|
42
|
+
/**
|
|
43
|
+
* Aggregates the per-file {@link ProcessResult}s into a single
|
|
44
|
+
* {@link SanitizationSummary} for display and/or JSON export.
|
|
45
|
+
*
|
|
46
|
+
* Aggregation includes:
|
|
47
|
+
* - Total redaction occurrence counts, broken down by pattern ID.
|
|
48
|
+
* - Total step-removal counts, broken down by rule label (with file counts).
|
|
49
|
+
* - Timestamp repair count and the strategy that was used.
|
|
50
|
+
* - Output mode and destination directory from the config.
|
|
51
|
+
*
|
|
52
|
+
* @param results - Per-file results from {@link sanitize} / {@link processHtmlReport} / {@link processTraceFile}.
|
|
53
|
+
* @param config - The sanitizer configuration used for this run.
|
|
54
|
+
* @param patternsLoaded - Number of distinct redact patterns that were active.
|
|
55
|
+
* @param rulesLoaded - Number of distinct removal rules that were active.
|
|
56
|
+
* @param safetyWarnings - Any safety-guard warning messages collected during processing.
|
|
57
|
+
* @returns A fully populated {@link SanitizationSummary}.
|
|
58
|
+
*/
|
|
59
|
+
function generateSummary(results, config, patternsLoaded, rulesLoaded, safetyWarnings) {
|
|
60
|
+
const reportCount = results.filter((r) => r.file.endsWith('.html')).length;
|
|
61
|
+
const traceCount = results.filter((r) => r.file.endsWith('.zip')).length;
|
|
62
|
+
// Aggregate redaction counts by pattern ID
|
|
63
|
+
const byPatternId = {};
|
|
64
|
+
for (const result of results) {
|
|
65
|
+
for (const match of result.redactionMatches) {
|
|
66
|
+
byPatternId[match.patternId] =
|
|
67
|
+
(byPatternId[match.patternId] ?? 0) + 1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Aggregate removal counts by rule label
|
|
71
|
+
const ruleLabelMap = new Map();
|
|
72
|
+
for (const result of results) {
|
|
73
|
+
for (const match of result.removalMatches) {
|
|
74
|
+
const existing = ruleLabelMap.get(match.ruleLabel);
|
|
75
|
+
if (existing) {
|
|
76
|
+
existing.count++;
|
|
77
|
+
existing.files.add(result.file);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
ruleLabelMap.set(match.ruleLabel, {
|
|
81
|
+
count: 1,
|
|
82
|
+
files: new Set([result.file]),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const totalRedactions = results.reduce((sum, r) => sum + r.redactionsApplied, 0);
|
|
88
|
+
const totalSteps = results.reduce((sum, r) => sum + r.stepsRemoved, 0);
|
|
89
|
+
const totalRepairs = results.reduce((sum, r) => sum + r.timestampRepairs, 0);
|
|
90
|
+
const strategy = config.remove?.timestampStrategy ?? 'absorb-into-prev';
|
|
91
|
+
const mode = config.output?.mode ?? 'copy';
|
|
92
|
+
const dir = config.output?.dir ?? './sanitized-report';
|
|
93
|
+
const summary = {
|
|
94
|
+
processedAt: new Date().toISOString(),
|
|
95
|
+
filesProcessed: { reports: reportCount, traces: traceCount },
|
|
96
|
+
redact: {
|
|
97
|
+
patternsLoaded,
|
|
98
|
+
totalOccurrencesReplaced: totalRedactions,
|
|
99
|
+
byPatternId,
|
|
100
|
+
},
|
|
101
|
+
remove: {
|
|
102
|
+
rulesLoaded,
|
|
103
|
+
totalStepsDeleted: totalSteps,
|
|
104
|
+
timestampRepairs: totalRepairs,
|
|
105
|
+
timestampStrategy: strategy,
|
|
106
|
+
byRuleLabel: Array.from(ruleLabelMap.entries()).map(([label, data]) => ({
|
|
107
|
+
label,
|
|
108
|
+
count: data.count,
|
|
109
|
+
files: data.files.size,
|
|
110
|
+
})),
|
|
111
|
+
safetyGuardWarnings: safetyWarnings,
|
|
112
|
+
},
|
|
113
|
+
output: { mode, dir },
|
|
114
|
+
};
|
|
115
|
+
return summary;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Renders a {@link SanitizationSummary} as a formatted table to `stdout`.
|
|
119
|
+
*
|
|
120
|
+
* The output includes:
|
|
121
|
+
* - File counts (HTML reports + trace files).
|
|
122
|
+
* - Per-pattern redaction counts (tree-style, with `├─` / `└─` connectors).
|
|
123
|
+
* - Per-rule removal counts and file coverage.
|
|
124
|
+
* - Timestamp repair count and strategy.
|
|
125
|
+
* - Any safety-guard warnings.
|
|
126
|
+
* - Output mode and destination directory.
|
|
127
|
+
*
|
|
128
|
+
* @param summary - The summary to render (typically from {@link generateSummary}).
|
|
129
|
+
*/
|
|
130
|
+
function printSummary(summary) {
|
|
131
|
+
const lines = [
|
|
132
|
+
'',
|
|
133
|
+
'playwright-sanitizer — Sanitization Summary',
|
|
134
|
+
'───────────────────────────────────────────────────────────────',
|
|
135
|
+
`Files processed : ${summary.filesProcessed.reports} HTML reports, ${summary.filesProcessed.traces} trace files`,
|
|
136
|
+
];
|
|
137
|
+
if (summary.redact.patternsLoaded > 0) {
|
|
138
|
+
lines.push(`[ redact ] Secrets masked : ${summary.redact.totalOccurrencesReplaced} values across ${summary.redact.patternsLoaded} declared patterns`);
|
|
139
|
+
const patternEntries = Object.entries(summary.redact.byPatternId);
|
|
140
|
+
for (let i = 0; i < patternEntries.length; i++) {
|
|
141
|
+
const [id, count] = patternEntries[i];
|
|
142
|
+
const prefix = i === patternEntries.length - 1 ? ' └─' : ' ├─';
|
|
143
|
+
lines.push(`${prefix} ${id.padEnd(25)}: ${count} occurrences`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (summary.remove.rulesLoaded > 0) {
|
|
147
|
+
lines.push(`[ remove ] Steps deleted : ${summary.remove.totalStepsDeleted} steps across ${summary.remove.rulesLoaded} declared rules`);
|
|
148
|
+
for (let i = 0; i < summary.remove.byRuleLabel.length; i++) {
|
|
149
|
+
const entry = summary.remove.byRuleLabel[i];
|
|
150
|
+
const prefix = i === summary.remove.byRuleLabel.length - 1 ? ' └─' : ' ├─';
|
|
151
|
+
lines.push(`${prefix} ${entry.label.padEnd(40)}: ${entry.count} removed (${entry.files} files)`);
|
|
152
|
+
}
|
|
153
|
+
lines.push(`Timestamp repairs : ${summary.remove.timestampRepairs} adjustments (strategy: ${summary.remove.timestampStrategy})`);
|
|
154
|
+
}
|
|
155
|
+
if (summary.remove.safetyGuardWarnings.length > 0) {
|
|
156
|
+
lines.push('Safety guard warnings:');
|
|
157
|
+
for (const w of summary.remove.safetyGuardWarnings) {
|
|
158
|
+
lines.push(` ⚠ ${w}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
lines.push(`Output : ${summary.output.mode} → ${summary.output.dir}`);
|
|
162
|
+
lines.push('───────────────────────────────────────────────────────────────');
|
|
163
|
+
console.log(lines.join('\n'));
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Serialises a {@link SanitizationSummary} to a JSON file at the given path.
|
|
167
|
+
*
|
|
168
|
+
* Creates parent directories as needed. The JSON is pretty-printed with
|
|
169
|
+
* 2-space indentation for human readability.
|
|
170
|
+
*
|
|
171
|
+
* @param summary - The summary to serialise.
|
|
172
|
+
* @param filePath - Destination file path (absolute or relative to `cwd`).
|
|
173
|
+
*/
|
|
174
|
+
function writeSummaryFile(summary, filePath) {
|
|
175
|
+
const dir = path.dirname(filePath);
|
|
176
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
177
|
+
fs.writeFileSync(filePath, JSON.stringify(summary, null, 2), 'utf-8');
|
|
178
|
+
logger_js_1.logger.verbose(`Summary written to ${filePath}`);
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playwright `globalTeardown` integration for `playwright-sanitizer`.
|
|
3
|
+
*
|
|
4
|
+
* Register this as the `globalTeardown` hook in your Playwright config and the
|
|
5
|
+
* sanitizer will run automatically after every test suite completes. Config is
|
|
6
|
+
* auto-discovered from `playwright-sanitizer.config.ts` (or the `sanitizer`
|
|
7
|
+
* key inside `playwright.config.ts`) — no arguments needed.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // playwright.config.ts
|
|
12
|
+
* import { defineConfig } from '@playwright/test';
|
|
13
|
+
*
|
|
14
|
+
* export default defineConfig({
|
|
15
|
+
* globalTeardown: require.resolve('playwright-sanitizer/teardown'),
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* Errors thrown by the sanitizer are **caught and logged** rather than
|
|
21
|
+
* re-thrown. This is intentional: a post-processing failure must never mask
|
|
22
|
+
* the actual test results that Playwright has already recorded.
|
|
23
|
+
*
|
|
24
|
+
* @returns A promise that resolves when sanitization completes (or fails gracefully).
|
|
25
|
+
*/
|
|
26
|
+
export default function teardown(): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=teardown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teardown.d.ts","sourceRoot":"","sources":["../src/teardown.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAA8B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAUtD"}
|
package/dist/teardown.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = teardown;
|
|
4
|
+
const index_js_1 = require("./index.js");
|
|
5
|
+
const logger_js_1 = require("./logger.js");
|
|
6
|
+
/**
|
|
7
|
+
* Playwright `globalTeardown` integration for `playwright-sanitizer`.
|
|
8
|
+
*
|
|
9
|
+
* Register this as the `globalTeardown` hook in your Playwright config and the
|
|
10
|
+
* sanitizer will run automatically after every test suite completes. Config is
|
|
11
|
+
* auto-discovered from `playwright-sanitizer.config.ts` (or the `sanitizer`
|
|
12
|
+
* key inside `playwright.config.ts`) — no arguments needed.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* // playwright.config.ts
|
|
17
|
+
* import { defineConfig } from '@playwright/test';
|
|
18
|
+
*
|
|
19
|
+
* export default defineConfig({
|
|
20
|
+
* globalTeardown: require.resolve('playwright-sanitizer/teardown'),
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* Errors thrown by the sanitizer are **caught and logged** rather than
|
|
26
|
+
* re-thrown. This is intentional: a post-processing failure must never mask
|
|
27
|
+
* the actual test results that Playwright has already recorded.
|
|
28
|
+
*
|
|
29
|
+
* @returns A promise that resolves when sanitization completes (or fails gracefully).
|
|
30
|
+
*/
|
|
31
|
+
async function teardown() {
|
|
32
|
+
try {
|
|
33
|
+
await (0, index_js_1.sanitize)();
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
// Log the error but don't throw — teardown failures should not
|
|
37
|
+
// mask test results. The sanitizer is a post-processing step.
|
|
38
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
39
|
+
logger_js_1.logger.error(`playwright-sanitizer teardown failed: ${message}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=teardown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teardown.js","sourceRoot":"","sources":["../src/teardown.ts"],"names":[],"mappings":";;AA4BA,2BAUC;AAtCD,yCAAsC;AACtC,2CAAqC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACY,KAAK,UAAU,QAAQ;IACpC,IAAI,CAAC;QACH,MAAM,IAAA,mBAAQ,GAAE,CAAC;IACnB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,+DAA+D;QAC/D,8DAA8D;QAC9D,MAAM,OAAO,GACX,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnD,kBAAM,CAAC,KAAK,CAAC,yCAAyC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;AACH,CAAC"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { SanitizerConfig } from './config/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a directory and returns all files matching a glob pattern.
|
|
4
|
+
* Returns an empty array (with an info log) if the directory does not exist.
|
|
5
|
+
*
|
|
6
|
+
* @param dir - Directory to search in (absolute or relative to `cwd`).
|
|
7
|
+
* @param pattern - Glob pattern relative to `dir` (e.g. `'**\\/*.html'`).
|
|
8
|
+
* @returns Absolute paths of all matching files.
|
|
9
|
+
*/
|
|
10
|
+
export declare function findFiles(dir: string, pattern: string): Promise<string[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Computes the destination path for a sanitized output file.
|
|
13
|
+
*
|
|
14
|
+
* - **`in-place`** / **`side-by-side`**: returns `inputPath` as-is.
|
|
15
|
+
* - **`copy`**: mirrors `inputPath` relative to `sourceDir` into the output directory.
|
|
16
|
+
*
|
|
17
|
+
* @param inputPath - Absolute path to the source file.
|
|
18
|
+
* @param sourceDir - Root directory used to compute the relative path fragment.
|
|
19
|
+
* @param config - The full sanitizer configuration (read for `output.mode` and `output.dir`).
|
|
20
|
+
* @returns The computed output path.
|
|
21
|
+
*/
|
|
22
|
+
export declare function computeOutputPath(inputPath: string, sourceDir: string, config: SanitizerConfig): string;
|
|
23
|
+
/**
|
|
24
|
+
* Writes sanitized content to disk according to the configured output mode.
|
|
25
|
+
*
|
|
26
|
+
* - **`in-place`**: overwrites the original file at `inputPath`.
|
|
27
|
+
* - **`side-by-side`**: writes `<basename>.sanitized<ext>` next to the original.
|
|
28
|
+
* - **`copy`** *(default)*: mirrors the file into `outputPath`, creating parent dirs as needed.
|
|
29
|
+
*
|
|
30
|
+
* @param inputPath - Absolute path to the original file (used for `in-place` and `side-by-side`).
|
|
31
|
+
* @param outputPath - Computed destination path (used for `copy` mode).
|
|
32
|
+
* @param content - The sanitized string or Buffer to write.
|
|
33
|
+
* @param config - The full sanitizer configuration (read for `output.mode`).
|
|
34
|
+
*/
|
|
35
|
+
export declare function writeOutput(inputPath: string, outputPath: string, content: string | Buffer, config: SanitizerConfig): void;
|
|
36
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,eAAe,GACtB,MAAM,CAUR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,MAAM,EAAE,eAAe,GACtB,IAAI,CAmBN"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.findFiles = findFiles;
|
|
37
|
+
exports.computeOutputPath = computeOutputPath;
|
|
38
|
+
exports.writeOutput = writeOutput;
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
const glob_1 = require("glob");
|
|
42
|
+
const logger_js_1 = require("./logger.js");
|
|
43
|
+
/**
|
|
44
|
+
* Resolves a directory and returns all files matching a glob pattern.
|
|
45
|
+
* Returns an empty array (with an info log) if the directory does not exist.
|
|
46
|
+
*
|
|
47
|
+
* @param dir - Directory to search in (absolute or relative to `cwd`).
|
|
48
|
+
* @param pattern - Glob pattern relative to `dir` (e.g. `'**\\/*.html'`).
|
|
49
|
+
* @returns Absolute paths of all matching files.
|
|
50
|
+
*/
|
|
51
|
+
async function findFiles(dir, pattern) {
|
|
52
|
+
const resolvedDir = path.resolve(dir);
|
|
53
|
+
if (!fs.existsSync(resolvedDir)) {
|
|
54
|
+
logger_js_1.logger.info(`Directory not found: ${resolvedDir}`);
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
return (0, glob_1.glob)(pattern, { cwd: resolvedDir, absolute: true });
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Computes the destination path for a sanitized output file.
|
|
61
|
+
*
|
|
62
|
+
* - **`in-place`** / **`side-by-side`**: returns `inputPath` as-is.
|
|
63
|
+
* - **`copy`**: mirrors `inputPath` relative to `sourceDir` into the output directory.
|
|
64
|
+
*
|
|
65
|
+
* @param inputPath - Absolute path to the source file.
|
|
66
|
+
* @param sourceDir - Root directory used to compute the relative path fragment.
|
|
67
|
+
* @param config - The full sanitizer configuration (read for `output.mode` and `output.dir`).
|
|
68
|
+
* @returns The computed output path.
|
|
69
|
+
*/
|
|
70
|
+
function computeOutputPath(inputPath, sourceDir, config) {
|
|
71
|
+
const mode = config.output?.mode ?? 'copy';
|
|
72
|
+
if (mode === 'in-place' || mode === 'side-by-side') {
|
|
73
|
+
return inputPath;
|
|
74
|
+
}
|
|
75
|
+
const outputDir = config.output?.dir ?? './sanitized-report';
|
|
76
|
+
const relative = path.relative(path.resolve(sourceDir), inputPath);
|
|
77
|
+
return path.resolve(outputDir, relative);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Writes sanitized content to disk according to the configured output mode.
|
|
81
|
+
*
|
|
82
|
+
* - **`in-place`**: overwrites the original file at `inputPath`.
|
|
83
|
+
* - **`side-by-side`**: writes `<basename>.sanitized<ext>` next to the original.
|
|
84
|
+
* - **`copy`** *(default)*: mirrors the file into `outputPath`, creating parent dirs as needed.
|
|
85
|
+
*
|
|
86
|
+
* @param inputPath - Absolute path to the original file (used for `in-place` and `side-by-side`).
|
|
87
|
+
* @param outputPath - Computed destination path (used for `copy` mode).
|
|
88
|
+
* @param content - The sanitized string or Buffer to write.
|
|
89
|
+
* @param config - The full sanitizer configuration (read for `output.mode`).
|
|
90
|
+
*/
|
|
91
|
+
function writeOutput(inputPath, outputPath, content, config) {
|
|
92
|
+
const mode = config.output?.mode ?? 'copy';
|
|
93
|
+
if (mode === 'in-place') {
|
|
94
|
+
fs.writeFileSync(inputPath, content);
|
|
95
|
+
logger_js_1.logger.verbose(`Wrote in-place: ${inputPath}`);
|
|
96
|
+
}
|
|
97
|
+
else if (mode === 'side-by-side') {
|
|
98
|
+
const ext = path.extname(inputPath);
|
|
99
|
+
const base = inputPath.slice(0, -ext.length);
|
|
100
|
+
const sidePath = `${base}.sanitized${ext}`;
|
|
101
|
+
fs.writeFileSync(sidePath, content);
|
|
102
|
+
logger_js_1.logger.verbose(`Wrote side-by-side: ${sidePath}`);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// 'copy' mode
|
|
106
|
+
const dir = path.dirname(outputPath);
|
|
107
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
108
|
+
fs.writeFileSync(outputPath, content);
|
|
109
|
+
logger_js_1.logger.verbose(`Wrote copy: ${outputPath}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,8BAQC;AAaD,8CAcC;AAcD,kCAwBC;AAvFD,4CAA8B;AAC9B,gDAAkC;AAClC,+BAA4B;AAE5B,2CAAqC;AAErC;;;;;;;GAOG;AACI,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,OAAe;IAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,kBAAM,CAAC,IAAI,CAAC,wBAAwB,WAAW,EAAE,CAAC,CAAC;QACnD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,IAAA,WAAI,EAAC,OAAO,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,iBAAiB,CAC/B,SAAiB,EACjB,SAAiB,EACjB,MAAuB;IAEvB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC;IAE3C,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;QACnD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,oBAAoB,CAAC;IAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,WAAW,CACzB,SAAiB,EACjB,UAAkB,EAClB,OAAwB,EACxB,MAAuB;IAEvB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,MAAM,CAAC;IAE3C,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACrC,kBAAM,CAAC,OAAO,CAAC,mBAAmB,SAAS,EAAE,CAAC,CAAC;IACjD,CAAC;SAAM,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,GAAG,IAAI,aAAa,GAAG,EAAE,CAAC;QAC3C,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACpC,kBAAM,CAAC,OAAO,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,cAAc;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACrC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACtC,kBAAM,CAAC,OAAO,CAAC,eAAe,UAAU,EAAE,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC"}
|