@prosopo/client-bundle-example 2.9.5 → 2.10.5

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 (37) hide show
  1. package/CHANGELOG.md +134 -0
  2. package/dist/cjs/index.cjs +49 -0
  3. package/dist/index.js +49 -1
  4. package/package.json +5 -9
  5. package/vite.config.ts +1 -0
  6. package/dist/assets/captcha-BaCo3bEP.js +0 -1
  7. package/dist/assets/captcha-DAWM1slf.css +0 -1
  8. package/dist/assets/dummy.txt +0 -0
  9. package/dist/assets/frictionless-explicit-CtnTw8dK.js +0 -1
  10. package/dist/assets/frictionless-implicit-BH7anfOq.js +0 -1
  11. package/dist/assets/image-explicit-Dm_JoW0N.js +0 -4
  12. package/dist/assets/image-implicit-M0Y7U93R.js +0 -1
  13. package/dist/assets/index-Ck5HfpfQ.js +0 -1
  14. package/dist/assets/invisible-frictionless-explicit-CSPYfcNr.js +0 -4
  15. package/dist/assets/invisible-frictionless-implicit-D0saDt4U.js +0 -1
  16. package/dist/assets/invisible-image-explicit-erOMAo-F.js +0 -4
  17. package/dist/assets/invisible-image-implicit-c0sMfk2s.js +0 -1
  18. package/dist/assets/invisible-pow-explicit-BgMt7lhN.js +0 -4
  19. package/dist/assets/invisible-pow-implicit-CnxS8gw2.js +0 -4
  20. package/dist/assets/pow-explicit-BgDWNJK9.js +0 -4
  21. package/dist/assets/pow-implicit-Ck5HfpfQ.js +0 -1
  22. package/dist/frictionless-explicit.html +0 -875
  23. package/dist/frictionless-implicit.html +0 -874
  24. package/dist/image-explicit.html +0 -877
  25. package/dist/index.html +0 -850
  26. package/dist/invisible-frictionless-explicit.html +0 -877
  27. package/dist/invisible-frictionless-implicit.html +0 -884
  28. package/dist/invisible-image-explicit.html +0 -878
  29. package/dist/invisible-image-implicit.html +0 -884
  30. package/dist/invisible-pow-explicit.html +0 -878
  31. package/dist/invisible-pow-implicit.html +0 -878
  32. package/dist/plugins/explanation-injector.ts +0 -250
  33. package/dist/plugins/form-filler-injector.ts +0 -233
  34. package/dist/plugins/navigation-injector.ts +0 -602
  35. package/dist/plugins/status-log-injector.ts +0 -199
  36. package/dist/pow-explicit.html +0 -877
  37. package/dist/pow-implicit.html +0 -881
