@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.cjs
CHANGED
|
@@ -4549,7 +4549,7 @@ var Logger = {
|
|
|
4549
4549
|
var import_delay2 = __toESM(require("delay"), 1);
|
|
4550
4550
|
|
|
4551
4551
|
// src/internals/watermarkify.js
|
|
4552
|
-
var
|
|
4552
|
+
var import_sharp = __toESM(require("sharp"), 1);
|
|
4553
4553
|
var DEFAULT_TIMEZONE_OFFSET = 8;
|
|
4554
4554
|
var DEFAULT_RESOLVER_TIMEOUT_MS = 180;
|
|
4555
4555
|
var DEFAULT_IP_LOOKUP_TIMEOUT_MS = 1e4;
|
|
@@ -4560,6 +4560,11 @@ var DEFAULT_WATERMARK_CELL_HEIGHT = 330;
|
|
|
4560
4560
|
var DEFAULT_STRIP_LOGO_URL = "https://static.heartbitai.com/geo/icon/favicon.png";
|
|
4561
4561
|
var DEFAULT_IP_LOOKUP_URL = "http://myip.ipip.net";
|
|
4562
4562
|
var DEFAULT_LOGO_FETCH_TIMEOUT_MS = 2500;
|
|
4563
|
+
var DEFAULT_STRIP_HEIGHT = 78;
|
|
4564
|
+
var DEFAULT_STRIP_PADDING_LEFT = 20;
|
|
4565
|
+
var DEFAULT_STRIP_PADDING_RIGHT = 22;
|
|
4566
|
+
var DEFAULT_STRIP_GAP = 16;
|
|
4567
|
+
var DEFAULT_STRIP_LABEL_WIDTH = 56;
|
|
4563
4568
|
var WEAK_LOCATION_VALUES = /* @__PURE__ */ new Set(["cn", "\u4E2D\u56FD"]);
|
|
4564
4569
|
var LOCATION_NETWORK_SUFFIX_PATTERNS = [
|
|
4565
4570
|
/(?:中国)?移动$/i,
|
|
@@ -4595,13 +4600,6 @@ var shortenTail = (value, maxLen = 80) => {
|
|
|
4595
4600
|
if (!text || text.length <= maxLen) return text;
|
|
4596
4601
|
return `${text.slice(0, Math.max(0, maxLen - 1)).trimEnd()}\u2026`;
|
|
4597
4602
|
};
|
|
4598
|
-
var shortenMiddle = (value, maxLen = 56, headLen = 32, tailLen = 14) => {
|
|
4599
|
-
const text = toInline(value, Math.max(maxLen * 2, maxLen + headLen + tailLen));
|
|
4600
|
-
if (!text || text.length <= maxLen) return text;
|
|
4601
|
-
const safeHeadLen = Math.max(4, Math.min(headLen, maxLen - 5));
|
|
4602
|
-
const safeTailLen = Math.max(4, Math.min(tailLen, maxLen - safeHeadLen - 1));
|
|
4603
|
-
return `${text.slice(0, safeHeadLen).trimEnd()}\u2026${text.slice(-safeTailLen).trimStart()}`;
|
|
4604
|
-
};
|
|
4605
4603
|
var padDatePart = (value) => String(value).padStart(2, "0");
|
|
4606
4604
|
var formatUtcOffsetLabel = (offsetHours = DEFAULT_TIMEZONE_OFFSET) => {
|
|
4607
4605
|
const sign = offsetHours >= 0 ? "+" : "-";
|
|
@@ -4777,8 +4775,8 @@ var resolveWithCustomResolver = async (page, baseMeta, options = {}) => {
|
|
|
4777
4775
|
url: baseMeta.url,
|
|
4778
4776
|
hostname: baseMeta.hostname,
|
|
4779
4777
|
title: baseMeta.title,
|
|
4778
|
+
prompt: baseMeta.prompt,
|
|
4780
4779
|
query: baseMeta.query,
|
|
4781
|
-
taskId: baseMeta.taskId,
|
|
4782
4780
|
serverAddr,
|
|
4783
4781
|
signal: controller?.signal
|
|
4784
4782
|
})).catch(() => null),
|
|
@@ -4914,22 +4912,23 @@ var resolveEnrichment = async (page, baseMeta, options) => {
|
|
|
4914
4912
|
}
|
|
4915
4913
|
return merged;
|
|
4916
4914
|
};
|
|
4917
|
-
var buildWatermarkStamp = ({
|
|
4915
|
+
var buildWatermarkStamp = ({ prompt, captureTime, ip, location }) => {
|
|
4918
4916
|
const parts = [
|
|
4919
|
-
`
|
|
4917
|
+
`Prompt ${shortenTail(prompt, 40) || "-"}`,
|
|
4920
4918
|
`Time ${captureTime}`,
|
|
4921
4919
|
`Loc ${shortenTail(location, 20) || "-"}`,
|
|
4922
4920
|
`IP ${toInline(ip, 24) || "-"}`
|
|
4923
4921
|
];
|
|
4924
4922
|
return parts.join(" | ");
|
|
4925
4923
|
};
|
|
4926
|
-
var buildStripSegments = ({
|
|
4924
|
+
var buildStripSegments = ({ prompt, captureTime, ip, location }) => {
|
|
4925
|
+
const promptValue = toInline(prompt, 240) || "-";
|
|
4927
4926
|
return [
|
|
4928
4927
|
{
|
|
4929
|
-
kind: "
|
|
4930
|
-
label: "
|
|
4931
|
-
value:
|
|
4932
|
-
rawValue:
|
|
4928
|
+
kind: "prompt",
|
|
4929
|
+
label: "Prompt",
|
|
4930
|
+
value: promptValue,
|
|
4931
|
+
rawValue: promptValue
|
|
4933
4932
|
},
|
|
4934
4933
|
{
|
|
4935
4934
|
kind: "time",
|
|
@@ -4951,14 +4950,58 @@ var buildStripSegments = ({ taskId, captureTime, ip, location }) => {
|
|
|
4951
4950
|
}
|
|
4952
4951
|
];
|
|
4953
4952
|
};
|
|
4953
|
+
var escapeXml = (value) => String(value || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4954
|
+
var estimateTextWidth = (value, fontSize = 16) => {
|
|
4955
|
+
const text = String(value || "");
|
|
4956
|
+
let width = 0;
|
|
4957
|
+
for (const char of text) {
|
|
4958
|
+
if (/\s/.test(char)) {
|
|
4959
|
+
width += fontSize * 0.34;
|
|
4960
|
+
} else if (/[\u4e00-\u9fff\u3400-\u4dbf\u3040-\u30ff\uac00-\ud7af]/.test(char)) {
|
|
4961
|
+
width += fontSize * 0.92;
|
|
4962
|
+
} else if (/[A-Z0-9]/.test(char)) {
|
|
4963
|
+
width += fontSize * 0.62;
|
|
4964
|
+
} else {
|
|
4965
|
+
width += fontSize * 0.56;
|
|
4966
|
+
}
|
|
4967
|
+
}
|
|
4968
|
+
return Math.ceil(width);
|
|
4969
|
+
};
|
|
4970
|
+
var fitTextToWidth = (value, maxWidth, fontSize = 16) => {
|
|
4971
|
+
const text = normalizeWhitespace(value);
|
|
4972
|
+
if (!text) return "-";
|
|
4973
|
+
const safeMaxWidth = Math.max(fontSize * 3, Number(maxWidth) || 0);
|
|
4974
|
+
if (estimateTextWidth(text, fontSize) <= safeMaxWidth) {
|
|
4975
|
+
return text;
|
|
4976
|
+
}
|
|
4977
|
+
const ellipsis = "\u2026";
|
|
4978
|
+
const ellipsisWidth = estimateTextWidth(ellipsis, fontSize);
|
|
4979
|
+
let current = "";
|
|
4980
|
+
for (const char of text) {
|
|
4981
|
+
const next = current + char;
|
|
4982
|
+
if (estimateTextWidth(next, fontSize) + ellipsisWidth > safeMaxWidth) {
|
|
4983
|
+
break;
|
|
4984
|
+
}
|
|
4985
|
+
current = next;
|
|
4986
|
+
}
|
|
4987
|
+
return `${current.trimEnd()}${ellipsis}`;
|
|
4988
|
+
};
|
|
4989
|
+
var resolvePromptFields = (options = {}, fallbackTitle = "") => {
|
|
4990
|
+
const query = normalizeText(options.query);
|
|
4991
|
+
const prompt = normalizeText(options.prompt) || query || normalizeText(fallbackTitle) || "\u672A\u63D0\u4F9B Prompt";
|
|
4992
|
+
return {
|
|
4993
|
+
prompt,
|
|
4994
|
+
query: query || prompt
|
|
4995
|
+
};
|
|
4996
|
+
};
|
|
4954
4997
|
var createBaseWatermarkifyOptions = () => ({
|
|
4955
4998
|
enabled: true,
|
|
4956
4999
|
timezoneOffsetHours: DEFAULT_TIMEZONE_OFFSET,
|
|
4957
5000
|
response: null,
|
|
4958
5001
|
ip: "",
|
|
4959
5002
|
location: "",
|
|
5003
|
+
prompt: "",
|
|
4960
5004
|
query: "",
|
|
4961
|
-
taskId: "",
|
|
4962
5005
|
ipLookup: true,
|
|
4963
5006
|
ipLookupTimeoutMs: DEFAULT_IP_LOOKUP_TIMEOUT_MS,
|
|
4964
5007
|
resolver: null,
|
|
@@ -5001,8 +5044,8 @@ var normalizeScreenshotWatermarkify = (value) => {
|
|
|
5001
5044
|
response: source.response ?? null,
|
|
5002
5045
|
ip: normalizeText(source.ip),
|
|
5003
5046
|
location: normalizeText(source.location),
|
|
5004
|
-
|
|
5005
|
-
|
|
5047
|
+
prompt: toInline(source.prompt, 220),
|
|
5048
|
+
query: toInline(source.query, 220),
|
|
5006
5049
|
ipLookup: source.ipLookup !== false,
|
|
5007
5050
|
ipLookupTimeoutMs: Number.isFinite(ipLookupTimeoutMsRaw) ? ipLookupTimeoutMsRaw : DEFAULT_IP_LOOKUP_TIMEOUT_MS,
|
|
5008
5051
|
resolver: typeof source.resolver === "function" ? source.resolver : null,
|
|
@@ -5021,16 +5064,16 @@ var resolveScreenshotWatermarkifyMeta = async (page, options = {}) => {
|
|
|
5021
5064
|
const url = normalizeText(page?.url?.()) || "about:blank";
|
|
5022
5065
|
const title = normalizeText(await page.title().catch(() => "")) || "\u672A\u547D\u540D\u9875\u9762";
|
|
5023
5066
|
const hostname = getHostname(url);
|
|
5024
|
-
const query =
|
|
5025
|
-
const
|
|
5026
|
-
const captureTime = formatTimestampForUtcOffset(
|
|
5067
|
+
const { prompt, query } = resolvePromptFields(options, title);
|
|
5068
|
+
const capturedAt = options.capturedAt instanceof Date ? options.capturedAt : new Date(options.capturedAt || Date.now());
|
|
5069
|
+
const captureTime = formatTimestampForUtcOffset(capturedAt, timezoneOffsetHours);
|
|
5027
5070
|
const [enrichment, stripLogoSrc] = await Promise.all([
|
|
5028
5071
|
resolveEnrichment(page, {
|
|
5029
5072
|
url,
|
|
5030
5073
|
hostname,
|
|
5031
5074
|
title,
|
|
5032
|
-
|
|
5033
|
-
|
|
5075
|
+
prompt,
|
|
5076
|
+
query
|
|
5034
5077
|
}, options),
|
|
5035
5078
|
resolveStripLogoSrc()
|
|
5036
5079
|
]);
|
|
@@ -5038,13 +5081,13 @@ var resolveScreenshotWatermarkifyMeta = async (page, options = {}) => {
|
|
|
5038
5081
|
const location = enrichment.location || "-";
|
|
5039
5082
|
return {
|
|
5040
5083
|
watermarkText: buildWatermarkStamp({
|
|
5041
|
-
|
|
5084
|
+
prompt,
|
|
5042
5085
|
captureTime,
|
|
5043
5086
|
ip,
|
|
5044
5087
|
location
|
|
5045
5088
|
}),
|
|
5046
5089
|
stripSegments: buildStripSegments({
|
|
5047
|
-
|
|
5090
|
+
prompt,
|
|
5048
5091
|
captureTime,
|
|
5049
5092
|
ip,
|
|
5050
5093
|
location
|
|
@@ -5054,395 +5097,199 @@ var resolveScreenshotWatermarkifyMeta = async (page, options = {}) => {
|
|
|
5054
5097
|
stripLogoSrc
|
|
5055
5098
|
};
|
|
5056
5099
|
};
|
|
5057
|
-
var
|
|
5100
|
+
var buildFontFamily = () => 'MiSans, "SF Pro Display", "PingFang SC", "Helvetica Neue", Arial, sans-serif';
|
|
5101
|
+
var buildStripSegmentLayouts = (segments, contentWidth) => {
|
|
5102
|
+
const safeSegments = Array.isArray(segments) ? segments : [];
|
|
5103
|
+
const sectionGap = DEFAULT_STRIP_GAP + 16;
|
|
5104
|
+
const labelWidth = DEFAULT_STRIP_LABEL_WIDTH;
|
|
5105
|
+
const promptFontSize = 15;
|
|
5106
|
+
const otherFontSizes = {
|
|
5107
|
+
time: 17,
|
|
5108
|
+
location: 17,
|
|
5109
|
+
ip: 17
|
|
5110
|
+
};
|
|
5111
|
+
const maxValueWidths = {
|
|
5112
|
+
time: 290,
|
|
5113
|
+
location: 220,
|
|
5114
|
+
ip: 160
|
|
5115
|
+
};
|
|
5116
|
+
const promptSegment = safeSegments.find((segment) => segment?.kind === "prompt") || null;
|
|
5117
|
+
const fixedSegments = safeSegments.filter((segment) => segment?.kind !== "prompt");
|
|
5118
|
+
const fixedLayouts = fixedSegments.map((segment) => {
|
|
5119
|
+
const fontSize = otherFontSizes[segment.kind] || 17;
|
|
5120
|
+
const maxValueWidth = maxValueWidths[segment.kind] || 220;
|
|
5121
|
+
const renderValue = fitTextToWidth(segment.rawValue || segment.value || "-", maxValueWidth, fontSize);
|
|
5122
|
+
const valueWidth = Math.min(maxValueWidth, estimateTextWidth(renderValue, fontSize) + 8);
|
|
5123
|
+
return {
|
|
5124
|
+
...segment,
|
|
5125
|
+
fontSize,
|
|
5126
|
+
labelWidth,
|
|
5127
|
+
renderValue,
|
|
5128
|
+
segmentWidth: labelWidth + valueWidth
|
|
5129
|
+
};
|
|
5130
|
+
});
|
|
5131
|
+
const fixedWidth = fixedLayouts.reduce((sum, segment) => sum + segment.segmentWidth, 0);
|
|
5132
|
+
const totalGapWidth = Math.max(0, safeSegments.length - 1) * sectionGap;
|
|
5133
|
+
const promptValueWidth = Math.max(
|
|
5134
|
+
180,
|
|
5135
|
+
Math.floor(contentWidth - fixedWidth - totalGapWidth - labelWidth)
|
|
5136
|
+
);
|
|
5137
|
+
const promptLayout = promptSegment ? {
|
|
5138
|
+
...promptSegment,
|
|
5139
|
+
fontSize: promptFontSize,
|
|
5140
|
+
labelWidth,
|
|
5141
|
+
renderValue: fitTextToWidth(promptSegment.rawValue || promptSegment.value || "-", promptValueWidth, promptFontSize),
|
|
5142
|
+
segmentWidth: labelWidth + promptValueWidth
|
|
5143
|
+
} : null;
|
|
5144
|
+
return [
|
|
5145
|
+
...promptLayout ? [promptLayout] : [],
|
|
5146
|
+
...fixedLayouts
|
|
5147
|
+
];
|
|
5148
|
+
};
|
|
5149
|
+
var buildWatermarkifySvg = (meta, imageWidth, imageHeight) => {
|
|
5058
5150
|
const hasWatermark = meta?.watermark?.enabled !== false && normalizeText(meta?.watermarkText);
|
|
5059
5151
|
const hasStrip = meta?.strip?.enabled !== false && Array.isArray(meta?.stripSegments) && meta.stripSegments.length > 0;
|
|
5060
|
-
if (!
|
|
5061
|
-
return
|
|
5062
|
-
};
|
|
5152
|
+
if (!hasWatermark && !hasStrip) {
|
|
5153
|
+
return "";
|
|
5063
5154
|
}
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
const
|
|
5071
|
-
|
|
5072
|
-
const
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
const
|
|
5078
|
-
const
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
inset: 0;
|
|
5102
|
-
width: 100%;
|
|
5103
|
-
height: 100%;
|
|
5104
|
-
overflow: hidden;
|
|
5105
|
-
pointer-events: none;
|
|
5106
|
-
font-family: MiSans, "SF Pro Display", "PingFang SC", "Helvetica Neue", Arial, sans-serif;
|
|
5107
|
-
}
|
|
5108
|
-
|
|
5109
|
-
.watermark {
|
|
5110
|
-
position: absolute;
|
|
5111
|
-
inset: 0;
|
|
5112
|
-
overflow: hidden;
|
|
5113
|
-
pointer-events: none;
|
|
5114
|
-
}
|
|
5115
|
-
|
|
5116
|
-
.wmStamp {
|
|
5117
|
-
position: absolute;
|
|
5118
|
-
left: 0;
|
|
5119
|
-
top: 0;
|
|
5120
|
-
transform-origin: left center;
|
|
5121
|
-
pointer-events: none;
|
|
5122
|
-
white-space: nowrap;
|
|
5123
|
-
}
|
|
5124
|
-
|
|
5125
|
-
.wmStampText {
|
|
5126
|
-
color: rgba(17, 17, 17, var(--wm-opacity, 0.15));
|
|
5127
|
-
font-size: 19px;
|
|
5128
|
-
font-weight: 720;
|
|
5129
|
-
line-height: 1;
|
|
5130
|
-
letter-spacing: 0.032em;
|
|
5131
|
-
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.44);
|
|
5132
|
-
-webkit-text-stroke: 0.22px rgba(255, 255, 255, 0.12);
|
|
5133
|
-
font-variant-numeric: tabular-nums;
|
|
5134
|
-
filter: saturate(0.92);
|
|
5135
|
-
}
|
|
5136
|
-
|
|
5137
|
-
.strip {
|
|
5138
|
-
position: absolute;
|
|
5139
|
-
left: 0;
|
|
5140
|
-
right: 0;
|
|
5141
|
-
bottom: 0;
|
|
5142
|
-
min-height: 78px;
|
|
5143
|
-
padding: 0 22px 0 20px;
|
|
5144
|
-
display: flex;
|
|
5145
|
-
align-items: center;
|
|
5146
|
-
overflow: hidden;
|
|
5147
|
-
border-top: 1px solid rgba(17, 17, 17, 0.1);
|
|
5148
|
-
background:
|
|
5149
|
-
linear-gradient(180deg, rgba(255, 255, 255, 0.995) 0%, rgba(248, 248, 247, 0.985) 100%);
|
|
5150
|
-
box-shadow:
|
|
5151
|
-
0 -22px 48px rgba(15, 23, 42, 0.1),
|
|
5152
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.92);
|
|
5153
|
-
backdrop-filter: blur(16px);
|
|
5154
|
-
-webkit-backdrop-filter: blur(16px);
|
|
5155
|
-
}
|
|
5156
|
-
|
|
5157
|
-
.strip::before {
|
|
5158
|
-
content: "";
|
|
5159
|
-
position: absolute;
|
|
5160
|
-
left: 20px;
|
|
5161
|
-
right: 52%;
|
|
5162
|
-
top: 0;
|
|
5163
|
-
height: 2px;
|
|
5164
|
-
border-radius: 999px;
|
|
5165
|
-
background: linear-gradient(
|
|
5166
|
-
90deg,
|
|
5167
|
-
rgba(17, 17, 17, 0.98) 0%,
|
|
5168
|
-
rgba(17, 17, 17, 0.68) 24%,
|
|
5169
|
-
rgba(17, 17, 17, 0.08) 58%,
|
|
5170
|
-
rgba(17, 17, 17, 0) 100%
|
|
5171
|
-
);
|
|
5172
|
-
}
|
|
5173
|
-
|
|
5174
|
-
.stripInner {
|
|
5175
|
-
position: relative;
|
|
5176
|
-
z-index: 1;
|
|
5177
|
-
display: flex;
|
|
5178
|
-
align-items: center;
|
|
5179
|
-
gap: 16px;
|
|
5180
|
-
width: 100%;
|
|
5181
|
-
min-width: 0;
|
|
5182
|
-
}
|
|
5183
|
-
|
|
5184
|
-
.stripLogo {
|
|
5185
|
-
position: relative;
|
|
5186
|
-
width: 28px;
|
|
5187
|
-
height: 28px;
|
|
5188
|
-
flex: none;
|
|
5189
|
-
display: flex;
|
|
5190
|
-
align-items: center;
|
|
5191
|
-
justify-content: center;
|
|
5192
|
-
}
|
|
5193
|
-
|
|
5194
|
-
.stripLogoImg {
|
|
5195
|
-
width: 28px;
|
|
5196
|
-
height: 28px;
|
|
5197
|
-
object-fit: contain;
|
|
5198
|
-
display: block;
|
|
5199
|
-
}
|
|
5200
|
-
|
|
5201
|
-
.segments {
|
|
5202
|
-
display: flex;
|
|
5203
|
-
align-items: center;
|
|
5204
|
-
gap: 0;
|
|
5205
|
-
flex: 1 1 auto;
|
|
5206
|
-
min-width: 0;
|
|
5207
|
-
white-space: nowrap;
|
|
5208
|
-
}
|
|
5209
|
-
|
|
5210
|
-
.segment {
|
|
5211
|
-
position: relative;
|
|
5212
|
-
display: inline-flex;
|
|
5213
|
-
align-items: center;
|
|
5214
|
-
gap: 10px;
|
|
5215
|
-
min-width: 0;
|
|
5216
|
-
flex: none;
|
|
5217
|
-
padding-right: 16px;
|
|
5218
|
-
margin-right: 16px;
|
|
5219
|
-
}
|
|
5220
|
-
|
|
5221
|
-
.segment:not(:last-child)::after {
|
|
5222
|
-
content: "";
|
|
5223
|
-
position: absolute;
|
|
5224
|
-
top: 50%;
|
|
5225
|
-
right: 0;
|
|
5226
|
-
width: 1px;
|
|
5227
|
-
height: 25px;
|
|
5228
|
-
transform: translateY(-50%);
|
|
5229
|
-
background: linear-gradient(
|
|
5230
|
-
180deg,
|
|
5231
|
-
rgba(148, 163, 184, 0) 0%,
|
|
5232
|
-
rgba(148, 163, 184, 0.34) 24%,
|
|
5233
|
-
rgba(148, 163, 184, 0.34) 76%,
|
|
5234
|
-
rgba(148, 163, 184, 0) 100%
|
|
5235
|
-
);
|
|
5236
|
-
}
|
|
5237
|
-
|
|
5238
|
-
.segmentTaskId {
|
|
5239
|
-
flex: 1 1 auto;
|
|
5240
|
-
max-width: none;
|
|
5241
|
-
min-width: 0;
|
|
5242
|
-
}
|
|
5243
|
-
|
|
5244
|
-
.label {
|
|
5245
|
-
width: 52px;
|
|
5246
|
-
color: rgba(17, 17, 17, 0.42);
|
|
5247
|
-
font-size: 12px;
|
|
5248
|
-
font-weight: 600;
|
|
5249
|
-
line-height: 1;
|
|
5250
|
-
letter-spacing: 0.01em;
|
|
5251
|
-
flex: none;
|
|
5252
|
-
display: inline-flex;
|
|
5253
|
-
align-items: center;
|
|
5254
|
-
justify-content: flex-start;
|
|
5255
|
-
}
|
|
5256
|
-
|
|
5257
|
-
.value {
|
|
5258
|
-
color: #111111;
|
|
5259
|
-
font-size: 18px;
|
|
5260
|
-
font-weight: 710;
|
|
5261
|
-
line-height: 1;
|
|
5262
|
-
min-width: 0;
|
|
5263
|
-
overflow: hidden;
|
|
5264
|
-
text-overflow: ellipsis;
|
|
5265
|
-
font-variant-numeric: tabular-nums;
|
|
5266
|
-
display: inline-flex;
|
|
5267
|
-
align-items: center;
|
|
5268
|
-
}
|
|
5269
|
-
|
|
5270
|
-
.segmentTaskId .value {
|
|
5271
|
-
color: #101010;
|
|
5272
|
-
font-size: 15px;
|
|
5273
|
-
font-weight: 760;
|
|
5274
|
-
letter-spacing: -0.01em;
|
|
5275
|
-
}
|
|
5276
|
-
|
|
5277
|
-
.segmentTime .value {
|
|
5278
|
-
color: #202020;
|
|
5279
|
-
font-size: 17px;
|
|
5280
|
-
font-weight: 700;
|
|
5281
|
-
}
|
|
5282
|
-
|
|
5283
|
-
.segmentLocation .value,
|
|
5284
|
-
.segmentIp .value {
|
|
5285
|
-
color: #2a2a2a;
|
|
5286
|
-
font-size: 17px;
|
|
5287
|
-
font-weight: 700;
|
|
5288
|
-
}
|
|
5289
|
-
|
|
5290
|
-
`;
|
|
5291
|
-
const root = createNode("div", "root");
|
|
5292
|
-
const watermarkNode = createNode("div", "watermark");
|
|
5293
|
-
const stripNode = createNode("div", "strip");
|
|
5294
|
-
const stripInner = createNode("div", "stripInner");
|
|
5295
|
-
const stripLogo = createNode("div", "stripLogo");
|
|
5296
|
-
const stripLogoImg = createNode("img", "stripLogoImg");
|
|
5297
|
-
const stripSegmentsNode = createNode("div", "segments");
|
|
5298
|
-
stripLogoImg.alt = "";
|
|
5299
|
-
stripLogoImg.decoding = "async";
|
|
5300
|
-
stripLogoImg.referrerPolicy = "no-referrer";
|
|
5301
|
-
stripLogoImg.src = safeText(watermarkifyMeta?.stripLogoSrc) || defaults.logoUrl;
|
|
5302
|
-
stripLogo.appendChild(stripLogoImg);
|
|
5303
|
-
stripInner.appendChild(stripLogo);
|
|
5304
|
-
stripInner.appendChild(stripSegmentsNode);
|
|
5305
|
-
stripNode.appendChild(stripInner);
|
|
5306
|
-
root.appendChild(watermarkNode);
|
|
5307
|
-
root.appendChild(stripNode);
|
|
5308
|
-
shadow.appendChild(style);
|
|
5309
|
-
shadow.appendChild(root);
|
|
5310
|
-
mountPoint.appendChild(host);
|
|
5311
|
-
const buildSegmentNode = (segment) => {
|
|
5312
|
-
const kind = String(segment?.kind || "").trim();
|
|
5313
|
-
const label = String(segment?.label || "").trim();
|
|
5314
|
-
const value = String(segment?.value || "").trim();
|
|
5315
|
-
const rawValue = String(segment?.rawValue || value).trim();
|
|
5316
|
-
const classSuffix = kind ? ` segment${kind.slice(0, 1).toUpperCase()}${kind.slice(1)}` : "";
|
|
5317
|
-
const segmentNode = createNode("span", `segment${classSuffix}`);
|
|
5318
|
-
const labelNode = createNode("span", "label");
|
|
5319
|
-
const valueNode = createNode("span", "value");
|
|
5320
|
-
labelNode.textContent = label;
|
|
5321
|
-
valueNode.textContent = value;
|
|
5322
|
-
segmentNode.title = rawValue ? `${label} ${rawValue}` : label;
|
|
5323
|
-
segmentNode.appendChild(labelNode);
|
|
5324
|
-
segmentNode.appendChild(valueNode);
|
|
5325
|
-
return segmentNode;
|
|
5326
|
-
};
|
|
5327
|
-
const renderStrip = () => {
|
|
5328
|
-
const stripSegments = Array.isArray(watermarkifyMeta?.stripSegments) ? watermarkifyMeta.stripSegments : [];
|
|
5329
|
-
if (!watermarkifyMeta?.strip?.enabled || stripSegments.length === 0) {
|
|
5330
|
-
stripNode.remove();
|
|
5331
|
-
return;
|
|
5332
|
-
}
|
|
5333
|
-
const fragment = document.createDocumentFragment();
|
|
5334
|
-
for (const segment of stripSegments) {
|
|
5335
|
-
fragment.appendChild(buildSegmentNode(segment));
|
|
5336
|
-
}
|
|
5337
|
-
stripSegmentsNode.replaceChildren(fragment);
|
|
5338
|
-
};
|
|
5339
|
-
const waitForLogo = async () => {
|
|
5340
|
-
if (!stripLogoImg.getAttribute("src")) {
|
|
5341
|
-
return;
|
|
5342
|
-
}
|
|
5343
|
-
await new Promise((resolve) => {
|
|
5344
|
-
let settled = false;
|
|
5345
|
-
const done = () => {
|
|
5346
|
-
if (settled) return;
|
|
5347
|
-
settled = true;
|
|
5348
|
-
resolve();
|
|
5349
|
-
};
|
|
5350
|
-
const fail = () => {
|
|
5351
|
-
if (settled) return;
|
|
5352
|
-
stripLogo.remove();
|
|
5353
|
-
done();
|
|
5354
|
-
};
|
|
5355
|
-
const timeoutDone = () => {
|
|
5356
|
-
if (settled) return;
|
|
5357
|
-
done();
|
|
5358
|
-
};
|
|
5359
|
-
if (stripLogoImg.complete && stripLogoImg.naturalWidth > 0) {
|
|
5360
|
-
done();
|
|
5361
|
-
return;
|
|
5362
|
-
}
|
|
5363
|
-
if (stripLogoImg.complete && stripLogoImg.naturalWidth === 0) {
|
|
5364
|
-
fail();
|
|
5365
|
-
return;
|
|
5366
|
-
}
|
|
5367
|
-
stripLogoImg.addEventListener("load", done, { once: true });
|
|
5368
|
-
stripLogoImg.addEventListener("error", fail, { once: true });
|
|
5369
|
-
setTimeout(timeoutDone, 2500);
|
|
5370
|
-
});
|
|
5371
|
-
};
|
|
5372
|
-
const renderWatermark = () => {
|
|
5373
|
-
const stampText = safeText(watermarkifyMeta?.watermarkText);
|
|
5374
|
-
if (!watermarkifyMeta?.watermark?.enabled || !stampText) {
|
|
5375
|
-
watermarkNode.remove();
|
|
5376
|
-
return;
|
|
5377
|
-
}
|
|
5378
|
-
const cellWidth = Math.max(680, Number(watermarkifyMeta.watermark.cellWidth) || defaults.cellWidth);
|
|
5379
|
-
const cellHeight = Math.max(260, Number(watermarkifyMeta.watermark.cellHeight) || defaults.cellHeight);
|
|
5380
|
-
const rotateDeg = Number(watermarkifyMeta.watermark.rotateDeg) || defaults.rotateDeg;
|
|
5381
|
-
const opacity = Math.min(0.22, Math.max(0.05, Number(watermarkifyMeta.watermark.opacity) || defaults.opacity));
|
|
5382
|
-
const width = watermarkNode.clientWidth || window.innerWidth || document.documentElement.clientWidth || cellWidth;
|
|
5383
|
-
const height = watermarkNode.clientHeight || window.innerHeight || document.documentElement.clientHeight || cellHeight;
|
|
5384
|
-
const rowOffset = Math.round(cellWidth * 0.24);
|
|
5385
|
-
const startX = -Math.round(cellWidth * 0.16);
|
|
5386
|
-
const startY = -Math.round(cellHeight * 0.12);
|
|
5387
|
-
const cols = Math.ceil((width + cellWidth * 1.1) / cellWidth) + 1;
|
|
5388
|
-
const rows = Math.ceil((height + cellHeight * 0.9) / cellHeight) + 1;
|
|
5389
|
-
const fragment = document.createDocumentFragment();
|
|
5390
|
-
for (let row = 0; row < rows; row += 1) {
|
|
5391
|
-
for (let col = 0; col < cols; col += 1) {
|
|
5392
|
-
const stamp = createNode("div", "wmStamp");
|
|
5393
|
-
const stampTextNode = createNode("div", "wmStampText");
|
|
5394
|
-
const x = startX + col * cellWidth + (row % 2 ? rowOffset : 0);
|
|
5395
|
-
const y = startY + row * cellHeight + (row % 2 ? 14 : -8);
|
|
5396
|
-
stamp.style.transform = `translate(${x}px, ${y}px) rotate(${rotateDeg}deg)`;
|
|
5397
|
-
stampTextNode.style.setProperty("--wm-opacity", String(opacity));
|
|
5398
|
-
stampTextNode.textContent = stampText;
|
|
5399
|
-
stamp.appendChild(stampTextNode);
|
|
5400
|
-
fragment.appendChild(stamp);
|
|
5401
|
-
}
|
|
5155
|
+
const width = Math.max(1, Number(imageWidth) || 1);
|
|
5156
|
+
const height = Math.max(1, Number(imageHeight) || 1);
|
|
5157
|
+
const fontFamily = escapeXml(buildFontFamily());
|
|
5158
|
+
const parts = [];
|
|
5159
|
+
if (hasWatermark) {
|
|
5160
|
+
const stampText = escapeXml(normalizeText(meta.watermarkText));
|
|
5161
|
+
const cellWidth = Math.max(680, Number(meta.watermark?.cellWidth) || DEFAULT_WATERMARK_CELL_WIDTH);
|
|
5162
|
+
const cellHeight = Math.max(260, Number(meta.watermark?.cellHeight) || DEFAULT_WATERMARK_CELL_HEIGHT);
|
|
5163
|
+
const rotateDeg = Number(meta.watermark?.rotateDeg) || DEFAULT_WATERMARK_ROTATE_DEG;
|
|
5164
|
+
const opacity = Math.min(0.22, Math.max(0.05, Number(meta.watermark?.opacity) || DEFAULT_WATERMARK_OPACITY));
|
|
5165
|
+
const rowOffset = Math.round(cellWidth * 0.24);
|
|
5166
|
+
const startX = -Math.round(cellWidth * 0.16);
|
|
5167
|
+
const startY = -Math.round(cellHeight * 0.12);
|
|
5168
|
+
const cols = Math.ceil((width + cellWidth * 1.1) / cellWidth) + 1;
|
|
5169
|
+
const rows = Math.ceil((height + cellHeight * 0.9) / cellHeight) + 1;
|
|
5170
|
+
const stamps = [];
|
|
5171
|
+
for (let row = 0; row < rows; row += 1) {
|
|
5172
|
+
for (let col = 0; col < cols; col += 1) {
|
|
5173
|
+
const x = startX + col * cellWidth + (row % 2 ? rowOffset : 0);
|
|
5174
|
+
const y = startY + row * cellHeight + (row % 2 ? 14 : -8);
|
|
5175
|
+
stamps.push(`
|
|
5176
|
+
<g transform="translate(${x} ${y}) rotate(${rotateDeg})">
|
|
5177
|
+
<text
|
|
5178
|
+
x="0"
|
|
5179
|
+
y="0"
|
|
5180
|
+
fill="#111111"
|
|
5181
|
+
fill-opacity="${opacity}"
|
|
5182
|
+
stroke="#ffffff"
|
|
5183
|
+
stroke-opacity="0.12"
|
|
5184
|
+
stroke-width="0.22"
|
|
5185
|
+
font-family="${fontFamily}"
|
|
5186
|
+
font-size="19"
|
|
5187
|
+
font-weight="720"
|
|
5188
|
+
letter-spacing="0.6"
|
|
5189
|
+
>${stampText}</text>
|
|
5190
|
+
</g>
|
|
5191
|
+
`);
|
|
5402
5192
|
}
|
|
5403
|
-
watermarkNode.replaceChildren(fragment);
|
|
5404
|
-
};
|
|
5405
|
-
let resizeFrame = 0;
|
|
5406
|
-
const queueWatermarkRender = () => {
|
|
5407
|
-
if (!watermarkNode.isConnected) return;
|
|
5408
|
-
cancelAnimationFrame(resizeFrame);
|
|
5409
|
-
resizeFrame = requestAnimationFrame(() => {
|
|
5410
|
-
renderWatermark();
|
|
5411
|
-
});
|
|
5412
|
-
};
|
|
5413
|
-
const handleResize = () => {
|
|
5414
|
-
queueWatermarkRender();
|
|
5415
|
-
};
|
|
5416
|
-
host.__pkCleanup = () => {
|
|
5417
|
-
cancelAnimationFrame(resizeFrame);
|
|
5418
|
-
window.removeEventListener("resize", handleResize);
|
|
5419
|
-
};
|
|
5420
|
-
renderStrip();
|
|
5421
|
-
renderWatermark();
|
|
5422
|
-
queueWatermarkRender();
|
|
5423
|
-
window.addEventListener("resize", handleResize, { passive: true });
|
|
5424
|
-
return waitForLogo();
|
|
5425
|
-
}, {
|
|
5426
|
-
hostId: SCREENSHOT_WATERMARKIFY_HOST_ID,
|
|
5427
|
-
watermarkifyMeta: meta,
|
|
5428
|
-
defaults: {
|
|
5429
|
-
opacity: DEFAULT_WATERMARK_OPACITY,
|
|
5430
|
-
rotateDeg: DEFAULT_WATERMARK_ROTATE_DEG,
|
|
5431
|
-
cellWidth: DEFAULT_WATERMARK_CELL_WIDTH,
|
|
5432
|
-
cellHeight: DEFAULT_WATERMARK_CELL_HEIGHT,
|
|
5433
|
-
logoUrl: DEFAULT_STRIP_LOGO_URL
|
|
5434
5193
|
}
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5194
|
+
parts.push(`<g id="watermarks">${stamps.join("")}</g>`);
|
|
5195
|
+
}
|
|
5196
|
+
if (hasStrip) {
|
|
5197
|
+
const stripHeight = DEFAULT_STRIP_HEIGHT;
|
|
5198
|
+
const stripY = height - stripHeight;
|
|
5199
|
+
const logoSize = 28;
|
|
5200
|
+
const logoX = DEFAULT_STRIP_PADDING_LEFT;
|
|
5201
|
+
const logoY = stripY + Math.round((stripHeight - logoSize) / 2);
|
|
5202
|
+
const contentStartX = logoX + logoSize + DEFAULT_STRIP_GAP;
|
|
5203
|
+
const contentWidth = width - contentStartX - DEFAULT_STRIP_PADDING_RIGHT;
|
|
5204
|
+
const centerY = stripY + stripHeight / 2 + 1;
|
|
5205
|
+
const layouts = buildStripSegmentLayouts(meta.stripSegments, contentWidth);
|
|
5206
|
+
const svgSegments = [];
|
|
5207
|
+
let currentX = contentStartX;
|
|
5208
|
+
layouts.forEach((segment, index) => {
|
|
5209
|
+
const label = escapeXml(segment.label || "");
|
|
5210
|
+
const value = escapeXml(segment.renderValue || "-");
|
|
5211
|
+
const labelX = currentX;
|
|
5212
|
+
const valueX = currentX + segment.labelWidth;
|
|
5213
|
+
svgSegments.push(`
|
|
5214
|
+
<text
|
|
5215
|
+
x="${labelX}"
|
|
5216
|
+
y="${centerY}"
|
|
5217
|
+
fill="#111111"
|
|
5218
|
+
fill-opacity="0.42"
|
|
5219
|
+
font-family="${fontFamily}"
|
|
5220
|
+
font-size="12"
|
|
5221
|
+
font-weight="600"
|
|
5222
|
+
dominant-baseline="middle"
|
|
5223
|
+
>${label}</text>
|
|
5224
|
+
<text
|
|
5225
|
+
x="${valueX}"
|
|
5226
|
+
y="${centerY}"
|
|
5227
|
+
fill="#111111"
|
|
5228
|
+
font-family="${fontFamily}"
|
|
5229
|
+
font-size="${segment.fontSize}"
|
|
5230
|
+
font-weight="${segment.kind === "prompt" ? 760 : 710}"
|
|
5231
|
+
dominant-baseline="middle"
|
|
5232
|
+
>${value}</text>
|
|
5233
|
+
`);
|
|
5234
|
+
currentX += segment.segmentWidth;
|
|
5235
|
+
if (index < layouts.length - 1) {
|
|
5236
|
+
const lineX = currentX + 8;
|
|
5237
|
+
svgSegments.push(`
|
|
5238
|
+
<line
|
|
5239
|
+
x1="${lineX}"
|
|
5240
|
+
y1="${stripY + 26}"
|
|
5241
|
+
x2="${lineX}"
|
|
5242
|
+
y2="${stripY + stripHeight - 26}"
|
|
5243
|
+
stroke="#94a3b8"
|
|
5244
|
+
stroke-opacity="0.34"
|
|
5245
|
+
stroke-width="1"
|
|
5246
|
+
/>
|
|
5247
|
+
`);
|
|
5248
|
+
currentX += DEFAULT_STRIP_GAP + 16;
|
|
5441
5249
|
}
|
|
5442
|
-
host?.remove();
|
|
5443
|
-
}, SCREENSHOT_WATERMARKIFY_HOST_ID).catch(() => {
|
|
5444
5250
|
});
|
|
5445
|
-
|
|
5251
|
+
parts.push(`
|
|
5252
|
+
<g id="strip">
|
|
5253
|
+
<rect x="0" y="${stripY}" width="${width}" height="${stripHeight}" fill="#ffffff" fill-opacity="0.985" />
|
|
5254
|
+
<rect x="0" y="${stripY}" width="${width}" height="1" fill="#111111" fill-opacity="0.10" />
|
|
5255
|
+
<rect x="${DEFAULT_STRIP_PADDING_LEFT}" y="${stripY}" width="${Math.max(120, Math.round(width * 0.42))}" height="2" fill="url(#stripAccent)" />
|
|
5256
|
+
${meta.stripLogoSrc ? `<image href="${escapeXml(meta.stripLogoSrc)}" x="${logoX}" y="${logoY}" width="${logoSize}" height="${logoSize}" />` : ""}
|
|
5257
|
+
${svgSegments.join("")}
|
|
5258
|
+
</g>
|
|
5259
|
+
`);
|
|
5260
|
+
}
|
|
5261
|
+
return `
|
|
5262
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
|
5263
|
+
<defs>
|
|
5264
|
+
<linearGradient id="stripAccent" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
5265
|
+
<stop offset="0%" stop-color="#111111" stop-opacity="0.98" />
|
|
5266
|
+
<stop offset="24%" stop-color="#111111" stop-opacity="0.68" />
|
|
5267
|
+
<stop offset="58%" stop-color="#111111" stop-opacity="0.08" />
|
|
5268
|
+
<stop offset="100%" stop-color="#111111" stop-opacity="0" />
|
|
5269
|
+
</linearGradient>
|
|
5270
|
+
</defs>
|
|
5271
|
+
${parts.join("")}
|
|
5272
|
+
</svg>
|
|
5273
|
+
`;
|
|
5274
|
+
};
|
|
5275
|
+
var watermarkifyScreenshotBuffer = async (buffer, meta) => {
|
|
5276
|
+
const hasWatermark = meta?.watermark?.enabled !== false && normalizeText(meta?.watermarkText);
|
|
5277
|
+
const hasStrip = meta?.strip?.enabled !== false && Array.isArray(meta?.stripSegments) && meta.stripSegments.length > 0;
|
|
5278
|
+
if (!Buffer.isBuffer(buffer) || !meta || !hasWatermark && !hasStrip) {
|
|
5279
|
+
return buffer;
|
|
5280
|
+
}
|
|
5281
|
+
const image = (0, import_sharp.default)(buffer, { failOn: "none" });
|
|
5282
|
+
const metadata = await image.metadata().catch(() => null);
|
|
5283
|
+
const width = Math.max(1, Number(metadata?.width) || 0);
|
|
5284
|
+
const height = Math.max(1, Number(metadata?.height) || 0);
|
|
5285
|
+
if (!width || !height) {
|
|
5286
|
+
return buffer;
|
|
5287
|
+
}
|
|
5288
|
+
const overlaySvg = buildWatermarkifySvg(meta, width, height);
|
|
5289
|
+
if (!overlaySvg) {
|
|
5290
|
+
return buffer;
|
|
5291
|
+
}
|
|
5292
|
+
return await image.composite([{ input: Buffer.from(overlaySvg), top: 0, left: 0 }]).png().toBuffer();
|
|
5446
5293
|
};
|
|
5447
5294
|
|
|
5448
5295
|
// src/share.js
|
|
@@ -5852,8 +5699,6 @@ var Share = {
|
|
|
5852
5699
|
const restore = options.restore ?? false;
|
|
5853
5700
|
const maxHeight = options.maxHeight ?? 8e3;
|
|
5854
5701
|
const screenshotWatermarkify = normalizeScreenshotWatermarkify(options.watermarkify ?? true);
|
|
5855
|
-
let cleanupScreenshotWatermarkify = async () => {
|
|
5856
|
-
};
|
|
5857
5702
|
try {
|
|
5858
5703
|
const maxScrollHeight = await page.evaluate(() => {
|
|
5859
5704
|
let maxHeight2 = document.body.scrollHeight;
|
|
@@ -5881,19 +5726,22 @@ var Share = {
|
|
|
5881
5726
|
height: targetHeight
|
|
5882
5727
|
});
|
|
5883
5728
|
await (0, import_delay2.default)(1e3);
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
cleanupScreenshotWatermarkify = await installScreenshotWatermarkify(page, watermarkifyMeta);
|
|
5887
|
-
await (0, import_delay2.default)(120);
|
|
5888
|
-
}
|
|
5889
|
-
const buffer_ = await capturePageScreenshot(page, {
|
|
5729
|
+
const capturedAt = /* @__PURE__ */ new Date();
|
|
5730
|
+
const rawBuffer = await capturePageScreenshot(page, {
|
|
5890
5731
|
fullPage: true,
|
|
5891
5732
|
type: "png",
|
|
5892
5733
|
maxClipHeight: targetHeight
|
|
5893
5734
|
});
|
|
5735
|
+
if (!screenshotWatermarkify.enabled) {
|
|
5736
|
+
return rawBuffer.toString("base64");
|
|
5737
|
+
}
|
|
5738
|
+
const watermarkifyMeta = await resolveScreenshotWatermarkifyMeta(page, {
|
|
5739
|
+
...screenshotWatermarkify,
|
|
5740
|
+
capturedAt
|
|
5741
|
+
});
|
|
5742
|
+
const buffer_ = await watermarkifyScreenshotBuffer(rawBuffer, watermarkifyMeta);
|
|
5894
5743
|
return buffer_.toString("base64");
|
|
5895
5744
|
} finally {
|
|
5896
|
-
await cleanupScreenshotWatermarkify();
|
|
5897
5745
|
if (restore) {
|
|
5898
5746
|
await page.evaluate(() => {
|
|
5899
5747
|
document.querySelectorAll(".__pk_expanded__").forEach((el) => {
|