@skrillex1224/playwright-toolkit 2.1.209 → 2.1.210
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 +4 -3
- package/dist/index.cjs +265 -417
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +265 -417
- package/dist/index.js.map +2 -2
- package/index.d.ts +4 -2
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -4521,7 +4521,7 @@ var Logger = {
|
|
|
4521
4521
|
import delay2 from "delay";
|
|
4522
4522
|
|
|
4523
4523
|
// src/internals/watermarkify.js
|
|
4524
|
-
|
|
4524
|
+
import sharp from "sharp";
|
|
4525
4525
|
var DEFAULT_TIMEZONE_OFFSET = 8;
|
|
4526
4526
|
var DEFAULT_RESOLVER_TIMEOUT_MS = 180;
|
|
4527
4527
|
var DEFAULT_IP_LOOKUP_TIMEOUT_MS = 1e4;
|
|
@@ -4532,6 +4532,11 @@ var DEFAULT_WATERMARK_CELL_HEIGHT = 330;
|
|
|
4532
4532
|
var DEFAULT_STRIP_LOGO_URL = "https://static.heartbitai.com/geo/icon/favicon.png";
|
|
4533
4533
|
var DEFAULT_IP_LOOKUP_URL = "http://myip.ipip.net";
|
|
4534
4534
|
var DEFAULT_LOGO_FETCH_TIMEOUT_MS = 2500;
|
|
4535
|
+
var DEFAULT_STRIP_HEIGHT = 78;
|
|
4536
|
+
var DEFAULT_STRIP_PADDING_LEFT = 20;
|
|
4537
|
+
var DEFAULT_STRIP_PADDING_RIGHT = 22;
|
|
4538
|
+
var DEFAULT_STRIP_GAP = 16;
|
|
4539
|
+
var DEFAULT_STRIP_LABEL_WIDTH = 56;
|
|
4535
4540
|
var WEAK_LOCATION_VALUES = /* @__PURE__ */ new Set(["cn", "\u4E2D\u56FD"]);
|
|
4536
4541
|
var LOCATION_NETWORK_SUFFIX_PATTERNS = [
|
|
4537
4542
|
/(?:中国)?移动$/i,
|
|
@@ -4567,13 +4572,6 @@ var shortenTail = (value, maxLen = 80) => {
|
|
|
4567
4572
|
if (!text || text.length <= maxLen) return text;
|
|
4568
4573
|
return `${text.slice(0, Math.max(0, maxLen - 1)).trimEnd()}\u2026`;
|
|
4569
4574
|
};
|
|
4570
|
-
var shortenMiddle = (value, maxLen = 56, headLen = 32, tailLen = 14) => {
|
|
4571
|
-
const text = toInline(value, Math.max(maxLen * 2, maxLen + headLen + tailLen));
|
|
4572
|
-
if (!text || text.length <= maxLen) return text;
|
|
4573
|
-
const safeHeadLen = Math.max(4, Math.min(headLen, maxLen - 5));
|
|
4574
|
-
const safeTailLen = Math.max(4, Math.min(tailLen, maxLen - safeHeadLen - 1));
|
|
4575
|
-
return `${text.slice(0, safeHeadLen).trimEnd()}\u2026${text.slice(-safeTailLen).trimStart()}`;
|
|
4576
|
-
};
|
|
4577
4575
|
var padDatePart = (value) => String(value).padStart(2, "0");
|
|
4578
4576
|
var formatUtcOffsetLabel = (offsetHours = DEFAULT_TIMEZONE_OFFSET) => {
|
|
4579
4577
|
const sign = offsetHours >= 0 ? "+" : "-";
|
|
@@ -4749,8 +4747,8 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
|
|
|
4749
4747
|
url: baseMeta.url,
|
|
4750
4748
|
hostname: baseMeta.hostname,
|
|
4751
4749
|
title: baseMeta.title,
|
|
4750
|
+
prompt: baseMeta.prompt,
|
|
4752
4751
|
query: baseMeta.query,
|
|
4753
|
-
taskId: baseMeta.taskId,
|
|
4754
4752
|
serverAddr,
|
|
4755
4753
|
signal: controller?.signal
|
|
4756
4754
|
})).catch(() => null),
|
|
@@ -4886,22 +4884,23 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
4886
4884
|
}
|
|
4887
4885
|
return merged;
|
|
4888
4886
|
};
|
|
4889
|
-
var buildWatermarkStamp = ({
|
|
4887
|
+
var buildWatermarkStamp = ({ prompt, captureTime, ip, location }) => {
|
|
4890
4888
|
const parts = [
|
|
4891
|
-
`
|
|
4889
|
+
`Prompt ${shortenTail(prompt, 40) || "-"}`,
|
|
4892
4890
|
`Time ${captureTime}`,
|
|
4893
4891
|
`Loc ${shortenTail(location, 20) || "-"}`,
|
|
4894
4892
|
`IP ${toInline(ip, 24) || "-"}`
|
|
4895
4893
|
];
|
|
4896
4894
|
return parts.join(" | ");
|
|
4897
4895
|
};
|
|
4898
|
-
var buildStripSegments = ({
|
|
4896
|
+
var buildStripSegments = ({ prompt, captureTime, ip, location }) => {
|
|
4897
|
+
const promptValue = toInline(prompt, 240) || "-";
|
|
4899
4898
|
return [
|
|
4900
4899
|
{
|
|
4901
|
-
kind: "
|
|
4902
|
-
label: "
|
|
4903
|
-
value:
|
|
4904
|
-
rawValue:
|
|
4900
|
+
kind: "prompt",
|
|
4901
|
+
label: "Prompt",
|
|
4902
|
+
value: promptValue,
|
|
4903
|
+
rawValue: promptValue
|
|
4905
4904
|
},
|
|
4906
4905
|
{
|
|
4907
4906
|
kind: "time",
|
|
@@ -4923,14 +4922,58 @@ var buildStripSegments = ({ taskId, captureTime, ip, location }) => {
|
|
|
4923
4922
|
}
|
|
4924
4923
|
];
|
|
4925
4924
|
};
|
|
4925
|
+
var escapeXml = (value) => String(value || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4926
|
+
var estimateTextWidth = (value, fontSize = 16) => {
|
|
4927
|
+
const text = String(value || "");
|
|
4928
|
+
let width = 0;
|
|
4929
|
+
for (const char of text) {
|
|
4930
|
+
if (/\s/.test(char)) {
|
|
4931
|
+
width += fontSize * 0.34;
|
|
4932
|
+
} else if (/[\u4e00-\u9fff\u3400-\u4dbf\u3040-\u30ff\uac00-\ud7af]/.test(char)) {
|
|
4933
|
+
width += fontSize * 0.92;
|
|
4934
|
+
} else if (/[A-Z0-9]/.test(char)) {
|
|
4935
|
+
width += fontSize * 0.62;
|
|
4936
|
+
} else {
|
|
4937
|
+
width += fontSize * 0.56;
|
|
4938
|
+
}
|
|
4939
|
+
}
|
|
4940
|
+
return Math.ceil(width);
|
|
4941
|
+
};
|
|
4942
|
+
var fitTextToWidth = (value, maxWidth, fontSize = 16) => {
|
|
4943
|
+
const text = normalizeWhitespace(value);
|
|
4944
|
+
if (!text) return "-";
|
|
4945
|
+
const safeMaxWidth = Math.max(fontSize * 3, Number(maxWidth) || 0);
|
|
4946
|
+
if (estimateTextWidth(text, fontSize) <= safeMaxWidth) {
|
|
4947
|
+
return text;
|
|
4948
|
+
}
|
|
4949
|
+
const ellipsis = "\u2026";
|
|
4950
|
+
const ellipsisWidth = estimateTextWidth(ellipsis, fontSize);
|
|
4951
|
+
let current = "";
|
|
4952
|
+
for (const char of text) {
|
|
4953
|
+
const next = current + char;
|
|
4954
|
+
if (estimateTextWidth(next, fontSize) + ellipsisWidth > safeMaxWidth) {
|
|
4955
|
+
break;
|
|
4956
|
+
}
|
|
4957
|
+
current = next;
|
|
4958
|
+
}
|
|
4959
|
+
return `${current.trimEnd()}${ellipsis}`;
|
|
4960
|
+
};
|
|
4961
|
+
var resolvePromptFields = (options = {}, fallbackTitle = "") => {
|
|
4962
|
+
const query = normalizeText(options.query);
|
|
4963
|
+
const prompt = normalizeText(options.prompt) || query || normalizeText(fallbackTitle) || "\u672A\u63D0\u4F9B Prompt";
|
|
4964
|
+
return {
|
|
4965
|
+
prompt,
|
|
4966
|
+
query: query || prompt
|
|
4967
|
+
};
|
|
4968
|
+
};
|
|
4926
4969
|
var createBaseWatermarkifyOptions = () => ({
|
|
4927
4970
|
enabled: true,
|
|
4928
4971
|
timezoneOffsetHours: DEFAULT_TIMEZONE_OFFSET,
|
|
4929
4972
|
response: null,
|
|
4930
4973
|
ip: "",
|
|
4931
4974
|
location: "",
|
|
4975
|
+
prompt: "",
|
|
4932
4976
|
query: "",
|
|
4933
|
-
taskId: "",
|
|
4934
4977
|
ipLookup: true,
|
|
4935
4978
|
ipLookupTimeoutMs: DEFAULT_IP_LOOKUP_TIMEOUT_MS,
|
|
4936
4979
|
resolver: null,
|
|
@@ -4973,8 +5016,8 @@ var normalizeScreenshotWatermarkify = (value) => {
|
|
|
4973
5016
|
response: source.response ?? null,
|
|
4974
5017
|
ip: normalizeText(source.ip),
|
|
4975
5018
|
location: normalizeText(source.location),
|
|
4976
|
-
|
|
4977
|
-
|
|
5019
|
+
prompt: toInline(source.prompt, 220),
|
|
5020
|
+
query: toInline(source.query, 220),
|
|
4978
5021
|
ipLookup: source.ipLookup !== false,
|
|
4979
5022
|
ipLookupTimeoutMs: Number.isFinite(ipLookupTimeoutMsRaw) ? ipLookupTimeoutMsRaw : DEFAULT_IP_LOOKUP_TIMEOUT_MS,
|
|
4980
5023
|
resolver: typeof source.resolver === "function" ? source.resolver : null,
|
|
@@ -4993,16 +5036,16 @@ var resolveScreenshotWatermarkifyMeta = async (page, options = {}) => {
|
|
|
4993
5036
|
const url = normalizeText(page?.url?.()) || "about:blank";
|
|
4994
5037
|
const title = normalizeText(await page.title().catch(() => "")) || "\u672A\u547D\u540D\u9875\u9762";
|
|
4995
5038
|
const hostname = getHostname(url);
|
|
4996
|
-
const query =
|
|
4997
|
-
const
|
|
4998
|
-
const captureTime = formatTimestampForUtcOffset(
|
|
5039
|
+
const { prompt, query } = resolvePromptFields(options, title);
|
|
5040
|
+
const capturedAt = options.capturedAt instanceof Date ? options.capturedAt : new Date(options.capturedAt || Date.now());
|
|
5041
|
+
const captureTime = formatTimestampForUtcOffset(capturedAt, timezoneOffsetHours);
|
|
4999
5042
|
const [enrichment, stripLogoSrc] = await Promise.all([
|
|
5000
5043
|
resolveEnrichment(page, {
|
|
5001
5044
|
url,
|
|
5002
5045
|
hostname,
|
|
5003
5046
|
title,
|
|
5004
|
-
|
|
5005
|
-
|
|
5047
|
+
prompt,
|
|
5048
|
+
query
|
|
5006
5049
|
}, options),
|
|
5007
5050
|
resolveStripLogoSrc()
|
|
5008
5051
|
]);
|
|
@@ -5010,13 +5053,13 @@ var resolveScreenshotWatermarkifyMeta = async (page, options = {}) => {
|
|
|
5010
5053
|
const location = enrichment.location || "-";
|
|
5011
5054
|
return {
|
|
5012
5055
|
watermarkText: buildWatermarkStamp({
|
|
5013
|
-
|
|
5056
|
+
prompt,
|
|
5014
5057
|
captureTime,
|
|
5015
5058
|
ip,
|
|
5016
5059
|
location
|
|
5017
5060
|
}),
|
|
5018
5061
|
stripSegments: buildStripSegments({
|
|
5019
|
-
|
|
5062
|
+
prompt,
|
|
5020
5063
|
captureTime,
|
|
5021
5064
|
ip,
|
|
5022
5065
|
location
|
|
@@ -5026,395 +5069,199 @@ var resolveScreenshotWatermarkifyMeta = async (page, options = {}) => {
|
|
|
5026
5069
|
stripLogoSrc
|
|
5027
5070
|
};
|
|
5028
5071
|
};
|
|
5029
|
-
var
|
|
5072
|
+
var buildFontFamily = () => 'MiSans, "SF Pro Display", "PingFang SC", "Helvetica Neue", Arial, sans-serif';
|
|
5073
|
+
var buildStripSegmentLayouts = (segments, contentWidth) => {
|
|
5074
|
+
const safeSegments = Array.isArray(segments) ? segments : [];
|
|
5075
|
+
const sectionGap = DEFAULT_STRIP_GAP + 16;
|
|
5076
|
+
const labelWidth = DEFAULT_STRIP_LABEL_WIDTH;
|
|
5077
|
+
const promptFontSize = 15;
|
|
5078
|
+
const otherFontSizes = {
|
|
5079
|
+
time: 17,
|
|
5080
|
+
location: 17,
|
|
5081
|
+
ip: 17
|
|
5082
|
+
};
|
|
5083
|
+
const maxValueWidths = {
|
|
5084
|
+
time: 290,
|
|
5085
|
+
location: 220,
|
|
5086
|
+
ip: 160
|
|
5087
|
+
};
|
|
5088
|
+
const promptSegment = safeSegments.find((segment) => segment?.kind === "prompt") || null;
|
|
5089
|
+
const fixedSegments = safeSegments.filter((segment) => segment?.kind !== "prompt");
|
|
5090
|
+
const fixedLayouts = fixedSegments.map((segment) => {
|
|
5091
|
+
const fontSize = otherFontSizes[segment.kind] || 17;
|
|
5092
|
+
const maxValueWidth = maxValueWidths[segment.kind] || 220;
|
|
5093
|
+
const renderValue = fitTextToWidth(segment.rawValue || segment.value || "-", maxValueWidth, fontSize);
|
|
5094
|
+
const valueWidth = Math.min(maxValueWidth, estimateTextWidth(renderValue, fontSize) + 8);
|
|
5095
|
+
return {
|
|
5096
|
+
...segment,
|
|
5097
|
+
fontSize,
|
|
5098
|
+
labelWidth,
|
|
5099
|
+
renderValue,
|
|
5100
|
+
segmentWidth: labelWidth + valueWidth
|
|
5101
|
+
};
|
|
5102
|
+
});
|
|
5103
|
+
const fixedWidth = fixedLayouts.reduce((sum, segment) => sum + segment.segmentWidth, 0);
|
|
5104
|
+
const totalGapWidth = Math.max(0, safeSegments.length - 1) * sectionGap;
|
|
5105
|
+
const promptValueWidth = Math.max(
|
|
5106
|
+
180,
|
|
5107
|
+
Math.floor(contentWidth - fixedWidth - totalGapWidth - labelWidth)
|
|
5108
|
+
);
|
|
5109
|
+
const promptLayout = promptSegment ? {
|
|
5110
|
+
...promptSegment,
|
|
5111
|
+
fontSize: promptFontSize,
|
|
5112
|
+
labelWidth,
|
|
5113
|
+
renderValue: fitTextToWidth(promptSegment.rawValue || promptSegment.value || "-", promptValueWidth, promptFontSize),
|
|
5114
|
+
segmentWidth: labelWidth + promptValueWidth
|
|
5115
|
+
} : null;
|
|
5116
|
+
return [
|
|
5117
|
+
...promptLayout ? [promptLayout] : [],
|
|
5118
|
+
...fixedLayouts
|
|
5119
|
+
];
|
|
5120
|
+
};
|
|
5121
|
+
var buildWatermarkifySvg = (meta, imageWidth, imageHeight) => {
|
|
5030
5122
|
const hasWatermark = meta?.watermark?.enabled !== false && normalizeText(meta?.watermarkText);
|
|
5031
5123
|
const hasStrip = meta?.strip?.enabled !== false && Array.isArray(meta?.stripSegments) && meta.stripSegments.length > 0;
|
|
5032
|
-
if (!
|
|
5033
|
-
return
|
|
5034
|
-
};
|
|
5124
|
+
if (!hasWatermark && !hasStrip) {
|
|
5125
|
+
return "";
|
|
5035
5126
|
}
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
const
|
|
5043
|
-
|
|
5044
|
-
const
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
const
|
|
5050
|
-
const
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
inset: 0;
|
|
5074
|
-
width: 100%;
|
|
5075
|
-
height: 100%;
|
|
5076
|
-
overflow: hidden;
|
|
5077
|
-
pointer-events: none;
|
|
5078
|
-
font-family: MiSans, "SF Pro Display", "PingFang SC", "Helvetica Neue", Arial, sans-serif;
|
|
5079
|
-
}
|
|
5080
|
-
|
|
5081
|
-
.watermark {
|
|
5082
|
-
position: absolute;
|
|
5083
|
-
inset: 0;
|
|
5084
|
-
overflow: hidden;
|
|
5085
|
-
pointer-events: none;
|
|
5086
|
-
}
|
|
5087
|
-
|
|
5088
|
-
.wmStamp {
|
|
5089
|
-
position: absolute;
|
|
5090
|
-
left: 0;
|
|
5091
|
-
top: 0;
|
|
5092
|
-
transform-origin: left center;
|
|
5093
|
-
pointer-events: none;
|
|
5094
|
-
white-space: nowrap;
|
|
5095
|
-
}
|
|
5096
|
-
|
|
5097
|
-
.wmStampText {
|
|
5098
|
-
color: rgba(17, 17, 17, var(--wm-opacity, 0.15));
|
|
5099
|
-
font-size: 19px;
|
|
5100
|
-
font-weight: 720;
|
|
5101
|
-
line-height: 1;
|
|
5102
|
-
letter-spacing: 0.032em;
|
|
5103
|
-
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.44);
|
|
5104
|
-
-webkit-text-stroke: 0.22px rgba(255, 255, 255, 0.12);
|
|
5105
|
-
font-variant-numeric: tabular-nums;
|
|
5106
|
-
filter: saturate(0.92);
|
|
5107
|
-
}
|
|
5108
|
-
|
|
5109
|
-
.strip {
|
|
5110
|
-
position: absolute;
|
|
5111
|
-
left: 0;
|
|
5112
|
-
right: 0;
|
|
5113
|
-
bottom: 0;
|
|
5114
|
-
min-height: 78px;
|
|
5115
|
-
padding: 0 22px 0 20px;
|
|
5116
|
-
display: flex;
|
|
5117
|
-
align-items: center;
|
|
5118
|
-
overflow: hidden;
|
|
5119
|
-
border-top: 1px solid rgba(17, 17, 17, 0.1);
|
|
5120
|
-
background:
|
|
5121
|
-
linear-gradient(180deg, rgba(255, 255, 255, 0.995) 0%, rgba(248, 248, 247, 0.985) 100%);
|
|
5122
|
-
box-shadow:
|
|
5123
|
-
0 -22px 48px rgba(15, 23, 42, 0.1),
|
|
5124
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.92);
|
|
5125
|
-
backdrop-filter: blur(16px);
|
|
5126
|
-
-webkit-backdrop-filter: blur(16px);
|
|
5127
|
-
}
|
|
5128
|
-
|
|
5129
|
-
.strip::before {
|
|
5130
|
-
content: "";
|
|
5131
|
-
position: absolute;
|
|
5132
|
-
left: 20px;
|
|
5133
|
-
right: 52%;
|
|
5134
|
-
top: 0;
|
|
5135
|
-
height: 2px;
|
|
5136
|
-
border-radius: 999px;
|
|
5137
|
-
background: linear-gradient(
|
|
5138
|
-
90deg,
|
|
5139
|
-
rgba(17, 17, 17, 0.98) 0%,
|
|
5140
|
-
rgba(17, 17, 17, 0.68) 24%,
|
|
5141
|
-
rgba(17, 17, 17, 0.08) 58%,
|
|
5142
|
-
rgba(17, 17, 17, 0) 100%
|
|
5143
|
-
);
|
|
5144
|
-
}
|
|
5145
|
-
|
|
5146
|
-
.stripInner {
|
|
5147
|
-
position: relative;
|
|
5148
|
-
z-index: 1;
|
|
5149
|
-
display: flex;
|
|
5150
|
-
align-items: center;
|
|
5151
|
-
gap: 16px;
|
|
5152
|
-
width: 100%;
|
|
5153
|
-
min-width: 0;
|
|
5154
|
-
}
|
|
5155
|
-
|
|
5156
|
-
.stripLogo {
|
|
5157
|
-
position: relative;
|
|
5158
|
-
width: 28px;
|
|
5159
|
-
height: 28px;
|
|
5160
|
-
flex: none;
|
|
5161
|
-
display: flex;
|
|
5162
|
-
align-items: center;
|
|
5163
|
-
justify-content: center;
|
|
5164
|
-
}
|
|
5165
|
-
|
|
5166
|
-
.stripLogoImg {
|
|
5167
|
-
width: 28px;
|
|
5168
|
-
height: 28px;
|
|
5169
|
-
object-fit: contain;
|
|
5170
|
-
display: block;
|
|
5171
|
-
}
|
|
5172
|
-
|
|
5173
|
-
.segments {
|
|
5174
|
-
display: flex;
|
|
5175
|
-
align-items: center;
|
|
5176
|
-
gap: 0;
|
|
5177
|
-
flex: 1 1 auto;
|
|
5178
|
-
min-width: 0;
|
|
5179
|
-
white-space: nowrap;
|
|
5180
|
-
}
|
|
5181
|
-
|
|
5182
|
-
.segment {
|
|
5183
|
-
position: relative;
|
|
5184
|
-
display: inline-flex;
|
|
5185
|
-
align-items: center;
|
|
5186
|
-
gap: 10px;
|
|
5187
|
-
min-width: 0;
|
|
5188
|
-
flex: none;
|
|
5189
|
-
padding-right: 16px;
|
|
5190
|
-
margin-right: 16px;
|
|
5191
|
-
}
|
|
5192
|
-
|
|
5193
|
-
.segment:not(:last-child)::after {
|
|
5194
|
-
content: "";
|
|
5195
|
-
position: absolute;
|
|
5196
|
-
top: 50%;
|
|
5197
|
-
right: 0;
|
|
5198
|
-
width: 1px;
|
|
5199
|
-
height: 25px;
|
|
5200
|
-
transform: translateY(-50%);
|
|
5201
|
-
background: linear-gradient(
|
|
5202
|
-
180deg,
|
|
5203
|
-
rgba(148, 163, 184, 0) 0%,
|
|
5204
|
-
rgba(148, 163, 184, 0.34) 24%,
|
|
5205
|
-
rgba(148, 163, 184, 0.34) 76%,
|
|
5206
|
-
rgba(148, 163, 184, 0) 100%
|
|
5207
|
-
);
|
|
5208
|
-
}
|
|
5209
|
-
|
|
5210
|
-
.segmentTaskId {
|
|
5211
|
-
flex: 1 1 auto;
|
|
5212
|
-
max-width: none;
|
|
5213
|
-
min-width: 0;
|
|
5214
|
-
}
|
|
5215
|
-
|
|
5216
|
-
.label {
|
|
5217
|
-
width: 52px;
|
|
5218
|
-
color: rgba(17, 17, 17, 0.42);
|
|
5219
|
-
font-size: 12px;
|
|
5220
|
-
font-weight: 600;
|
|
5221
|
-
line-height: 1;
|
|
5222
|
-
letter-spacing: 0.01em;
|
|
5223
|
-
flex: none;
|
|
5224
|
-
display: inline-flex;
|
|
5225
|
-
align-items: center;
|
|
5226
|
-
justify-content: flex-start;
|
|
5227
|
-
}
|
|
5228
|
-
|
|
5229
|
-
.value {
|
|
5230
|
-
color: #111111;
|
|
5231
|
-
font-size: 18px;
|
|
5232
|
-
font-weight: 710;
|
|
5233
|
-
line-height: 1;
|
|
5234
|
-
min-width: 0;
|
|
5235
|
-
overflow: hidden;
|
|
5236
|
-
text-overflow: ellipsis;
|
|
5237
|
-
font-variant-numeric: tabular-nums;
|
|
5238
|
-
display: inline-flex;
|
|
5239
|
-
align-items: center;
|
|
5240
|
-
}
|
|
5241
|
-
|
|
5242
|
-
.segmentTaskId .value {
|
|
5243
|
-
color: #101010;
|
|
5244
|
-
font-size: 15px;
|
|
5245
|
-
font-weight: 760;
|
|
5246
|
-
letter-spacing: -0.01em;
|
|
5247
|
-
}
|
|
5248
|
-
|
|
5249
|
-
.segmentTime .value {
|
|
5250
|
-
color: #202020;
|
|
5251
|
-
font-size: 17px;
|
|
5252
|
-
font-weight: 700;
|
|
5253
|
-
}
|
|
5254
|
-
|
|
5255
|
-
.segmentLocation .value,
|
|
5256
|
-
.segmentIp .value {
|
|
5257
|
-
color: #2a2a2a;
|
|
5258
|
-
font-size: 17px;
|
|
5259
|
-
font-weight: 700;
|
|
5260
|
-
}
|
|
5261
|
-
|
|
5262
|
-
`;
|
|
5263
|
-
const root = createNode("div", "root");
|
|
5264
|
-
const watermarkNode = createNode("div", "watermark");
|
|
5265
|
-
const stripNode = createNode("div", "strip");
|
|
5266
|
-
const stripInner = createNode("div", "stripInner");
|
|
5267
|
-
const stripLogo = createNode("div", "stripLogo");
|
|
5268
|
-
const stripLogoImg = createNode("img", "stripLogoImg");
|
|
5269
|
-
const stripSegmentsNode = createNode("div", "segments");
|
|
5270
|
-
stripLogoImg.alt = "";
|
|
5271
|
-
stripLogoImg.decoding = "async";
|
|
5272
|
-
stripLogoImg.referrerPolicy = "no-referrer";
|
|
5273
|
-
stripLogoImg.src = safeText(watermarkifyMeta?.stripLogoSrc) || defaults.logoUrl;
|
|
5274
|
-
stripLogo.appendChild(stripLogoImg);
|
|
5275
|
-
stripInner.appendChild(stripLogo);
|
|
5276
|
-
stripInner.appendChild(stripSegmentsNode);
|
|
5277
|
-
stripNode.appendChild(stripInner);
|
|
5278
|
-
root.appendChild(watermarkNode);
|
|
5279
|
-
root.appendChild(stripNode);
|
|
5280
|
-
shadow.appendChild(style);
|
|
5281
|
-
shadow.appendChild(root);
|
|
5282
|
-
mountPoint.appendChild(host);
|
|
5283
|
-
const buildSegmentNode = (segment) => {
|
|
5284
|
-
const kind = String(segment?.kind || "").trim();
|
|
5285
|
-
const label = String(segment?.label || "").trim();
|
|
5286
|
-
const value = String(segment?.value || "").trim();
|
|
5287
|
-
const rawValue = String(segment?.rawValue || value).trim();
|
|
5288
|
-
const classSuffix = kind ? ` segment${kind.slice(0, 1).toUpperCase()}${kind.slice(1)}` : "";
|
|
5289
|
-
const segmentNode = createNode("span", `segment${classSuffix}`);
|
|
5290
|
-
const labelNode = createNode("span", "label");
|
|
5291
|
-
const valueNode = createNode("span", "value");
|
|
5292
|
-
labelNode.textContent = label;
|
|
5293
|
-
valueNode.textContent = value;
|
|
5294
|
-
segmentNode.title = rawValue ? `${label} ${rawValue}` : label;
|
|
5295
|
-
segmentNode.appendChild(labelNode);
|
|
5296
|
-
segmentNode.appendChild(valueNode);
|
|
5297
|
-
return segmentNode;
|
|
5298
|
-
};
|
|
5299
|
-
const renderStrip = () => {
|
|
5300
|
-
const stripSegments = Array.isArray(watermarkifyMeta?.stripSegments) ? watermarkifyMeta.stripSegments : [];
|
|
5301
|
-
if (!watermarkifyMeta?.strip?.enabled || stripSegments.length === 0) {
|
|
5302
|
-
stripNode.remove();
|
|
5303
|
-
return;
|
|
5304
|
-
}
|
|
5305
|
-
const fragment = document.createDocumentFragment();
|
|
5306
|
-
for (const segment of stripSegments) {
|
|
5307
|
-
fragment.appendChild(buildSegmentNode(segment));
|
|
5308
|
-
}
|
|
5309
|
-
stripSegmentsNode.replaceChildren(fragment);
|
|
5310
|
-
};
|
|
5311
|
-
const waitForLogo = async () => {
|
|
5312
|
-
if (!stripLogoImg.getAttribute("src")) {
|
|
5313
|
-
return;
|
|
5314
|
-
}
|
|
5315
|
-
await new Promise((resolve) => {
|
|
5316
|
-
let settled = false;
|
|
5317
|
-
const done = () => {
|
|
5318
|
-
if (settled) return;
|
|
5319
|
-
settled = true;
|
|
5320
|
-
resolve();
|
|
5321
|
-
};
|
|
5322
|
-
const fail = () => {
|
|
5323
|
-
if (settled) return;
|
|
5324
|
-
stripLogo.remove();
|
|
5325
|
-
done();
|
|
5326
|
-
};
|
|
5327
|
-
const timeoutDone = () => {
|
|
5328
|
-
if (settled) return;
|
|
5329
|
-
done();
|
|
5330
|
-
};
|
|
5331
|
-
if (stripLogoImg.complete && stripLogoImg.naturalWidth > 0) {
|
|
5332
|
-
done();
|
|
5333
|
-
return;
|
|
5334
|
-
}
|
|
5335
|
-
if (stripLogoImg.complete && stripLogoImg.naturalWidth === 0) {
|
|
5336
|
-
fail();
|
|
5337
|
-
return;
|
|
5338
|
-
}
|
|
5339
|
-
stripLogoImg.addEventListener("load", done, { once: true });
|
|
5340
|
-
stripLogoImg.addEventListener("error", fail, { once: true });
|
|
5341
|
-
setTimeout(timeoutDone, 2500);
|
|
5342
|
-
});
|
|
5343
|
-
};
|
|
5344
|
-
const renderWatermark = () => {
|
|
5345
|
-
const stampText = safeText(watermarkifyMeta?.watermarkText);
|
|
5346
|
-
if (!watermarkifyMeta?.watermark?.enabled || !stampText) {
|
|
5347
|
-
watermarkNode.remove();
|
|
5348
|
-
return;
|
|
5349
|
-
}
|
|
5350
|
-
const cellWidth = Math.max(680, Number(watermarkifyMeta.watermark.cellWidth) || defaults.cellWidth);
|
|
5351
|
-
const cellHeight = Math.max(260, Number(watermarkifyMeta.watermark.cellHeight) || defaults.cellHeight);
|
|
5352
|
-
const rotateDeg = Number(watermarkifyMeta.watermark.rotateDeg) || defaults.rotateDeg;
|
|
5353
|
-
const opacity = Math.min(0.22, Math.max(0.05, Number(watermarkifyMeta.watermark.opacity) || defaults.opacity));
|
|
5354
|
-
const width = watermarkNode.clientWidth || window.innerWidth || document.documentElement.clientWidth || cellWidth;
|
|
5355
|
-
const height = watermarkNode.clientHeight || window.innerHeight || document.documentElement.clientHeight || cellHeight;
|
|
5356
|
-
const rowOffset = Math.round(cellWidth * 0.24);
|
|
5357
|
-
const startX = -Math.round(cellWidth * 0.16);
|
|
5358
|
-
const startY = -Math.round(cellHeight * 0.12);
|
|
5359
|
-
const cols = Math.ceil((width + cellWidth * 1.1) / cellWidth) + 1;
|
|
5360
|
-
const rows = Math.ceil((height + cellHeight * 0.9) / cellHeight) + 1;
|
|
5361
|
-
const fragment = document.createDocumentFragment();
|
|
5362
|
-
for (let row = 0; row < rows; row += 1) {
|
|
5363
|
-
for (let col = 0; col < cols; col += 1) {
|
|
5364
|
-
const stamp = createNode("div", "wmStamp");
|
|
5365
|
-
const stampTextNode = createNode("div", "wmStampText");
|
|
5366
|
-
const x = startX + col * cellWidth + (row % 2 ? rowOffset : 0);
|
|
5367
|
-
const y = startY + row * cellHeight + (row % 2 ? 14 : -8);
|
|
5368
|
-
stamp.style.transform = `translate(${x}px, ${y}px) rotate(${rotateDeg}deg)`;
|
|
5369
|
-
stampTextNode.style.setProperty("--wm-opacity", String(opacity));
|
|
5370
|
-
stampTextNode.textContent = stampText;
|
|
5371
|
-
stamp.appendChild(stampTextNode);
|
|
5372
|
-
fragment.appendChild(stamp);
|
|
5373
|
-
}
|
|
5127
|
+
const width = Math.max(1, Number(imageWidth) || 1);
|
|
5128
|
+
const height = Math.max(1, Number(imageHeight) || 1);
|
|
5129
|
+
const fontFamily = escapeXml(buildFontFamily());
|
|
5130
|
+
const parts = [];
|
|
5131
|
+
if (hasWatermark) {
|
|
5132
|
+
const stampText = escapeXml(normalizeText(meta.watermarkText));
|
|
5133
|
+
const cellWidth = Math.max(680, Number(meta.watermark?.cellWidth) || DEFAULT_WATERMARK_CELL_WIDTH);
|
|
5134
|
+
const cellHeight = Math.max(260, Number(meta.watermark?.cellHeight) || DEFAULT_WATERMARK_CELL_HEIGHT);
|
|
5135
|
+
const rotateDeg = Number(meta.watermark?.rotateDeg) || DEFAULT_WATERMARK_ROTATE_DEG;
|
|
5136
|
+
const opacity = Math.min(0.22, Math.max(0.05, Number(meta.watermark?.opacity) || DEFAULT_WATERMARK_OPACITY));
|
|
5137
|
+
const rowOffset = Math.round(cellWidth * 0.24);
|
|
5138
|
+
const startX = -Math.round(cellWidth * 0.16);
|
|
5139
|
+
const startY = -Math.round(cellHeight * 0.12);
|
|
5140
|
+
const cols = Math.ceil((width + cellWidth * 1.1) / cellWidth) + 1;
|
|
5141
|
+
const rows = Math.ceil((height + cellHeight * 0.9) / cellHeight) + 1;
|
|
5142
|
+
const stamps = [];
|
|
5143
|
+
for (let row = 0; row < rows; row += 1) {
|
|
5144
|
+
for (let col = 0; col < cols; col += 1) {
|
|
5145
|
+
const x = startX + col * cellWidth + (row % 2 ? rowOffset : 0);
|
|
5146
|
+
const y = startY + row * cellHeight + (row % 2 ? 14 : -8);
|
|
5147
|
+
stamps.push(`
|
|
5148
|
+
<g transform="translate(${x} ${y}) rotate(${rotateDeg})">
|
|
5149
|
+
<text
|
|
5150
|
+
x="0"
|
|
5151
|
+
y="0"
|
|
5152
|
+
fill="#111111"
|
|
5153
|
+
fill-opacity="${opacity}"
|
|
5154
|
+
stroke="#ffffff"
|
|
5155
|
+
stroke-opacity="0.12"
|
|
5156
|
+
stroke-width="0.22"
|
|
5157
|
+
font-family="${fontFamily}"
|
|
5158
|
+
font-size="19"
|
|
5159
|
+
font-weight="720"
|
|
5160
|
+
letter-spacing="0.6"
|
|
5161
|
+
>${stampText}</text>
|
|
5162
|
+
</g>
|
|
5163
|
+
`);
|
|
5374
5164
|
}
|
|
5375
|
-
watermarkNode.replaceChildren(fragment);
|
|
5376
|
-
};
|
|
5377
|
-
let resizeFrame = 0;
|
|
5378
|
-
const queueWatermarkRender = () => {
|
|
5379
|
-
if (!watermarkNode.isConnected) return;
|
|
5380
|
-
cancelAnimationFrame(resizeFrame);
|
|
5381
|
-
resizeFrame = requestAnimationFrame(() => {
|
|
5382
|
-
renderWatermark();
|
|
5383
|
-
});
|
|
5384
|
-
};
|
|
5385
|
-
const handleResize = () => {
|
|
5386
|
-
queueWatermarkRender();
|
|
5387
|
-
};
|
|
5388
|
-
host.__pkCleanup = () => {
|
|
5389
|
-
cancelAnimationFrame(resizeFrame);
|
|
5390
|
-
window.removeEventListener("resize", handleResize);
|
|
5391
|
-
};
|
|
5392
|
-
renderStrip();
|
|
5393
|
-
renderWatermark();
|
|
5394
|
-
queueWatermarkRender();
|
|
5395
|
-
window.addEventListener("resize", handleResize, { passive: true });
|
|
5396
|
-
return waitForLogo();
|
|
5397
|
-
}, {
|
|
5398
|
-
hostId: SCREENSHOT_WATERMARKIFY_HOST_ID,
|
|
5399
|
-
watermarkifyMeta: meta,
|
|
5400
|
-
defaults: {
|
|
5401
|
-
opacity: DEFAULT_WATERMARK_OPACITY,
|
|
5402
|
-
rotateDeg: DEFAULT_WATERMARK_ROTATE_DEG,
|
|
5403
|
-
cellWidth: DEFAULT_WATERMARK_CELL_WIDTH,
|
|
5404
|
-
cellHeight: DEFAULT_WATERMARK_CELL_HEIGHT,
|
|
5405
|
-
logoUrl: DEFAULT_STRIP_LOGO_URL
|
|
5406
5165
|
}
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5166
|
+
parts.push(`<g id="watermarks">${stamps.join("")}</g>`);
|
|
5167
|
+
}
|
|
5168
|
+
if (hasStrip) {
|
|
5169
|
+
const stripHeight = DEFAULT_STRIP_HEIGHT;
|
|
5170
|
+
const stripY = height - stripHeight;
|
|
5171
|
+
const logoSize = 28;
|
|
5172
|
+
const logoX = DEFAULT_STRIP_PADDING_LEFT;
|
|
5173
|
+
const logoY = stripY + Math.round((stripHeight - logoSize) / 2);
|
|
5174
|
+
const contentStartX = logoX + logoSize + DEFAULT_STRIP_GAP;
|
|
5175
|
+
const contentWidth = width - contentStartX - DEFAULT_STRIP_PADDING_RIGHT;
|
|
5176
|
+
const centerY = stripY + stripHeight / 2 + 1;
|
|
5177
|
+
const layouts = buildStripSegmentLayouts(meta.stripSegments, contentWidth);
|
|
5178
|
+
const svgSegments = [];
|
|
5179
|
+
let currentX = contentStartX;
|
|
5180
|
+
layouts.forEach((segment, index) => {
|
|
5181
|
+
const label = escapeXml(segment.label || "");
|
|
5182
|
+
const value = escapeXml(segment.renderValue || "-");
|
|
5183
|
+
const labelX = currentX;
|
|
5184
|
+
const valueX = currentX + segment.labelWidth;
|
|
5185
|
+
svgSegments.push(`
|
|
5186
|
+
<text
|
|
5187
|
+
x="${labelX}"
|
|
5188
|
+
y="${centerY}"
|
|
5189
|
+
fill="#111111"
|
|
5190
|
+
fill-opacity="0.42"
|
|
5191
|
+
font-family="${fontFamily}"
|
|
5192
|
+
font-size="12"
|
|
5193
|
+
font-weight="600"
|
|
5194
|
+
dominant-baseline="middle"
|
|
5195
|
+
>${label}</text>
|
|
5196
|
+
<text
|
|
5197
|
+
x="${valueX}"
|
|
5198
|
+
y="${centerY}"
|
|
5199
|
+
fill="#111111"
|
|
5200
|
+
font-family="${fontFamily}"
|
|
5201
|
+
font-size="${segment.fontSize}"
|
|
5202
|
+
font-weight="${segment.kind === "prompt" ? 760 : 710}"
|
|
5203
|
+
dominant-baseline="middle"
|
|
5204
|
+
>${value}</text>
|
|
5205
|
+
`);
|
|
5206
|
+
currentX += segment.segmentWidth;
|
|
5207
|
+
if (index < layouts.length - 1) {
|
|
5208
|
+
const lineX = currentX + 8;
|
|
5209
|
+
svgSegments.push(`
|
|
5210
|
+
<line
|
|
5211
|
+
x1="${lineX}"
|
|
5212
|
+
y1="${stripY + 26}"
|
|
5213
|
+
x2="${lineX}"
|
|
5214
|
+
y2="${stripY + stripHeight - 26}"
|
|
5215
|
+
stroke="#94a3b8"
|
|
5216
|
+
stroke-opacity="0.34"
|
|
5217
|
+
stroke-width="1"
|
|
5218
|
+
/>
|
|
5219
|
+
`);
|
|
5220
|
+
currentX += DEFAULT_STRIP_GAP + 16;
|
|
5413
5221
|
}
|
|
5414
|
-
host?.remove();
|
|
5415
|
-
}, SCREENSHOT_WATERMARKIFY_HOST_ID).catch(() => {
|
|
5416
5222
|
});
|
|
5417
|
-
|
|
5223
|
+
parts.push(`
|
|
5224
|
+
<g id="strip">
|
|
5225
|
+
<rect x="0" y="${stripY}" width="${width}" height="${stripHeight}" fill="#ffffff" fill-opacity="0.985" />
|
|
5226
|
+
<rect x="0" y="${stripY}" width="${width}" height="1" fill="#111111" fill-opacity="0.10" />
|
|
5227
|
+
<rect x="${DEFAULT_STRIP_PADDING_LEFT}" y="${stripY}" width="${Math.max(120, Math.round(width * 0.42))}" height="2" fill="url(#stripAccent)" />
|
|
5228
|
+
${meta.stripLogoSrc ? `<image href="${escapeXml(meta.stripLogoSrc)}" x="${logoX}" y="${logoY}" width="${logoSize}" height="${logoSize}" />` : ""}
|
|
5229
|
+
${svgSegments.join("")}
|
|
5230
|
+
</g>
|
|
5231
|
+
`);
|
|
5232
|
+
}
|
|
5233
|
+
return `
|
|
5234
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
|
5235
|
+
<defs>
|
|
5236
|
+
<linearGradient id="stripAccent" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
5237
|
+
<stop offset="0%" stop-color="#111111" stop-opacity="0.98" />
|
|
5238
|
+
<stop offset="24%" stop-color="#111111" stop-opacity="0.68" />
|
|
5239
|
+
<stop offset="58%" stop-color="#111111" stop-opacity="0.08" />
|
|
5240
|
+
<stop offset="100%" stop-color="#111111" stop-opacity="0" />
|
|
5241
|
+
</linearGradient>
|
|
5242
|
+
</defs>
|
|
5243
|
+
${parts.join("")}
|
|
5244
|
+
</svg>
|
|
5245
|
+
`;
|
|
5246
|
+
};
|
|
5247
|
+
var watermarkifyScreenshotBuffer = async (buffer, meta) => {
|
|
5248
|
+
const hasWatermark = meta?.watermark?.enabled !== false && normalizeText(meta?.watermarkText);
|
|
5249
|
+
const hasStrip = meta?.strip?.enabled !== false && Array.isArray(meta?.stripSegments) && meta.stripSegments.length > 0;
|
|
5250
|
+
if (!Buffer.isBuffer(buffer) || !meta || !hasWatermark && !hasStrip) {
|
|
5251
|
+
return buffer;
|
|
5252
|
+
}
|
|
5253
|
+
const image = sharp(buffer, { failOn: "none" });
|
|
5254
|
+
const metadata = await image.metadata().catch(() => null);
|
|
5255
|
+
const width = Math.max(1, Number(metadata?.width) || 0);
|
|
5256
|
+
const height = Math.max(1, Number(metadata?.height) || 0);
|
|
5257
|
+
if (!width || !height) {
|
|
5258
|
+
return buffer;
|
|
5259
|
+
}
|
|
5260
|
+
const overlaySvg = buildWatermarkifySvg(meta, width, height);
|
|
5261
|
+
if (!overlaySvg) {
|
|
5262
|
+
return buffer;
|
|
5263
|
+
}
|
|
5264
|
+
return await image.composite([{ input: Buffer.from(overlaySvg), top: 0, left: 0 }]).png().toBuffer();
|
|
5418
5265
|
};
|
|
5419
5266
|
|
|
5420
5267
|
// src/share.js
|
|
@@ -5824,8 +5671,6 @@ var Share = {
|
|
|
5824
5671
|
const restore = options.restore ?? false;
|
|
5825
5672
|
const maxHeight = options.maxHeight ?? 8e3;
|
|
5826
5673
|
const screenshotWatermarkify = normalizeScreenshotWatermarkify(options.watermarkify ?? true);
|
|
5827
|
-
let cleanupScreenshotWatermarkify = async () => {
|
|
5828
|
-
};
|
|
5829
5674
|
try {
|
|
5830
5675
|
const maxScrollHeight = await page.evaluate(() => {
|
|
5831
5676
|
let maxHeight2 = document.body.scrollHeight;
|
|
@@ -5853,19 +5698,22 @@ var Share = {
|
|
|
5853
5698
|
height: targetHeight
|
|
5854
5699
|
});
|
|
5855
5700
|
await delay2(1e3);
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
cleanupScreenshotWatermarkify = await installScreenshotWatermarkify(page, watermarkifyMeta);
|
|
5859
|
-
await delay2(120);
|
|
5860
|
-
}
|
|
5861
|
-
const buffer_ = await capturePageScreenshot(page, {
|
|
5701
|
+
const capturedAt = /* @__PURE__ */ new Date();
|
|
5702
|
+
const rawBuffer = await capturePageScreenshot(page, {
|
|
5862
5703
|
fullPage: true,
|
|
5863
5704
|
type: "png",
|
|
5864
5705
|
maxClipHeight: targetHeight
|
|
5865
5706
|
});
|
|
5707
|
+
if (!screenshotWatermarkify.enabled) {
|
|
5708
|
+
return rawBuffer.toString("base64");
|
|
5709
|
+
}
|
|
5710
|
+
const watermarkifyMeta = await resolveScreenshotWatermarkifyMeta(page, {
|
|
5711
|
+
...screenshotWatermarkify,
|
|
5712
|
+
capturedAt
|
|
5713
|
+
});
|
|
5714
|
+
const buffer_ = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta);
|
|
5866
5715
|
return buffer_.toString("base64");
|
|
5867
5716
|
} finally {
|
|
5868
|
-
await cleanupScreenshotWatermarkify();
|
|
5869
5717
|
if (restore) {
|
|
5870
5718
|
await page.evaluate(() => {
|
|
5871
5719
|
document.querySelectorAll(".__pk_expanded__").forEach((el) => {
|