@prosopo/client-bundle-example 2.5.0 → 2.5.3

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/dist/pow.html ADDED
@@ -0,0 +1,324 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Procaptcha demo: Live Test</title>
5
+ <script
6
+ id="procaptchaScript"
7
+ type="module"
8
+ src="https://staging-js.prosopo.io/js/procaptcha.bundle.js?onload=captchaLoaded&render=explicit"
9
+ async
10
+ defer
11
+ ></script>
12
+
13
+ <style>
14
+ .nav-topbar {
15
+ background-color: #2196F3;
16
+ padding: 0;
17
+ margin-bottom: 20px;
18
+ transition: all 0.3s ease;
19
+ overflow: hidden;
20
+ max-height: 500px; /* Initial state - visible */
21
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
22
+ }
23
+ .nav-topbar.collapsed {
24
+ max-height: 50px; /* Collapsed state - only show toggle button and title */
25
+ }
26
+ .nav-container {
27
+ max-width: 1200px;
28
+ margin: 0 auto;
29
+ padding: 0 15px;
30
+ position: relative;
31
+ }
32
+ .nav-header {
33
+ display: flex;
34
+ justify-content: space-between;
35
+ align-items: center;
36
+ padding: 10px 0;
37
+ position: relative;
38
+ z-index: 20;
39
+ }
40
+ .nav-title {
41
+ color: white;
42
+ font-size: 18px;
43
+ font-weight: bold;
44
+ margin: 0;
45
+ display: flex;
46
+ align-items: center;
47
+ }
48
+ .nav-title-text {
49
+ margin-right: 10px;
50
+ }
51
+ .nav-title-hint {
52
+ font-size: 14px;
53
+ font-weight: normal;
54
+ opacity: 0;
55
+ transition: opacity 0.3s ease;
56
+ }
57
+ .collapsed .nav-title-hint {
58
+ opacity: 0.8;
59
+ }
60
+ .nav-toggle {
61
+ background-color: rgba(0,0,0,0.1);
62
+ color: white;
63
+ border: none;
64
+ padding: 5px 10px;
65
+ cursor: pointer;
66
+ border-radius: 4px;
67
+ z-index: 10;
68
+ display: flex;
69
+ align-items: center;
70
+ justify-content: center;
71
+ }
72
+ .nav-toggle:hover {
73
+ background-color: rgba(0,0,0,0.2);
74
+ }
75
+ .nav-toggle-icon {
76
+ width: 24px;
77
+ height: 24px;
78
+ display: inline-block;
79
+ position: relative;
80
+ }
81
+ .nav-toggle-icon svg {
82
+ position: absolute;
83
+ top: 0;
84
+ left: 0;
85
+ transition: opacity 0.3s ease;
86
+ }
87
+ .nav-toggle-icon .icon-collapse {
88
+ opacity: 1;
89
+ }
90
+ .nav-toggle-icon .icon-expand {
91
+ opacity: 0;
92
+ }
93
+ .collapsed .nav-toggle-icon .icon-collapse {
94
+ opacity: 0;
95
+ }
96
+ .collapsed .nav-toggle-icon .icon-expand {
97
+ opacity: 1;
98
+ }
99
+ .nav-content {
100
+ padding: 0 0 15px 0;
101
+ transition: opacity 0.3s ease;
102
+ }
103
+ .collapsed .nav-content {
104
+ opacity: 0;
105
+ }
106
+ .nav-row {
107
+ display: flex;
108
+ flex-wrap: wrap;
109
+ margin-bottom: 15px;
110
+ }
111
+ .nav-group {
112
+ flex: 1;
113
+ min-width: 250px;
114
+ margin-bottom: 10px;
115
+ margin-right: 20px;
116
+ }
117
+ .nav-group-title {
118
+ color: rgba(255,255,255,0.8);
119
+ font-size: 0.9em;
120
+ margin: 0 0 5px 0;
121
+ text-transform: uppercase;
122
+ font-weight: 500;
123
+ }
124
+ .nav-group-links {
125
+ list-style: none;
126
+ margin: 0;
127
+ padding: 0;
128
+ }
129
+ .nav-group-links li {
130
+ margin: 5px 0;
131
+ }
132
+ .nav-group-links a {
133
+ color: white;
134
+ text-decoration: none;
135
+ font-weight: bold;
136
+ padding: 5px 0;
137
+ display: inline-block;
138
+ }
139
+ .nav-group-links a:hover {
140
+ text-decoration: underline;
141
+ }
142
+ .nav-group-links .active {
143
+ border-bottom: 2px solid white;
144
+ }
145
+ .nav-group-links .disabled {
146
+ color: rgba(255,255,255,0.5);
147
+ cursor: not-allowed;
148
+ }
149
+
150
+ @media (max-width: 768px) {
151
+ .nav-row {
152
+ flex-direction: column;
153
+ }
154
+ .nav-title-hint {
155
+ display: none;
156
+ }
157
+ }
158
+ </style>
159
+ <script type="module" crossorigin src="/assets/pow-DpBboekQ.js"></script>
160
+ <link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
161
+ <link rel="modulepreload" crossorigin href="/assets/captchaType-CYBmmAZe.js">
162
+ </head>
163
+ <body>
164
+
165
+ <div id="nav-topbar" class="nav-topbar">
166
+ <div class="nav-container">
167
+ <div id="nav-header" class="nav-header">
168
+ <h1 class="nav-title">
169
+ <span class="nav-title-text">Procaptcha Demo Playground</span>
170
+ <span class="nav-title-hint">(Click anywhere to see more examples)</span>
171
+ </h1>
172
+ <button id="nav-toggle" class="nav-toggle" aria-label="Toggle navigation">
173
+ <span class="nav-toggle-icon">
174
+ <svg class="icon-collapse" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
175
+ <polyline points="18 15 12 9 6 15"></polyline>
176
+ </svg>
177
+ <svg class="icon-expand" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
178
+ <polyline points="6 9 12 15 18 9"></polyline>
179
+ </svg>
180
+ </span>
181
+ </button>
182
+ </div>
183
+ <div class="nav-content">
184
+ <div class="nav-row">
185
+
186
+ <div class="nav-section">
187
+ <h3 style="color: white; margin: 0 0 10px 0;">Standard Captchas</h3>
188
+ <div class="nav-row">
189
+
190
+ <div class="nav-group">
191
+ <div class="nav-group-title">Image</div>
192
+ <ul class="nav-group-links">
193
+ <li><a href="index.html">Implicit</a></li>
194
+ <li><span class="disabled" title="Coming Soon">Explicit</span></li>
195
+ </ul>
196
+ </div>
197
+
198
+
199
+ <div class="nav-group">
200
+ <div class="nav-group-title">Pow</div>
201
+ <ul class="nav-group-links">
202
+ <li><span class="disabled" title="Coming Soon">Implicit</span></li>
203
+ <li><span class="disabled" title="Coming Soon">Explicit</span></li>
204
+ </ul>
205
+ </div>
206
+
207
+
208
+ <div class="nav-group">
209
+ <div class="nav-group-title">Frictionless</div>
210
+ <ul class="nav-group-links">
211
+ <li><span class="disabled" title="Coming Soon">Implicit</span></li>
212
+ <li><a href="frictionless-explicit.html">Explicit</a></li>
213
+ </ul>
214
+ </div>
215
+
216
+ </div>
217
+ </div>
218
+
219
+
220
+ <div class="nav-section">
221
+ <h3 style="color: white; margin: 0 0 10px 0;">Invisible Captchas</h3>
222
+ <div class="nav-row">
223
+
224
+ <div class="nav-group">
225
+ <div class="nav-group-title">Image</div>
226
+ <ul class="nav-group-links">
227
+ <li><a href="invisible-image-implicit.html">Implicit</a></li>
228
+ <li><a href="invisible-image-explicit.html">Explicit</a></li>
229
+ </ul>
230
+ </div>
231
+
232
+
233
+ <div class="nav-group">
234
+ <div class="nav-group-title">Pow</div>
235
+ <ul class="nav-group-links">
236
+ <li><a href="invisible-pow-implicit.html">Implicit</a></li>
237
+ <li><a href="invisible-pow-explicit.html">Explicit</a></li>
238
+ </ul>
239
+ </div>
240
+
241
+
242
+ <div class="nav-group">
243
+ <div class="nav-group-title">Frictionless</div>
244
+ <ul class="nav-group-links">
245
+ <li><a href="invisible-frictionless-implicit.html">Implicit</a></li>
246
+ <li><a href="invisible-frictionless-explicit.html">Explicit</a></li>
247
+ </ul>
248
+ </div>
249
+
250
+ </div>
251
+ </div>
252
+
253
+ </div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+
258
+ <form>
259
+ <div id="procaptcha-container"></div>
260
+ </form>
261
+
262
+ <script>
263
+ document.addEventListener('DOMContentLoaded', function() {
264
+ const toggleBtn = document.getElementById('nav-toggle');
265
+ const navBar = document.getElementById('nav-topbar');
266
+ const navHeader = document.getElementById('nav-header');
267
+
268
+ // Check if navigation was previously collapsed
269
+ const navCollapsed = localStorage.getItem('navCollapsed') === 'true';
270
+ if (navCollapsed) {
271
+ navBar.classList.add('collapsed');
272
+ }
273
+
274
+ // Function to expand the navigation
275
+ function expandNav() {
276
+ if (navBar.classList.contains('collapsed')) {
277
+ navBar.classList.remove('collapsed');
278
+ localStorage.setItem('navCollapsed', 'false');
279
+ }
280
+ }
281
+
282
+ // Function to collapse the navigation
283
+ function collapseNav() {
284
+ if (!navBar.classList.contains('collapsed')) {
285
+ navBar.classList.add('collapsed');
286
+ localStorage.setItem('navCollapsed', 'true');
287
+ }
288
+ }
289
+
290
+ // Function to toggle the navigation
291
+ function toggleNav() {
292
+ navBar.classList.toggle('collapsed');
293
+ localStorage.setItem('navCollapsed', navBar.classList.contains('collapsed'));
294
+ }
295
+
296
+ // Toggle on button click
297
+ toggleBtn.addEventListener('click', function(e) {
298
+ e.stopPropagation(); // Prevent header click from firing
299
+ toggleNav();
300
+ });
301
+
302
+ // Expand on toggle button hover when collapsed
303
+ toggleBtn.addEventListener('mouseenter', function() {
304
+ if (navBar.classList.contains('collapsed')) {
305
+ expandNav();
306
+ }
307
+ });
308
+
309
+ // Toggle on header click
310
+ navHeader.addEventListener('click', function(e) {
311
+ // Don't toggle if a link within the header was clicked
312
+ if (e.target.tagName === 'A') {
313
+ return;
314
+ }
315
+ toggleNav();
316
+ });
317
+
318
+ // Make the header appear clickable with cursor style
319
+ navHeader.style.cursor = 'pointer';
320
+ });
321
+ </script>
322
+
323
+ </body>
324
+ </html>
package/package.json CHANGED
@@ -8,14 +8,14 @@
8
8
  },
