@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.
Files changed (51) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +5 -4
  2. package/.turbo/turbo-build$colon$tsc.log +11 -11
  3. package/.turbo/turbo-build.log +6 -5
  4. package/CHANGELOG.md +16 -0
  5. package/dist/cjs/index.cjs +13 -41
  6. package/dist/cjs/plugins/pages.cjs +113 -0
  7. package/dist/index.js +2 -42
  8. package/dist/plugins/pages.js +103 -0
  9. package/package.json +2 -2
  10. package/src/frictionless-explicit-web3.html +10 -23
  11. package/src/frictionless-explicit.html +10 -22
  12. package/src/frictionless-implicit.html +60 -86
  13. package/src/frictionless-manual-start.html +13 -33
  14. package/src/image-explicit-web3.html +8 -24
  15. package/src/image-explicit.html +8 -23
  16. package/src/image-implicit.html +192 -0
  17. package/src/index.html +11 -26
  18. package/src/index.ts +1 -62
  19. package/src/invisible-frictionless-explicit.html +8 -17
  20. package/src/invisible-frictionless-implicit.html +8 -25
  21. package/src/invisible-image-explicit.html +8 -23
  22. package/src/invisible-image-implicit.html +8 -24
  23. package/src/invisible-pow-explicit.html +8 -23
  24. package/src/invisible-pow-implicit.html +9 -21
  25. package/src/invisible-puzzle-explicit.html +8 -23
  26. package/src/invisible-puzzle-implicit.html +9 -21
  27. package/src/plugins/code-snippet-injector.ts +179 -0
  28. package/src/plugins/form-filler-injector.ts +36 -121
  29. package/src/plugins/layout-injector.ts +238 -0
  30. package/src/plugins/logo.ts +15 -0
  31. package/src/plugins/pages.ts +219 -0
  32. package/src/plugins/placement-injector.ts +25 -64
  33. package/src/plugins/slots.ts +32 -0
  34. package/src/plugins/status-log-injector.ts +35 -114
  35. package/src/pow-explicit-web3.html +8 -24
  36. package/src/pow-explicit.html +8 -23
  37. package/src/pow-implicit-sessionid.html +10 -24
  38. package/src/pow-implicit.html +9 -24
  39. package/src/puzzle-bind-explicit.html +9 -24
  40. package/src/puzzle-explicit.html +8 -23
  41. package/src/puzzle-implicit.html +9 -24
  42. package/src/styles/demo.css +803 -0
  43. package/src/tests/plugins.unit.test.ts +285 -118
  44. package/tsconfig.tsbuildinfo +1 -1
  45. package/vite.config.ts +5 -5
  46. package/src/plugins/explanation-injector.ts +0 -294
  47. package/src/plugins/navigation-injector.ts +0 -606
  48. package/src/styles/captcha.css +0 -78
  49. package/src/styles/field.css +0 -12
  50. package/src/tests/floatLabel.unit.test.ts +0 -195
  51. 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 explanationInjector from "./src/plugins/explanation-injector.js";
20
+ import codeSnippetInjector from "./src/plugins/code-snippet-injector.js";
21
21
  import formFillerInjector from "./src/plugins/form-filler-injector.js";
22
- import navigationInjector from "./src/plugins/navigation-injector.js";
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/index.html"),
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
- navigationInjector(),
230
+ layoutInjector(),
231
231
  formFillerInjector(),
232
- explanationInjector(),
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, "&lt;")
22
- .replace(/>/g, "&gt;")
23
- .replace(/"/g, "&quot;")
24
- .replace(/'/g, "&#39;");
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
- }