@prosopo/client-bundle-example 2.10.24 → 2.11.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/.turbo/turbo-build$colon$cjs.log +5 -4
- package/.turbo/turbo-build$colon$tsc.log +11 -11
- package/.turbo/turbo-build.log +6 -5
- package/CHANGELOG.md +16 -0
- package/dist/cjs/index.cjs +13 -41
- package/dist/cjs/plugins/pages.cjs +113 -0
- package/dist/index.js +2 -42
- package/dist/plugins/pages.js +103 -0
- package/package.json +2 -2
- package/src/frictionless-explicit-web3.html +10 -23
- package/src/frictionless-explicit.html +10 -22
- package/src/frictionless-implicit.html +60 -86
- package/src/frictionless-manual-start.html +13 -33
- package/src/image-explicit-web3.html +8 -24
- package/src/image-explicit.html +8 -23
- package/src/image-implicit.html +192 -0
- package/src/index.html +11 -26
- package/src/index.ts +1 -62
- package/src/invisible-frictionless-explicit.html +8 -17
- package/src/invisible-frictionless-implicit.html +8 -25
- package/src/invisible-image-explicit.html +8 -23
- package/src/invisible-image-implicit.html +8 -24
- package/src/invisible-pow-explicit.html +8 -23
- package/src/invisible-pow-implicit.html +9 -21
- package/src/invisible-puzzle-explicit.html +8 -23
- package/src/invisible-puzzle-implicit.html +9 -21
- package/src/plugins/code-snippet-injector.ts +179 -0
- package/src/plugins/form-filler-injector.ts +36 -121
- package/src/plugins/layout-injector.ts +238 -0
- package/src/plugins/logo.ts +15 -0
- package/src/plugins/pages.ts +219 -0
- package/src/plugins/placement-injector.ts +25 -64
- package/src/plugins/slots.ts +32 -0
- package/src/plugins/status-log-injector.ts +35 -114
- package/src/pow-explicit-web3.html +8 -24
- package/src/pow-explicit.html +8 -23
- package/src/pow-implicit-sessionid.html +10 -24
- package/src/pow-implicit.html +9 -24
- package/src/puzzle-bind-explicit.html +9 -24
- package/src/puzzle-explicit.html +8 -23
- package/src/puzzle-implicit.html +9 -24
- package/src/styles/demo.css +803 -0
- package/src/tests/plugins.unit.test.ts +285 -118
- package/tsconfig.tsbuildinfo +1 -1
- package/vite.config.ts +5 -5
- package/src/plugins/explanation-injector.ts +0 -294
- package/src/plugins/navigation-injector.ts +0 -606
- package/src/styles/captcha.css +0 -78
- package/src/styles/field.css +0 -12
- package/src/tests/floatLabel.unit.test.ts +0 -195
- package/src/tests/floatLabelReady.unit.test.ts +0 -36
package/vite.config.ts
CHANGED
|
@@ -17,9 +17,9 @@ import path from "node:path";
|
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
18
18
|
import { loadEnv } from "@prosopo/dotenv";
|
|
19
19
|
import { type UserConfig, defineConfig } from "vite";
|
|
20
|
-
import
|
|
20
|
+
import codeSnippetInjector from "./src/plugins/code-snippet-injector.js";
|
|
21
21
|
import formFillerInjector from "./src/plugins/form-filler-injector.js";
|
|
22
|
-
import
|
|
22
|
+
import layoutInjector from "./src/plugins/layout-injector.js";
|
|
23
23
|
import placementInjector from "./src/plugins/placement-injector.js";
|
|
24
24
|
import statusLogInjector from "./src/plugins/status-log-injector.js";
|
|
25
25
|
|
|
@@ -166,7 +166,7 @@ export default defineConfig(({ command, mode }) => {
|
|
|
166
166
|
"pow-explicit": path.resolve(__dirname, "src/pow-explicit.html"),
|
|
167
167
|
"image-explicit": path.resolve(__dirname, "src/image-explicit.html"),
|
|
168
168
|
"pow-implicit": path.resolve(__dirname, "src/pow-implicit.html"),
|
|
169
|
-
"image-implicit": path.resolve(__dirname, "src/
|
|
169
|
+
"image-implicit": path.resolve(__dirname, "src/image-implicit.html"),
|
|
170
170
|
"frictionless-implicit": path.resolve(
|
|
171
171
|
__dirname,
|
|
172
172
|
"src/frictionless-implicit.html",
|
|
@@ -227,9 +227,9 @@ export default defineConfig(({ command, mode }) => {
|
|
|
227
227
|
},
|
|
228
228
|
},
|
|
229
229
|
plugins: [
|
|
230
|
-
|
|
230
|
+
layoutInjector(),
|
|
231
231
|
formFillerInjector(),
|
|
232
|
-
|
|
232
|
+
codeSnippetInjector(),
|
|
233
233
|
statusLogInjector(),
|
|
234
234
|
placementInjector(),
|
|
235
235
|
{
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
14
|
-
// Vite plugin to inject explanations into HTML files
|
|
15
|
-
import type { IndexHtmlTransformContext, Plugin } from "vite";
|
|
16
|
-
|
|
17
|
-
// Utility function to escape HTML special characters
|
|
18
|
-
function escapeHtml(text: string): string {
|
|
19
|
-
return text
|
|
20
|
-
.replace(/&/g, "&")
|
|
21
|
-
.replace(/</g, "<")
|
|
22
|
-
.replace(/>/g, ">")
|
|
23
|
-
.replace(/"/g, """)
|
|
24
|
-
.replace(/'/g, "'");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export default function explanationInjector(): Plugin {
|
|
28
|
-
return {
|
|
29
|
-
name: "explanation-injector",
|
|
30
|
-
transformIndexHtml: {
|
|
31
|
-
order: "post", // Run after other HTML transforms
|
|
32
|
-
handler(html: string, ctx: IndexHtmlTransformContext): string {
|
|
33
|
-
// Skip if no HTML body is found
|
|
34
|
-
if (!html.includes("<body") || !html.includes("</body>")) {
|
|
35
|
-
return html;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Extract the current page name from the context
|
|
39
|
-
const url = ctx.filename || "";
|
|
40
|
-
const pageName = url.split("/").pop()?.split(".")[0] || "";
|
|
41
|
-
|
|
42
|
-
// Determine CAPTCHA type from filename
|
|
43
|
-
const isFrictionless = pageName.includes("frictionless");
|
|
44
|
-
const isImage = pageName.includes("image");
|
|
45
|
-
const isPow = pageName.includes("pow");
|
|
46
|
-
const isInvisible = pageName.includes("invisible");
|
|
47
|
-
const isExplicit = pageName.includes("explicit");
|
|
48
|
-
|
|
49
|
-
// Generate the appropriate explanation based on CAPTCHA type
|
|
50
|
-
let explanationHtml = "";
|
|
51
|
-
|
|
52
|
-
if (isFrictionless) {
|
|
53
|
-
explanationHtml = generateFrictionlessExplanation(
|
|
54
|
-
isExplicit,
|
|
55
|
-
isInvisible,
|
|
56
|
-
);
|
|
57
|
-
} else if (isImage) {
|
|
58
|
-
explanationHtml = generateImageExplanation(isExplicit, isInvisible);
|
|
59
|
-
} else if (isPow) {
|
|
60
|
-
explanationHtml = generatePowExplanation(isExplicit, isInvisible);
|
|
61
|
-
} else if (pageName.includes("puzzle")) {
|
|
62
|
-
explanationHtml = generatePuzzleExplanation(isExplicit, isInvisible);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// No explanation needed or couldn't determine type
|
|
66
|
-
if (!explanationHtml) {
|
|
67
|
-
return html;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Look for an existing explanation div to replace
|
|
71
|
-
if (html.includes('<div class="explanation">')) {
|
|
72
|
-
// Replace the existing explanation
|
|
73
|
-
const explRegex =
|
|
74
|
-
/<div class="explanation">[\s\S]*?<\/div>\s*<\/div>/;
|
|
75
|
-
return html.replace(explRegex, explanationHtml);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Otherwise insert before the closing body tag
|
|
79
|
-
return html.replace("</body>", `${explanationHtml}</body>`);
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Helper functions to generate explanations for different CAPTCHA types
|
|
86
|
-
function generateFrictionlessExplanation(
|
|
87
|
-
isExplicit: boolean,
|
|
88
|
-
isInvisible: boolean,
|
|
89
|
-
): string {
|
|
90
|
-
const renderType = isExplicit ? "Explicit" : "Implicit";
|
|
91
|
-
const modeDesc = isInvisible ? "invisible" : "normal";
|
|
92
|
-
|
|
93
|
-
// Create code example with proper HTML escaping
|
|
94
|
-
const codeExample = isExplicit
|
|
95
|
-
? escapeHtml(`// Import the render function
|
|
96
|
-
import { render } from "%VITE_BUNDLE_URL%"
|
|
97
|
-
|
|
98
|
-
// Render CAPTCHA
|
|
99
|
-
const widgetId = render(document.getElementById('procaptcha-container'), {
|
|
100
|
-
siteKey: import.meta.env.PROSOPO_SITE_KEY_FRICTIONLESS,
|
|
101
|
-
callback: handleCaptchaResponse,
|
|
102
|
-
"failed-callback": handleCaptchaFailed${isInvisible ? ',\n size: "invisible"' : ""}
|
|
103
|
-
});`)
|
|
104
|
-
: escapeHtml(`<div
|
|
105
|
-
class="procaptcha"
|
|
106
|
-
data-theme="light"
|
|
107
|
-
data-sitekey="%PROSOPO_SITE_KEY_FRICTIONLESS%"
|
|
108
|
-
data-failed-callback="onCaptchaFailed"
|
|
109
|
-
data-callback="onCaptchaVerified"${isInvisible ? '\n data-size="invisible"' : ""}
|
|
110
|
-
></div>`);
|
|
111
|
-
|
|
112
|
-
return `
|
|
113
|
-
<div class="explanation">
|
|
114
|
-
<h2>How ${isInvisible ? "Invisible " : ""}Frictionless CAPTCHA Works (${renderType} Rendering)</h2>
|
|
115
|
-
|
|
116
|
-
<h3>Implementation Details</h3>
|
|
117
|
-
<p>This example demonstrates how to use Procaptcha in frictionless mode with ${renderType.toLowerCase()} rendering:</p>
|
|
118
|
-
<ol>
|
|
119
|
-
<li>Import the Procaptcha ${isExplicit ? "render function" : "script"}</li>
|
|
120
|
-
<li>${escapeHtml(isExplicit ? "Create a container for the CAPTCHA" : "Add a div with the procaptcha class")}</li>
|
|
121
|
-
<li>${escapeHtml(isExplicit ? "Render the CAPTCHA explicitly" : "Set data-* attributes to configure the CAPTCHA")}</li>
|
|
122
|
-
<li>Handle the verification result in the callback function</li>
|
|
123
|
-
</ol>
|
|
124
|
-
|
|
125
|
-
<h3>Key Code Example</h3>
|
|
126
|
-
<pre>${codeExample}</pre>
|
|
127
|
-
|
|
128
|
-
<h3>Execution Flow</h3>
|
|
129
|
-
<ol>
|
|
130
|
-
<li>On page load, ${escapeHtml(isExplicit ? "the render function is called to initialize" : "Procaptcha scans for elements with the procaptcha class")}</li>
|
|
131
|
-
<li>The CAPTCHA verification happens ${isInvisible ? "invisibly in the background" : "when the user interacts with it"}</li>
|
|
132
|
-
<li>When verification is complete, the callback function is called with the token</li>
|
|
133
|
-
<li>On successful verification, the form can be submitted with the token</li>
|
|
134
|
-
</ol>
|
|
135
|
-
</div>
|
|
136
|
-
`;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function generateImageExplanation(
|
|
140
|
-
isExplicit: boolean,
|
|
141
|
-
isInvisible: boolean,
|
|
142
|
-
): string {
|
|
143
|
-
const renderType = isExplicit ? "Explicit" : "Implicit";
|
|
144
|
-
const modeDesc = isInvisible ? "invisible" : "visible";
|
|
145
|
-
|
|
146
|
-
// Create code example with proper HTML escaping
|
|
147
|
-
const codeExample = isExplicit
|
|
148
|
-
? escapeHtml(`// Import the render function
|
|
149
|
-
import { render } from "%VITE_BUNDLE_URL%"
|
|
150
|
-
|
|
151
|
-
// Render CAPTCHA
|
|
152
|
-
const widgetId = render(document.getElementById('procaptcha-container'), {
|
|
153
|
-
siteKey: import.meta.env.PROSOPO_SITE_KEY_IMAGE,
|
|
154
|
-
callback: handleCaptchaResponse,
|
|
155
|
-
"failed-callback": handleCaptchaFailed${isInvisible ? ',\n size: "invisible"' : ""}
|
|
156
|
-
});`)
|
|
157
|
-
: escapeHtml(`<div
|
|
158
|
-
class="procaptcha"
|
|
159
|
-
data-theme="light"
|
|
160
|
-
data-sitekey="%PROSOPO_SITE_KEY_IMAGE%"
|
|
161
|
-
data-failed-callback="onCaptchaFailed"
|
|
162
|
-
data-callback="onCaptchaVerified"${isInvisible ? '\n data-size="invisible"' : ""}
|
|
163
|
-
></div>`);
|
|
164
|
-
|
|
165
|
-
return `
|
|
166
|
-
<div class="explanation">
|
|
167
|
-
<h2>How ${isInvisible ? "Invisible " : ""}Image CAPTCHA Works (${renderType} Rendering)</h2>
|
|
168
|
-
|
|
169
|
-
<h3>Implementation Details</h3>
|
|
170
|
-
<p>This example demonstrates how to use Procaptcha in image mode with ${renderType.toLowerCase()} rendering:</p>
|
|
171
|
-
<ol>
|
|
172
|
-
<li>Import the Procaptcha ${isExplicit ? "render function" : "script"}</li>
|
|
173
|
-
<li>${escapeHtml(isExplicit ? "Create a container for the CAPTCHA" : "Add a div with the procaptcha class")}</li>
|
|
174
|
-
<li>${escapeHtml(isExplicit ? "Render the CAPTCHA explicitly" : "Set data-* attributes to configure the CAPTCHA")}</li>
|
|
175
|
-
<li>Handle the verification result in the callback function</li>
|
|
176
|
-
</ol>
|
|
177
|
-
|
|
178
|
-
<h3>Key Code Example</h3>
|
|
179
|
-
<pre>${codeExample}</pre>
|
|
180
|
-
|
|
181
|
-
<h3>Execution Flow</h3>
|
|
182
|
-
<ol>
|
|
183
|
-
<li>On page load, ${escapeHtml(isExplicit ? "the render function is called to initialize" : "Procaptcha scans for elements with the procaptcha class")}</li>
|
|
184
|
-
<li>The CAPTCHA challenge is rendered ${isInvisible ? "only when needed" : "in the specified container"}</li>
|
|
185
|
-
<li>When the user completes the challenge, the callback function is called</li>
|
|
186
|
-
<li>On successful verification, the form can be submitted with the token</li>
|
|
187
|
-
</ol>
|
|
188
|
-
</div>
|
|
189
|
-
`;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function generatePowExplanation(
|
|
193
|
-
isExplicit: boolean,
|
|
194
|
-
isInvisible: boolean,
|
|
195
|
-
): string {
|
|
196
|
-
const renderType = isExplicit ? "Explicit" : "Implicit";
|
|
197
|
-
const modeDesc = isInvisible ? "invisible" : "visible";
|
|
198
|
-
|
|
199
|
-
// Create code example with proper HTML escaping
|
|
200
|
-
const codeExample = isExplicit
|
|
201
|
-
? escapeHtml(`// Import the render function
|
|
202
|
-
import { render } from "%VITE_BUNDLE_URL%"
|
|
203
|
-
|
|
204
|
-
// Render CAPTCHA
|
|
205
|
-
const widgetId = render(document.getElementById('procaptcha-container'), {
|
|
206
|
-
siteKey: import.meta.env.PROSOPO_SITE_KEY_POW,
|
|
207
|
-
callback: handleCaptchaResponse,
|
|
208
|
-
"failed-callback": handleCaptchaFailed${isInvisible ? ',\n size: "invisible"' : ""}
|
|
209
|
-
});`)
|
|
210
|
-
: escapeHtml(`<div
|
|
211
|
-
class="procaptcha"
|
|
212
|
-
data-theme="light"
|
|
213
|
-
data-sitekey="%PROSOPO_SITE_KEY_POW%"
|
|
214
|
-
data-failed-callback="onCaptchaFailed"
|
|
215
|
-
data-callback="onCaptchaVerified"${isInvisible ? '\n data-size="invisible"' : ""}
|
|
216
|
-
></div>`);
|
|
217
|
-
|
|
218
|
-
return `
|
|
219
|
-
<div class="explanation">
|
|
220
|
-
<h2>How ${isInvisible ? "Invisible " : ""}Proof of Work CAPTCHA Works (${renderType} Rendering)</h2>
|
|
221
|
-
|
|
222
|
-
<h3>Implementation Details</h3>
|
|
223
|
-
<p>This example demonstrates how to use Procaptcha in Proof of Work mode with ${renderType.toLowerCase()} rendering:</p>
|
|
224
|
-
<ol>
|
|
225
|
-
<li>Import the Procaptcha ${isExplicit ? "render function" : "script"}</li>
|
|
226
|
-
<li>${escapeHtml(isExplicit ? "Create a container for the CAPTCHA" : "Add a div with the procaptcha class")}</li>
|
|
227
|
-
<li>${escapeHtml(isExplicit ? "Render the CAPTCHA explicitly" : "Set data-* attributes to configure the CAPTCHA")}</li>
|
|
228
|
-
<li>Handle the verification result in the callback function</li>
|
|
229
|
-
</ol>
|
|
230
|
-
|
|
231
|
-
<h3>Key Code Example</h3>
|
|
232
|
-
<pre>${codeExample}</pre>
|
|
233
|
-
|
|
234
|
-
<h3>Execution Flow</h3>
|
|
235
|
-
<ol>
|
|
236
|
-
<li>On page load, ${escapeHtml(isExplicit ? "the render function is called to initialize" : "Procaptcha scans for elements with the procaptcha class")}</li>
|
|
237
|
-
<li>The Proof of Work computation happens in the browser</li>
|
|
238
|
-
<li>When the computation is complete, the callback function is called</li>
|
|
239
|
-
<li>On successful verification, the form can be submitted with the token</li>
|
|
240
|
-
</ol>
|
|
241
|
-
</div>
|
|
242
|
-
`;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function generatePuzzleExplanation(
|
|
246
|
-
isExplicit: boolean,
|
|
247
|
-
isInvisible: boolean,
|
|
248
|
-
): string {
|
|
249
|
-
const renderType = isExplicit ? "Explicit" : "Implicit";
|
|
250
|
-
|
|
251
|
-
const codeExample = isExplicit
|
|
252
|
-
? escapeHtml(`// Import the render function
|
|
253
|
-
import { render } from "%VITE_BUNDLE_URL%"
|
|
254
|
-
|
|
255
|
-
// Render CAPTCHA
|
|
256
|
-
const widgetId = render(document.getElementById('procaptcha-container'), {
|
|
257
|
-
siteKey: import.meta.env.PROSOPO_SITE_KEY_PUZZLE,
|
|
258
|
-
callback: handleCaptchaResponse,
|
|
259
|
-
"failed-callback": handleCaptchaFailed${isInvisible ? ',\n size: "invisible"' : ""}
|
|
260
|
-
});`)
|
|
261
|
-
: escapeHtml(`<div
|
|
262
|
-
class="procaptcha"
|
|
263
|
-
data-theme="light"
|
|
264
|
-
data-sitekey="%PROSOPO_SITE_KEY_PUZZLE%"
|
|
265
|
-
data-failed-callback="onCaptchaFailed"
|
|
266
|
-
data-callback="onCaptchaVerified"${isInvisible ? '\n data-size="invisible"' : ""}
|
|
267
|
-
></div>`);
|
|
268
|
-
|
|
269
|
-
return `
|
|
270
|
-
<div class="explanation">
|
|
271
|
-
<h2>How ${isInvisible ? "Invisible " : ""}Puzzle CAPTCHA Works (${renderType} Rendering)</h2>
|
|
272
|
-
|
|
273
|
-
<h3>Implementation Details</h3>
|
|
274
|
-
<p>This example demonstrates how to use Procaptcha in puzzle mode with ${renderType.toLowerCase()} rendering:</p>
|
|
275
|
-
<ol>
|
|
276
|
-
<li>Import the Procaptcha ${isExplicit ? "render function" : "script"}</li>
|
|
277
|
-
<li>${escapeHtml(isExplicit ? "Create a container for the CAPTCHA" : "Add a div with the procaptcha class")}</li>
|
|
278
|
-
<li>${escapeHtml(isExplicit ? "Render the CAPTCHA explicitly" : "Set data-* attributes to configure the CAPTCHA")}</li>
|
|
279
|
-
<li>Handle the verification result in the callback function</li>
|
|
280
|
-
</ol>
|
|
281
|
-
|
|
282
|
-
<h3>Key Code Example</h3>
|
|
283
|
-
<pre>${codeExample}</pre>
|
|
284
|
-
|
|
285
|
-
<h3>Execution Flow</h3>
|
|
286
|
-
<ol>
|
|
287
|
-
<li>On page load, ${escapeHtml(isExplicit ? "the render function is called to initialize" : "Procaptcha scans for elements with the procaptcha class")}</li>
|
|
288
|
-
<li>A drag-to-target puzzle challenge is presented to the user</li>
|
|
289
|
-
<li>When the user completes the puzzle, the callback function is called</li>
|
|
290
|
-
<li>On successful verification, the form can be submitted with the token</li>
|
|
291
|
-
</ol>
|
|
292
|
-
</div>
|
|
293
|
-
`;
|
|
294
|
-
}
|