@@ -1,250 +0,0 @@
1
- // Copyright 2021-2025 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
- enforce: "post", // Run after other HTML transforms
32
- transform(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
- }
62
-
63
- // No explanation needed or couldn't determine type
64
- if (!explanationHtml) {
65
- return html;
66
- }
67
-
68
- // Look for an existing explanation div to replace
69
- if (html.includes('<div class="explanation">')) {
70
- // Replace the existing explanation
71
- const explRegex =
72
- /<div class="explanation">[\s\S]*?<\/div>\s*<\/div>/;
73
- return html.replace(explRegex, explanationHtml);
74
- }
75
-
76
- // Otherwise insert before the closing body tag
77
- return html.replace("</body>", `${explanationHtml}</body>`);
78
- },
79
- },
80
- };
81
- }
82
-
83
- // Helper functions to generate explanations for different CAPTCHA types
84
- function generateFrictionlessExplanation(
85
- isExplicit: boolean,
86
- isInvisible: boolean,
87
- ): string {
88
- const renderType = isExplicit ? "Explicit" : "Implicit";
89
- const modeDesc = isInvisible ? "invisible" : "normal";
90
-
91
- // Create code example with proper HTML escaping
92
- const codeExample = isExplicit
93
- ? escapeHtml(`// Import the render function
94
- import { render } from "%VITE_BUNDLE_URL%"
95
- import { CaptchaType } from "@prosopo/types";
96
-
97
- // Render CAPTCHA
98
- const widgetId = render(document.getElementById('procaptcha-container'), {
99
- siteKey: import.meta.env.PROSOPO_SITE_KEY_FRICTIONLESS,
100
- captchaType: CaptchaType.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"
110
- data-captcha-type="frictionless"${isInvisible ? '\n data-size="invisible"' : ""}
111
- ></div>`);
112
-
113
- return `
114
- <div class="explanation">
115
- <h2>How ${isInvisible ? "Invisible " : ""}Frictionless CAPTCHA Works (${renderType} Rendering)</h2>
116
-
117
- <h3>Implementation Details</h3>
118
- <p>This example demonstrates how to use Procaptcha in frictionless mode with ${renderType.toLowerCase()} rendering:</p>
119
- <ol>
120
- <li>Import the Procaptcha ${isExplicit ? "render function" : "script"}</li>
121
- <li>${escapeHtml(isExplicit ? "Create a container for the CAPTCHA" : "Add a div with the procaptcha class")}</li>
122
- <li>${escapeHtml(isExplicit ? "Render the CAPTCHA explicitly" : "Set data-* attributes to configure the CAPTCHA")}</li>
123
- <li>Handle the verification result in the callback function</li>
124
- </ol>
125
-
126
- <h3>Key Code Example</h3>
127
- <pre>${codeExample}</pre>
128
-
129
- <h3>Execution Flow</h3>
130
- <ol>
131
- <li>On page load, ${escapeHtml(isExplicit ? "the render function is called to initialize" : "Procaptcha scans for elements with the procaptcha class")}</li>
132
- <li>The CAPTCHA verification happens ${isInvisible ? "invisibly in the background" : "when the user interacts with it"}</li>
133
- <li>When verification is complete, the callback function is called with the token</li>
134
- <li>On successful verification, the form can be submitted with the token</li>
135
- </ol>
136
- </div>
137
- `;
138
- }
139
-
140
- function generateImageExplanation(
141
- isExplicit: boolean,
142
- isInvisible: boolean,
143
- ): string {
144
- const renderType = isExplicit ? "Explicit" : "Implicit";
145
- const modeDesc = isInvisible ? "invisible" : "visible";
146
-
147
- // Create code example with proper HTML escaping
148
- const codeExample = isExplicit
149
- ? escapeHtml(`// Import the render function
150
- import { render } from "%VITE_BUNDLE_URL%"
151
- import { CaptchaType } from "@prosopo/types";
152
-
153
- // Render CAPTCHA
154
- const widgetId = render(document.getElementById('procaptcha-container'), {
155
- siteKey: import.meta.env.PROSOPO_SITE_KEY_IMAGE,
156
- captchaType: CaptchaType.image,
157
- callback: handleCaptchaResponse,
158
- "failed-callback": handleCaptchaFailed${isInvisible ? ',\n size: "invisible"' : ""}
159
- });`)
160
- : escapeHtml(`<div
161
- class="procaptcha"
162
- data-theme="light"
163
- data-sitekey="%PROSOPO_SITE_KEY_IMAGE%"
164
- data-failed-callback="onCaptchaFailed"
165
- data-callback="onCaptchaVerified"
166
- data-captcha-type="image"${isInvisible ? '\n data-size="invisible"' : ""}
167
- ></div>`);
168
-
169
- return `
170
- <div class="explanation">
171
- <h2>How ${isInvisible ? "Invisible " : ""}Image CAPTCHA Works (${renderType} Rendering)</h2>
172
-
173
- <h3>Implementation Details</h3>
174
- <p>This example demonstrates how to use Procaptcha in image mode with ${renderType.toLowerCase()} rendering:</p>
175
- <ol>
176
- <li>Import the Procaptcha ${isExplicit ? "render function" : "script"}</li>
177
- <li>${escapeHtml(isExplicit ? "Create a container for the CAPTCHA" : "Add a div with the procaptcha class")}</li>
178
- <li>${escapeHtml(isExplicit ? "Render the CAPTCHA explicitly" : "Set data-* attributes to configure the CAPTCHA")}</li>
179
- <li>Handle the verification result in the callback function</li>
180
- </ol>
181
-
182
- <h3>Key Code Example</h3>
183
- <pre>${codeExample}</pre>
184
-
185
- <h3>Execution Flow</h3>
186
- <ol>
187
- <li>On page load, ${escapeHtml(isExplicit ? "the render function is called to initialize" : "Procaptcha scans for elements with the procaptcha class")}</li>
188
- <li>The CAPTCHA challenge is rendered ${isInvisible ? "only when needed" : "in the specified container"}</li>
189
- <li>When the user completes the challenge, the callback function is called</li>
190
- <li>On successful verification, the form can be submitted with the token</li>
191
- </ol>
192
- </div>
193
- `;
194
- }
195
-
196
- function generatePowExplanation(
197
- isExplicit: boolean,
198
- isInvisible: boolean,
199
- ): string {
200
- const renderType = isExplicit ? "Explicit" : "Implicit";
201
- const modeDesc = isInvisible ? "invisible" : "visible";
202
-
203
- // Create code example with proper HTML escaping
204
- const codeExample = isExplicit
205
- ? escapeHtml(`// Import the render function
206
- import { render } from "%VITE_BUNDLE_URL%"
207
- import { CaptchaType } from "@prosopo/types";
208
-
209
- // Render CAPTCHA
210
- const widgetId = render(document.getElementById('procaptcha-container'), {
211
- siteKey: import.meta.env.PROSOPO_SITE_KEY_POW,
212
- captchaType: CaptchaType.pow,
213
- callback: handleCaptchaResponse,
214
- "failed-callback": handleCaptchaFailed${isInvisible ? ',\n size: "invisible"' : ""}
215
- });`)
216
- : escapeHtml(`<div
217
- class="procaptcha"
218
- data-theme="light"
219
- data-sitekey="%PROSOPO_SITE_KEY_POW%"
220
- data-failed-callback="onCaptchaFailed"
221
- data-callback="onCaptchaVerified"
222
- data-captcha-type="pow"${isInvisible ? '\n data-size="invisible"' : ""}
223
- ></div>`);
224
-
225
- return `
226
- <div class="explanation">
227
- <h2>How ${isInvisible ? "Invisible " : ""}Proof of Work CAPTCHA Works (${renderType} Rendering)</h2>
228
-
229
- <h3>Implementation Details</h3>
230
- <p>This example demonstrates how to use Procaptcha in Proof of Work mode with ${renderType.toLowerCase()} rendering:</p>
231
- <ol>
232
- <li>Import the Procaptcha ${isExplicit ? "render function" : "script"}</li>
233
- <li>${escapeHtml(isExplicit ? "Create a container for the CAPTCHA" : "Add a div with the procaptcha class")}</li>
234
- <li>${escapeHtml(isExplicit ? "Render the CAPTCHA explicitly" : "Set data-* attributes to configure the CAPTCHA")}</li>
235
- <li>Handle the verification result in the callback function</li>
236
- </ol>
237
-
238
- <h3>Key Code Example</h3>
239
- <pre>${codeExample}</pre>
240
-
241
- <h3>Execution Flow</h3>
242
- <ol>
243
- <li>On page load, ${escapeHtml(isExplicit ? "the render function is called to initialize" : "Procaptcha scans for elements with the procaptcha class")}</li>
244
- <li>The Proof of Work computation happens in the browser</li>
245
- <li>When the computation is complete, the callback function is called</li>
246
- <li>On successful verification, the form can be submitted with the token</li>
247
- </ol>
248
- </div>
249
- `;
250
- }
@@ -1,233 +0,0 @@
1
- // Copyright 2021-2025 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 a form filler button into HTML files
15
- import type { IndexHtmlTransformContext, Plugin } from "vite";
16
-
17
- export default function formFillerInjector(): Plugin {
18
- // Style for the form filler button
19
- const buttonStyle = `
20
- <style>
21
- .form-filler-button {
22
- position: fixed;
23
- bottom: 20px;
24
- right: 20px;
25
- background-color: #2196F3;
26
- color: white;
27
- border: none;
28
- border-radius: 30px;
29
- padding: 12px 20px;
30
- font-size: 14px;
31
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
32
- cursor: pointer;
33
- box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
34
- z-index: 9999;
35
- display: flex;
36
- align-items: center;
37
- gap: 8px;
38
- transition: all 0.2s ease;
39
- outline: none;
40
- }
41
-
42
- .form-filler-button:hover {
43
- background-color: #1976D2;
44
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.25);
45
- transform: translateY(-2px);
46
- }
47
-
48
- .form-filler-button:active {
49
- transform: translateY(1px);
50
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
51
- }
52
-
53
- .form-filler-button svg {
54
- width: 18px;
55
- height: 18px;
56
- fill: white;
57
- }
58
-
59
- .form-filler-button span {
60
- font-weight: 500;
61
- }
62
-
63
- @media (max-width: 768px) {
64
- .form-filler-button {
65
- bottom: 15px;
66
- right: 15px;
67
- padding: 10px 15px;
68
- font-size: 12px;
69
- }
70
-
71
- .form-filler-button svg {
72
- width: 14px;
73
- height: 14px;
74
- }
75
- }
76
- </style>
77
- `;
78
-
79
- // HTML for the form filler button
80
- const buttonHtml = `
81
- <button id="form-filler-button" class="form-filler-button" title="Fill all form fields with default values">
82
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
83
- <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
84
- </svg>
85
- <span>Fill Form</span>
86
- </button>
87
- `;
88
-
89
- // JavaScript for form filling functionality
90
- const fillerScript = `
91
- <script>
92
- document.addEventListener('DOMContentLoaded', function() {
93
- // Create a function to fill the form with sensible default values
94
- function fillFormWithDefaults() {
95
- // Get all input elements
96
- const inputs = document.querySelectorAll('input, select, textarea');
97
-
98
- // Record which elements were filled for status feedback
99
- const filledElements = [];
100
-
101
- // Process each input
102
- inputs.forEach(input => {
103
- let filled = true;
104
-
105
- // Skip hidden inputs and those with existing values
106
- if (input.type === 'hidden' || (input.value && input.value.trim() !== '')) {
107
- filled = false;
108
- }
109
- // Handle different input types
110
- else if (input.type === 'text') {
111
- if (input.id.toLowerCase().includes('name') || input.name.toLowerCase().includes('name')) {
112
- input.value = 'John Doe';
113
- } else {
114
- input.value = 'Default Text';
115
- }
116
- }
117
- else if (input.type === 'email') {
118
- input.value = 'test@example.com';
119
- }
120
- else if (input.type === 'password') {
121
- input.value = 'Password123!';
122
- }
123
- else if (input.type === 'tel') {
124
- input.value = '+1234567890';
125
- }
126
- else if (input.type === 'number') {
127
- input.value = '42';
128
- }
129
- else if (input.type === 'url') {
130
- input.value = 'https://example.com';
131
- }
132
- else if (input.type === 'date') {
133
- const today = new Date();
134
- const yyyy = today.getFullYear();
135
- const mm = String(today.getMonth() + 1).padStart(2, '0');
136
- const dd = String(today.getDate()).padStart(2, '0');
137
- input.value = \`\${yyyy}-\${mm}-\${dd}\`;
138
- }
139
- else if (input.type === 'time') {
140
- input.value = '12:00';
141
- }
142
- else if (input.type === 'checkbox' || input.type === 'radio') {
143
- input.checked = true;
144
- }
145
- else if (input.tagName === 'SELECT') {
146
- if (input.options.length > 0) {
147
- input.selectedIndex = 1 >= input.options.length ? 0 : 1; // Select second option if available, first otherwise
148
- }
149
- }
150
- else if (input.tagName === 'TEXTAREA') {
151
- input.value = 'This is a sample text for the textarea field.';
152
- }
153
- else {
154
- // For any other input types
155
- input.value = 'Default Value';
156
- }
157
-
158
- // Add to filled elements if we actually filled it
159
- if (filled) {
160
- filledElements.push(input);
161
-
162
- // Dispatch input event to trigger any listeners
163
- const event = new Event('input', { bubbles: true });
164
- input.dispatchEvent(event);
165
-
166
- // For select elements, also dispatch change event
167
- if (input.tagName === 'SELECT') {
168
- const changeEvent = new Event('change', { bubbles: true });
169
- input.dispatchEvent(changeEvent);
170
- }
171
- }
172
- });
173
-
174
- // Show a notification about what was filled
175
- if (filledElements.length > 0) {
176
- // If an updateCaptchaStatus function exists (from our other demos), use it
177
- if (typeof window.updateCaptchaStatus === 'function') {
178
- window.updateCaptchaStatus(\`Filled \${filledElements.length} form fields with default values\`, 'info');
179
- } else {
180
- console.log(\`Filled \${filledElements.length} form fields with default values\`);
181
- }
182
-
183
- // Highlight the filled fields briefly
184
- filledElements.forEach(el => {
185
- const originalBackground = el.style.backgroundColor;
186
- const originalTransition = el.style.transition;
187
-
188
- el.style.transition = 'background-color 1.5s ease';
189
- el.style.backgroundColor = '#e3f2fd';
190
-
191
- setTimeout(() => {
192
- el.style.backgroundColor = originalBackground;
193
- setTimeout(() => {
194
- el.style.transition = originalTransition;
195
- }, 1500);
196
- }, 500);
197
- });
198
- }
199
- }
200
-
201
- // Add the click event listener to the form filler button
202
- const formFillerButton = document.getElementById('form-filler-button');
203
- if (formFillerButton) {
204
- formFillerButton.addEventListener('click', fillFormWithDefaults);
205
- }
206
- });
207
- </script>
208
- `;
209
-
210
- return {
211
- name: "form-filler-injector",
212
- transformIndexHtml: {
213
- enforce: "post", // Run after other HTML transforms
214
- transform(html: string, ctx: IndexHtmlTransformContext): string {
215
- // Skip if no HTML body is found
216
- if (!html.includes("<body") || !html.includes("</body>")) {
217
- return html;
218
- }
219
-
220
- // Inject style into the head
221
- let updatedHtml = html.replace("</head>", `${buttonStyle}</head>`);
222
-
223
- // Inject button and script before closing body tag
224
- updatedHtml = updatedHtml.replace(
225
- "</body>",
226
- `${buttonHtml}${fillerScript}</body>`,
227
- );
228
-
229
- return updatedHtml;
230
- },
231
- },
232
- };
233
- }