9
9
  "scripts": {
10
10
  "test": "echo \"No test specified\"",
11
- "build": "echo \"No build specified\"",
11
+ "build": "vite build",
12
12
  "build:cjs": "echo 'no cjs build'",
13
13
  "start": "vite serve ./src --port 9232 --config vite.config.ts",
14
14
  "clean": "echo 'nothing to clean'"
15
15
  },
16
- "version": "2.5.0",
16
+ "version": "2.5.3",
17
17
  "devDependencies": {
18
- "@prosopo/dotenv": "2.5.0",
18
+ "@prosopo/dotenv": "2.5.3",
19
19
  "@types/node": "22.5.5",
20
20
  "@vitest/coverage-v8": "2.1.1",
21
21
  "concurrently": "9.0.1",
package/vite.config.ts CHANGED
@@ -12,8 +12,73 @@
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
 
15
+ import fs from "node:fs";
16
+ import path from "node:path";
15
17
  import { loadEnv } from "@prosopo/dotenv";
16
18
  import { type UserConfig, defineConfig } from "vite";
19
+ import navigationInjector from "./src/plugins/navigation-injector.js";
20
+
21
+ // Function to copy contents of a directory to another directory
22
+ function copyDirContents(src: string, dest: string) {
23
+ if (!fs.existsSync(dest)) {
24
+ fs.mkdirSync(dest, { recursive: true });
25
+ }
26
+
27
+ const entries = fs.readdirSync(src, { withFileTypes: true });
28
+
29
+ for (const entry of entries) {
30
+ const srcPath = path.join(src, entry.name);
31
+ const destPath = path.join(dest, entry.name);
32
+
33
+ if (entry.isDirectory()) {
34
+ copyDirContents(srcPath, destPath);
35
+ } else {
36
+ fs.copyFileSync(srcPath, destPath);
37
+ }
38
+ }
39
+ }
40
+
41
+ // This is like close and copy but for output /dist/src to just /dist
42
+ function moveDirectoryContents(
43
+ srcDir: string,
44
+ destDir: string,
45
+ deleteSource = false,
46
+ ) {
47
+ if (!fs.existsSync(srcDir)) {
48
+ return;
49
+ }
50
+
51
+ if (!fs.existsSync(destDir)) {
52
+ fs.mkdirSync(destDir, { recursive: true });
53
+ }
54
+
55
+ const entries = fs.readdirSync(srcDir, { withFileTypes: true });
56
+
57
+ for (const entry of entries) {
58
+ const srcPath = path.join(srcDir, entry.name);
59
+ const destPath = path.join(destDir, entry.name);
60
+
61
+ if (entry.isDirectory()) {
62
+ moveDirectoryContents(srcPath, destPath, deleteSource);
63
+ if (deleteSource) {
64
+ try {
65
+ fs.rmdirSync(srcPath);
66
+ } catch (err) {
67
+ console.warn(`Could not remove directory ${srcPath}:`, err);
68
+ }
69
+ }
70
+ } else {
71
+ try {
72
+ fs.copyFileSync(srcPath, destPath);
73
+ if (deleteSource) {
74
+ fs.unlinkSync(srcPath);
75
+ }
76
+ } catch (err) {
77
+ console.warn(`Error moving file ${srcPath} to ${destPath}:`, err);
78
+ }
79
+ }
80
+ }
81
+ }
17
82
 
18
83
  export default defineConfig(({ command, mode }) => {
19
84
  loadEnv();
@@ -31,10 +96,87 @@ export default defineConfig(({ command, mode }) => {
31
96
  "import.meta.env.PROSOPO_SERVER_URL": JSON.stringify(
32
97
  process.env.PROSOPO_SERVER_URL,
33
98
  ),
99
+ "import.meta.env.VITE_BUNDLE_URL": JSON.stringify(
100
+ process.env.VITE_BUNDLE_URL || "./assets/procaptcha.bundle.js",
101
+ ),
34
102
  },
35
103
  optimizeDeps: {
36
104
  noDiscovery: true,
37
105
  include: ["void-elements", "react", "bn.js"],
38
106
  },
107
+ build: {
108
+ outDir: "dist",
109
+ emptyOutDir: true,
110
+ rollupOptions: {
111
+ input: {
112
+ index: path.resolve(__dirname, "src/index.html"),
113
+ "invisible-pow-explicit": path.resolve(
114
+ __dirname,
115
+ "src/invisible-pow-explicit.html",
116
+ ),
117
+ "invisible-image-explicit": path.resolve(
118
+ __dirname,
119
+ "src/invisible-image-explicit.html",
120
+ ),
121
+ "invisible-pow-implicit": path.resolve(
122
+ __dirname,
123
+ "src/invisible-pow-implicit.html",
124
+ ),
125
+ "invisible-image-implicit": path.resolve(
126
+ __dirname,
127
+ "src/invisible-image-implicit.html",
128
+ ),
129
+ pow: path.resolve(__dirname, "src/pow.html"),
130
+ frictionless: path.resolve(__dirname, "src/frictionless.html"),
131
+ "invisible-frictionless-implicit": path.resolve(
132
+ __dirname,
133
+ "src/invisible-frictionless-implicit.html",
134
+ ),
135
+ "invisible-frictionless-explicit": path.resolve(
136
+ __dirname,
137
+ "src/invisible-frictionless-explicit.html",
138
+ ),
139
+ },
140
+ },
141
+ },
142
+ plugins: [
143
+ navigationInjector(),
144
+ {
145
+ name: "copy-files",
146
+ closeBundle() {
147
+ // This runs after all other plugins have processed files
148
+ console.log("Copying additional files from src to dist...");
149
+ // Only copy assets and other non-HTML files since HTML files are processed by Vite
150
+ const srcAssetsDir = path.resolve(__dirname, "src/assets");
151
+ const destAssetsDir = path.resolve(__dirname, "dist/assets");
152
+ if (fs.existsSync(srcAssetsDir)) {
153
+ copyDirContents(srcAssetsDir, destAssetsDir);
154
+ }
155
+
156
+ // Copy any other necessary directories
157
+ const srcPluginsDir = path.resolve(__dirname, "src/plugins");
158
+ const destPluginsDir = path.resolve(__dirname, "dist/plugins");
159
+ if (fs.existsSync(srcPluginsDir)) {
160
+ copyDirContents(srcPluginsDir, destPluginsDir);
161
+ }
162
+
163
+ // Final step: move any content from dist/src to dist root
164
+ const distSrcDir = path.resolve(__dirname, "dist/src");
165
+ const distDir = path.resolve(__dirname, "dist");
166
+ if (fs.existsSync(distSrcDir)) {
167
+ console.log("Moving files from dist/src to dist root...");
168
+ moveDirectoryContents(distSrcDir, distDir, true);
169
+
170
+ // Try to remove the now-empty dist/src directory
171
+ try {
172
+ fs.rmdirSync(distSrcDir);
173
+ console.log("Removed empty dist/src directory");
174
+ } catch (err) {
175
+ console.warn("Could not remove dist/src directory:", err);
176
+ }
177
+ }
178
+ },
179
+ },
180
+ ],
39
181
  } as UserConfig;
40
182
  });