@networkpro/web 1.9.0 → 1.10.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/README.md CHANGED
@@ -62,11 +62,10 @@ All infrastructure and data flows are designed with **maximum transparency, self
62
62
  ├── netlify/
63
63
  │ ├── edge-functions/
64
64
  │ │ └── csp-report.js # Receives CSP violation reports
65
- │ └── netlify.toml # Netlify configuration
66
65
  ├── scripts/ # General-purpose utility scripts
67
66
  ├── src/
68
67
  │ ├── app.html # Entry HTML (CSP meta, bootstrapping)
69
- │ ├── hooks.client.ts # PWA install prompt & client-side logging
68
+ │ ├── hooks.client.ts # Client-side error handling
70
69
  │ ├── hooks.server.js # Injects CSP headers and permissions policy
71
70
  │ ├── lib/ # Components, utilities, types, styles
72
71
  │ │ ├── components/ # Svelte components
@@ -85,7 +84,9 @@ All infrastructure and data flows are designed with **maximum transparency, self
85
84
  │ │ └── auditCoverage.test.js # Warns about untested source modules
86
85
  │ └── unit/ # Vitest unit tests
87
86
  ├── _redirects # Netlify redirect rules
88
- └── package.json # Project manifest (scripts, deps, etc.)
87
+ ├── netlify.toml # Netlify configuration
88
+ ├── package.json # Project manifest (scripts, deps, etc.)
89
+ └── ...
89
90
  ```
90
91
 
91
92
   
@@ -340,7 +341,7 @@ You can optionally import unregisterServiceWorker() in a debug menu or settings
340
341
 
341
342
  ## 📣 CSP Report Handler
342
343
 
343
- To receive and inspect CSP violation reports in development or production, the repo includes a Netlify-compatible function at:
344
+ To receive and inspect CSP violation reports in development or production, the repo includes a Netlify-compatible [Edge Function](https://docs.netlify.com/edge-functions/overview/) at:
344
345
 
345
346
  ```bash
346
347
  netlify/edge-functions/csp-report.js
package/cspell.json CHANGED
@@ -9,6 +9,8 @@
9
9
  "beforeinstallprompt",
10
10
  "bootentry",
11
11
  "ccby",
12
+ "CCPA",
13
+ "CPRA",
12
14
  "Embedder",
13
15
  "Ente",
14
16
  "esbuild",
package/jsconfig.json CHANGED
@@ -1,6 +1,7 @@
1
1
  /* =========================================================================
2
2
  jsconfig.json
3
3
 
4
+ Copyright © 2025 Network Pro Strategies (Network Pro™)
4
5
  SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
5
6
  This file is part of Network Pro.
6
7
  ========================================================================= */
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "sideEffects": [
5
5
  "./.netlify/shims.js"
6
6
  ],
7
- "version": "1.9.0",
7
+ "version": "1.10.0",
8
8
  "description": "Locking Down Networks, Unlocking Confidence | Security, Networking, Privacy — Network Pro Strategies",
9
9
  "keywords": [
10
10
  "advisory",
@@ -78,9 +78,9 @@
78
78
  },
79
79
  "dependencies": {
80
80
  "dompurify": "^3.2.6",
81
- "posthog-js": "^1.249.0",
81
+ "posthog-js": "^1.249.1",
82
82
  "semver": "^7.7.2",
83
- "svelte": "5.33.11"
83
+ "svelte": "5.33.14"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@eslint/compat": "^1.2.9",
@@ -92,13 +92,13 @@
92
92
  "@sveltejs/vite-plugin-svelte": "5.0.3",
93
93
  "@testing-library/jest-dom": "^6.6.3",
94
94
  "@testing-library/svelte": "^5.2.8",
95
- "@vitest/coverage-v8": "^3.1.4",
95
+ "@vitest/coverage-v8": "^3.2.0",
96
96
  "autoprefixer": "^10.4.21",
97
97
  "browserslist": "^4.25.0",
98
98
  "eslint": "^9.28.0",
99
99
  "eslint-config-prettier": "^10.1.5",
100
- "eslint-plugin-jsdoc": "^50.7.0",
101
- "eslint-plugin-svelte": "^3.9.0",
100
+ "eslint-plugin-jsdoc": "^50.7.1",
101
+ "eslint-plugin-svelte": "^3.9.1",
102
102
  "globals": "^16.2.0",
103
103
  "jsdom": "^26.1.0",
104
104
  "lightningcss": "^1.30.1",
@@ -119,7 +119,7 @@
119
119
  "typescript": "^5.8.3",
120
120
  "vite": "^6.3.5",
121
121
  "vite-plugin-lightningcss": "^0.0.5",
122
- "vitest": "^3.1.4"
122
+ "vitest": "^3.2.0"
123
123
  },
124
124
  "overrides": {
125
125
  "@sveltejs/kit": {
package/src/global.d.ts CHANGED
@@ -22,4 +22,3 @@ declare global {
22
22
  }
23
23
 
24
24
  export { };
25
-
@@ -12,24 +12,18 @@ This file is part of Network Pro.
12
12
  import { base } from "$app/paths";
13
13
  // Import icons for licenses
14
14
  import { bySvg, ccSvg } from "$lib";
15
+ import { CONSTANTS } from "$lib";
15
16
 
16
17
  // Log the base path to verify its value
17
18
  //console.log("Base path:", base);
18
19
 
20
+ console.log(CONSTANTS.APP_NAME);
21
+
19
22
  // Dynamic links for licensing and trademark
20
23
  const ccbyLink = `${base}/license#cc-by`;
21
24
  const gnugplLink = `${base}/license#gnu-gpl`;
22
25
  const trademarkLink = `${base}/license#trademark`;
23
26
 
24
- /**
25
- * Creator details object.
26
- * @typedef {Object} Creator
27
- * @property {string} name - The name of the creator.
28
- * @property {string} url - The URL of the creator's website.
29
- * @property {string} trademark - The trademark name of the creator.
30
- * @property {string} slogan - The slogan of the creator.
31
- */
32
-
33
27
  /**
34
28
  * Icon details object.
35
29
  * @typedef {Object} Icon
@@ -47,15 +41,11 @@ This file is part of Network Pro.
47
41
  * @property {Icon[]} [icons] - An array of icon objects for representing the license visually.
48
42
  */
49
43
 
50
- /**
51
- * @type {Creator}
52
- */
53
- const creator = {
54
- name: "Network Pro Strategies",
55
- url: "https://netwk.pro",
56
- trademark: "Network Pro™",
57
- slogan: "Locking Down Networks™",
58
- };
44
+ /** @type {string} */
45
+ const creatorUrl = "https://netwk.pro";
46
+
47
+ /** @type {string} */
48
+ const creatorSlogan = "Privacy Made Practical";
59
49
 
60
50
  /**
61
51
  * @type {License[]}
@@ -122,22 +112,23 @@ This file is part of Network Pro.
122
112
  <div class="copyright" {...namespaceAttributes}>
123
113
  <!-- Copyright Section -->
124
114
  <p>
125
- Copyright &copy; 2025<br />
115
+ Copyright &copy; {CONSTANTS.COPYRIGHT_YEAR}<br />
126
116
  <a
127
117
  rel="cc:attributionURL dct:creator"
128
118
  property="cc:attributionName"
129
- href={creator.url}
119
+ href={creatorUrl}
130
120
  target={targetBlank}>
131
- <strong>{creator.name}</strong>
121
+ <strong>{CONSTANTS.COMPANY}</strong>
132
122
  </a>
133
- ({creator.trademark})
123
+ ({CONSTANTS.APP_NAME}&trade;)
134
124
  </p>
135
125
 
136
126
  <!-- Trademark Section -->
137
127
  <p>
138
- {creator.trademark}, the shield logo, and the "{creator.slogan}" slogan are
128
+ {CONSTANTS.APP_NAME}&trade;, the shield logo, and the "{creatorSlogan}"
129
+ slogan are
139
130
  <a href={trademarkLink} target={targetSelf}>trademarks</a>
140
- of {creator.name}.
131
+ of {CONSTANTS.COMPANY}.
141
132
  </p>
142
133
 
143
134
  <!-- Licensing Section -->
package/src/lib/index.js CHANGED
@@ -13,7 +13,7 @@ This file is part of Network Pro.
13
13
  * @description Main export point for library components, utilities, and assets
14
14
  * @module src/lib
15
15
  * @author SunDevil311
16
- * @updated 2025-05-14
16
+ * @updated 2025-06-02
17
17
  */
18
18
 
19
19
  // Re-export images from dedicated images.js file
@@ -33,13 +33,24 @@ export * from "./images.js";
33
33
  // export { default as Card } from './components/Card.svelte';
34
34
 
35
35
  /**
36
- * Application constants
37
- * Common values used throughout the application
38
- *
39
- * @type {object}
36
+ * @typedef {{
37
+ * COMPANY: string,
38
+ * APP_NAME: string,
39
+ * COPYRIGHT_YEAR: string,
40
+ * CONTACT_EMAIL: string,
41
+ * SECURE_EMAIL: string,
42
+ * PRIVACY_EMAIL: string,
43
+ * PHONE: string,
44
+ * }} AppConstants
40
45
  */
46
+
47
+ /** @type {AppConstants} */
41
48
  export const CONSTANTS = {
49
+ COMPANY: "Network Pro Strategies",
42
50
  APP_NAME: "Network Pro",
43
51
  COPYRIGHT_YEAR: "2025",
44
- CONTACT_EMAIL: "contact@s.neteng.pro",
52
+ CONTACT_EMAIL: "support (at) neteng.pro",
53
+ SECURE_EMAIL: "contact (at) s.neteng.pro",
54
+ PRIVACY_EMAIL: "privacy (at) netwk.pro",
55
+ PHONE: "(623) 252-4350"
45
56
  };
@@ -9,10 +9,15 @@ This file is part of Network Pro.
9
9
  <script>
10
10
  import { pgpContact, pgpSupport, vcfSrc } from "$lib";
11
11
  import { base } from "$app/paths";
12
+ import { CONSTANTS } from "$lib";
12
13
 
13
14
  // Log the base path to verify its value
14
15
  //console.log("Base path:", base);
15
16
 
17
+ console.log(CONSTANTS.APP_NAME);
18
+
19
+ const { COMPANY, APP_NAME } = CONSTANTS;
20
+
16
21
  /**
17
22
  * URL to the Contact Form route, using the base path
18
23
  * @type {string}
@@ -123,9 +128,9 @@ This file is part of Network Pro.
123
128
  </section>
124
129
 
125
130
  <section id="page-title">
126
- <h1>About Network Pro&trade;</h1>
131
+ <h1>About {APP_NAME}&trade;</h1>
127
132
  <p>
128
- <strong>Network Pro Strategies (Network Pro&trade;)</strong>
133
+ <strong>{COMPANY} ({APP_NAME}&trade;)</strong>
129
134
  <br />
130
135
  <em>Remote-First Cybersecurity & Privacy Consulting</em>
131
136
  </p>
@@ -150,8 +155,8 @@ This file is part of Network Pro.
150
155
  </p>
151
156
 
152
157
  <p>
153
- At <strong>Network Pro Strategies (Network Pro&trade;)</strong>, we deliver
154
- network security, cybersecurity, and digital privacy consulting with clarity,
158
+ At <strong>{COMPANY} ({APP_NAME}&trade;)</strong>, we deliver network
159
+ security, cybersecurity, and digital privacy consulting with clarity,
155
160
  credibility, and care. We believe that real security doesn't have to come at
156
161
  the cost of user autonomy, and that privacy-minded solutions can be both
157
162
  practical and powerful.
@@ -6,8 +6,6 @@ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
6
6
  This file is part of Network Pro.
7
7
  ========================================================================== -->
8
8
 
9
- <!-- cspell:ignore prights prefs pdash -->
10
-
11
9
  <script>
12
10
  import { base } from "$app/paths";
13
11
  import { onMount } from "svelte";
@@ -17,10 +15,13 @@ This file is part of Network Pro.
17
15
  setTrackingPreference,
18
16
  clearTrackingPreferences,
19
17
  } from "$lib/utils/trackingCookies.js";
18
+ import { CONSTANTS } from "$lib";
20
19
 
21
20
  // Log the base path to verify its value
22
21
  //console.log("Base path:", base);
23
22
 
23
+ console.log(CONSTANTS.APP_NAME);
24
+
24
25
  /**
25
26
  * URL to the Privacy Rights Request Form redirect route, using the base path
26
27
  * URL to the Contact Form redirect route, using the base path
@@ -58,17 +59,8 @@ This file is part of Network Pro.
58
59
  { id: "contact", text: "Contact" },
59
60
  ];
60
61
 
61
- /**
62
- * Contact Information
63
- * @type {{ company: string, email: string, secure: string, phone: string, effectiveDate: string }}
64
- */
65
- const contactInfo = {
66
- company: "Network Pro Strategies",
67
- email: "support (at) neteng.pro",
68
- secure: "contact (at) s.neteng.pro",
69
- phone: "(623) 252-4350",
70
- effectiveDate: "May 28, 2025",
71
- };
62
+ /** @type {string} */
63
+ const effectiveDate = "June 2, 2025";
72
64
 
73
65
  /**
74
66
  * Constants used throughout the component for consistent styling and behavior
@@ -148,9 +140,9 @@ This file is part of Network Pro.
148
140
  <section id="page-title">
149
141
  <h1>Privacy Policy</h1>
150
142
  <p>
151
- <strong>{contactInfo.company}</strong><br />
143
+ <strong>{CONSTANTS.COMPANY}</strong><br />
152
144
  <strong>Effective Date:</strong>
153
- {contactInfo.effectiveDate}
145
+ {effectiveDate}
154
146
  </p>
155
147
  </section>
156
148
  <!-- END TITLE -->
@@ -205,14 +197,19 @@ This file is part of Network Pro.
205
197
  </p>
206
198
  {:else if link.id === "collect"}
207
199
  <ul>
208
- <li
209
- ><strong>Personal Identifiers</strong> (e.g., name, email, phone number)</li>
210
- <li><strong>Business and Professional Information</strong></li>
211
- <li
212
- ><strong>Device/Technical Information</strong> (e.g., IP address, browser
213
- type, access logs)</li>
214
- <li
215
- ><strong>Client-Submitted Content</strong> related to our services</li>
200
+ <li>
201
+ <strong>Personal Identifiers</strong> (e.g., name, email, phone number)
202
+ </li>
203
+ <li>
204
+ <strong>Business and Professional Information</strong>
205
+ </li>
206
+ <li>
207
+ <strong>Device/Technical Information</strong> (e.g., IP address, browser
208
+ type, access logs)
209
+ </li>
210
+ <li>
211
+ <strong>Client-Submitted Content</strong> related to our services
212
+ </li>
216
213
  </ul>
217
214
  {:else if link.id === "tracking"}
218
215
  <p>
@@ -226,8 +223,9 @@ This file is part of Network Pro.
226
223
  <ul>
227
224
  <li>Pages visited and navigation behavior</li>
228
225
  <li>Device type, browser version, and operating system</li>
229
- <li
230
- >Time spent on pages and interaction events (e.g., clicks, scrolls)</li>
226
+ <li>
227
+ Time spent on pages and interaction events (e.g., clicks, scrolls)
228
+ </li>
231
229
  <li>Referral URLs and outbound link activity</li>
232
230
  <li>General geolocation (approximate, based on IP address)</li>
233
231
  </ul>
@@ -308,8 +306,6 @@ This file is part of Network Pro.
308
306
  When processing payments, we may collect credit card details and billing
309
307
  contact information. All credit card data is encrypted via TLS and
310
308
  shared only with PCI-compliant processors.
311
- <strong
312
- >Data is purged within 90 days post-verification of payment.</strong>
313
309
  </p>
314
310
  {:else if link.id === "use"}
315
311
  <p>Information is used to:</p>
@@ -325,24 +321,26 @@ This file is part of Network Pro.
325
321
  business information under the following circumstances:
326
322
  </p>
327
323
  <ul>
328
- <li
329
- ><strong>With Service Providers:</strong> We may share your
330
- information with carefully selected third-party vendors under
331
- enforceable, contractual agreements. These providers support essential
332
- aspects of our operations&mdash;including, but not limited to, payment
333
- processing, data analytics, and customer support services. All such
334
- partnerships are structured to uphold our core principles of
324
+ <li>
325
+ <strong>With Service Providers:</strong> We may share your information
326
+ with carefully selected third-party vendors. These providers support
327
+ essential aspects of our operations&mdash;including, but not limited
328
+ to, payment processing, data analytics, and customer support services.
329
+ All such partnerships are structured to uphold our core principles of
335
330
  <em>transparency, self-hosting, and prioritizing user privacy</em> across
336
- all infrastructure and data flows.</li>
337
- <li
338
- ><strong>Legal Compliance:</strong> We may disclose information if required
331
+ all infrastructure and data flows.
332
+ </li>
333
+ <li>
334
+ <strong>Legal Compliance:</strong> We may disclose information if required
339
335
  to do so by applicable law, regulation, legal process, or enforceable governmental
340
- request, including subpoenas or court orders.</li>
341
- <li
342
- ><strong>Business Transfers:</strong> In connection with a merger, acquisition,
336
+ request, including subpoenas or court orders.
337
+ </li>
338
+ <li>
339
+ <strong>Business Transfers:</strong> In connection with a merger, acquisition,
343
340
  asset sale, or similar corporate transaction, we may disclose or transfer
344
341
  personal information, provided that reasonable steps are taken to ensure
345
- continued confidentiality and compliance with applicable privacy laws.</li>
342
+ continued confidentiality and compliance with applicable privacy laws.
343
+ </li>
346
344
  </ul>
347
345
  {:else if link.id === "security"}
348
346
  <p>
@@ -355,22 +353,52 @@ This file is part of Network Pro.
355
353
  </p>
356
354
  {:else if link.id === "rights"}
357
355
  <h3>Your Rights and Choices</h3>
358
- <p> Under applicable state and federal law, you may have rights to: </p>
356
+
357
+ <p
358
+ ><em
359
+ >We do not sell your personal information under any circumstances.</em
360
+ ></p>
361
+ <p>
362
+ However, under applicable state, federal, and international privacy
363
+ laws, you may have the right to:
364
+ </p>
365
+
359
366
  <ul>
360
- <li
361
- ><strong>Access, update, or delete</strong> your personal information,
362
- subject to legal and contractual limitations.</li>
363
- <li
364
- ><strong>Restrict or object to processing</strong> under certain conditions,
365
- as permitted by law.</li>
366
- <li><strong>Opt out of direct marketing</strong></li>
367
+ <li>
368
+ <strong>Access, correct, or delete</strong> your personal information,
369
+ subject to legal and contractual limitations;
370
+ </li>
371
+ <li>
372
+ <strong
373
+ >Restrict or object to the processing of your personal data</strong>
374
+ in certain circumstances, as permitted by law;
375
+ </li>
376
+ <li><strong>Opt out</strong> of direct marketing communications.</li>
367
377
  </ul>
378
+
368
379
  <p>
369
- To exercise these rights, please use our <a
380
+ Although these rights are specifically granted to residents of
381
+ California and the European Union under laws such as the <a
382
+ rel={constants.rel}
383
+ href="https://oag.ca.gov/privacy/ccpa"
384
+ target={constants.targetBlank}
385
+ >California Consumer Privacy Act (CCPA)</a
386
+ >, the California Privacy Rights Act (CPRA), and the
387
+ <a
370
388
  rel={constants.rel}
389
+ href="https://gdpr.eu/what-is-gdpr/"
390
+ target={constants.targetBlank}
391
+ >EU General Data Protection Regulation (GDPR)</a
392
+ >, we voluntarily extend these rights to all users, regardless of
393
+ residency.
394
+ </p>
395
+ <p>
396
+ To exercise any of these rights, you may submit a request through our <a
371
397
  href={prightsLink}
372
- target={constants.targetBlank}>Privacy Rights Request Form</a>
373
- or email us at <code>{contactInfo.secure}</code>.
398
+ target={constants.targetBlank}>Privacy Rights Request Form</a
399
+ >. Alternatively, you can email us at
400
+ <strong>{CONSTANTS.PRIVACY_EMAIL}</strong>
401
+ with the subject line: "<strong>Privacy Rights Preferences</strong>".
374
402
  </p>
375
403
  {:else if link.id === "third-party"}
376
404
  <p>
@@ -396,10 +424,10 @@ This file is part of Network Pro.
396
424
  href={contactLink}
397
425
  target={constants.targetSelf}>Contact Form</a> or contact us directly:</p>
398
426
  <p>
399
- <strong>{contactInfo.company}</strong><br />
400
- 📧 General Inquiries: <code>{contactInfo.email}</code><br />
401
- 🔐 Secure Email: <code>{contactInfo.secure}</code><br />
402
- 📞 Phone: {contactInfo.phone}
427
+ <strong>{CONSTANTS.COMPANY}</strong><br />
428
+ 📧 General Inquiries: {CONSTANTS.CONTACT_EMAIL}<br />
429
+ 🔐 Secure Email: {CONSTANTS.SECURE_EMAIL}<br />
430
+ 📞 Phone: {CONSTANTS.PHONE}
403
431
  </p>
404
432
  {/if}
405
433
 
@@ -411,3 +439,5 @@ This file is part of Network Pro.
411
439
  {/each}
412
440
  <!-- END POLICY SECTIONS -->
413
441
  <!-- END PRIVACY POLICY -->
442
+
443
+ <!-- cspell:ignore prights prefs pdash -->
@@ -15,6 +15,14 @@ This file is part of Network Pro.
15
15
  setTrackingPreference,
16
16
  clearTrackingPreferences,
17
17
  } from "$lib/utils/trackingCookies.js";
18
+ import { CONSTANTS } from "$lib";
19
+
20
+ // Log the base path to verify its value
21
+ //console.log("Base path:", base);
22
+
23
+ console.log(CONSTANTS.APP_NAME);
24
+
25
+ const { PRIVACY_EMAIL } = CONSTANTS;
18
26
 
19
27
  /**
20
28
  * @type {string}
@@ -211,24 +219,48 @@ This file is part of Network Pro.
211
219
  <section id="rights">
212
220
  <h3>Your Rights and Choices</h3>
213
221
 
214
- <p> Under applicable state and federal law, you may have rights to: </p>
222
+ <p
223
+ ><em>We do not sell your personal information under any circumstances.</em
224
+ ></p>
225
+ <p>
226
+ However, under applicable state, federal, and international privacy laws,
227
+ you may have the right to:
228
+ </p>
215
229
 
216
230
  <ul>
217
- <li
218
- ><strong>Access, update, or delete</strong> your personal information, subject
219
- to legal and contractual limitations.</li>
220
- <li
221
- ><strong>Restrict or object to processing</strong> under certain conditions,
222
- as permitted by law.</li>
223
- <li><strong>Opt out of direct marketing</strong></li>
231
+ <li>
232
+ <strong>Access, correct, or delete</strong> your personal information, subject
233
+ to legal and contractual limitations;
234
+ </li>
235
+ <li>
236
+ <strong
237
+ >Restrict or object to the processing of your personal data</strong> in certain
238
+ circumstances, as permitted by law;
239
+ </li>
240
+ <li><strong>Opt out</strong> of direct marketing communications.</li>
224
241
  </ul>
225
242
 
226
243
  <p>
227
- To exercise these rights, please use our <a
244
+ Although these rights are specifically granted to residents of California
245
+ and the European Union under laws such as the <a
246
+ rel={constants.rel}
247
+ href="https://oag.ca.gov/privacy/ccpa"
248
+ target={constants.targetBlank}>California Consumer Privacy Act (CCPA)</a
249
+ >, the California Privacy Rights Act (CPRA), and the
250
+ <a
228
251
  rel={constants.rel}
252
+ href="https://gdpr.eu/what-is-gdpr/"
253
+ target={constants.targetBlank}
254
+ >EU General Data Protection Regulation (GDPR)</a
255
+ >, we voluntarily extend these rights to all users, regardless of residency.
256
+ </p>
257
+ <p>
258
+ To exercise any of these rights, you may submit a request through our <a
229
259
  href={prightsLink}
230
- target={constants.targetBlank}>Privacy Rights Request Form</a>
231
- or email us at <code>contact (at) s.neteng.pro</code>.
260
+ target={constants.targetBlank}>Privacy Rights Request Form</a
261
+ >. Alternatively, you can email us at
262
+ <strong>{PRIVACY_EMAIL}</strong>
263
+ with the subject line: "<strong>Privacy Rights Preferences</strong>".
232
264
  </p>
233
265
  </section>
234
266
 
@@ -10,10 +10,15 @@ This file is part of Network Pro.
10
10
 
11
11
  <script>
12
12
  import { base } from "$app/paths";
13
+ import { CONSTANTS } from "$lib";
13
14
 
14
15
  // Log the base path to verify its value
15
16
  //console.log("Base path:", base);
16
17
 
18
+ console.log(CONSTANTS.APP_NAME);
19
+
20
+ const { COMPANY } = CONSTANTS;
21
+
17
22
  /**
18
23
  * URL to Terms of Use page, using the base path
19
24
  * @type {string}
@@ -29,7 +34,6 @@ This file is part of Network Pro.
29
34
  /**
30
35
  * Common constants used throughout the component
31
36
  * @type {{
32
- * company: string,
33
37
  * effectiveDate: string,
34
38
  * rel: string,
35
39
  * targetBlank: string,
@@ -39,7 +43,6 @@ This file is part of Network Pro.
39
43
  * }}
40
44
  */
41
45
  const constants = {
42
- company: "Network Pro Strategies",
43
46
  effectiveDate: "May 8, 2025",
44
47
  rel: "noopener noreferrer",
45
48
  targetBlank: "_blank",
@@ -79,7 +82,7 @@ This file is part of Network Pro.
79
82
  <section id="page-title">
80
83
  <h1>Consulting Terms and Conditions</h1>
81
84
  <p>
82
- <strong>{constants.company}<br />Effective Date:</strong>
85
+ <strong>{COMPANY}<br />Effective Date:</strong>
83
86
  {constants.effectiveDate}
84
87
  </p>
85
88
  </section>
@@ -129,8 +132,8 @@ This file is part of Network Pro.
129
132
  <p>
130
133
  By engaging with the information security, network security,
131
134
  cybersecurity, and digital privacy consulting and implementation
132
- services provided by {constants.company} ("Company," "we," "us," or "our"),
133
- you ("Client") agree to be bound by these Terms and Conditions ("Terms").
135
+ services provided by {COMPANY} ("Company," "we," "us," or "our"), you ("Client")
136
+ agree to be bound by these Terms and Conditions ("Terms").
134
137
  <strong>
135
138
  These Terms govern all engagements except where explicitly superseded
136
139
  by a separate written agreement or Statement of Work (SOW).
@@ -10,10 +10,15 @@ This file is part of Network Pro.
10
10
 
11
11
  <script>
12
12
  import { base } from "$app/paths";
13
+ import { CONSTANTS } from "$lib";
13
14
 
14
15
  // Log the base path to verify its value
15
16
  //console.log("Base path:", base);
16
17
 
18
+ console.log(CONSTANTS.APP_NAME);
19
+
20
+ const { COMPANY } = CONSTANTS;
21
+
17
22
  /**
18
23
  * URL to Terms and Conditions page, using the base path
19
24
  * @type {string}
@@ -57,10 +62,9 @@ This file is part of Network Pro.
57
62
 
58
63
  /**
59
64
  * Constants for reusable content
60
- * @type {{ company: string, effectiveDate: string, classSmall: string, rel: string, hrefTop: string, targetBlank: string, targetSelf: string }}
65
+ * @type {{ effectiveDate: string, classSmall: string, rel: string, hrefTop: string, targetBlank: string, targetSelf: string }}
61
66
  */
62
67
  const constants = {
63
- company: "Network Pro Strategies",
64
68
  effectiveDate: "May 21, 2025",
65
69
  classSmall: "small-text",
66
70
  rel: "noopener noreferrer",
@@ -85,7 +89,7 @@ This file is part of Network Pro.
85
89
  <section id="page-title">
86
90
  <h1>Website Terms of Use</h1>
87
91
  <p>
88
- <strong>{constants.company}</strong><br />
92
+ <strong>{COMPANY}</strong><br />
89
93
  <strong>Effective Date:</strong>
90
94
  {constants.effectiveDate}
91
95
  </p>
@@ -133,7 +137,7 @@ This file is part of Network Pro.
133
137
 
134
138
  {#if link.id === "introduction"}
135
139
  <p>
136
- Welcome! By accessing or using any of the platforms operated by {constants.company}
140
+ Welcome! By accessing or using any of the platforms operated by {COMPANY}
137
141
  ("Company," "we," "us," or "our"), you agree to be bound by these Terms of
138
142
  Use ("Terms"). If you do not agree to these Terms, please refrain from using
139
143
  our services.
@@ -198,10 +202,10 @@ This file is part of Network Pro.
198
202
  </p>
199
203
  {:else if link.id === "jurisdiction"}
200
204
  <p>
201
- {constants.company} is based in Maricopa County, Arizona. Any legal action
202
- or dispute arising from these Terms of Use shall be subject to the exclusive
203
- jurisdiction of the state and federal courts located in Maricopa County,
204
- Arizona. These Terms shall be governed by the
205
+ {COMPANY} is based in Maricopa County, Arizona. Any legal action or dispute
206
+ arising from these Terms of Use shall be subject to the exclusive jurisdiction
207
+ of the state and federal courts located in Maricopa County, Arizona. These
208
+ Terms shall be governed by the
205
209
  <strong>Arizona Revised Statutes (A.R.S.)</strong> and applicable
206
210
  provisions of the <strong>United States Code (U.S.C.)</strong>.
207
211
  </p>
@@ -433,10 +433,19 @@ footer .container {
433
433
  text-align: center;
434
434
  }
435
435
 
436
+ .gold {
437
+ color: #FFC627;
438
+ }
439
+
436
440
  .visited {
437
441
  color: #7f6227;
438
442
  }
439
443
 
444
+ .goldseparator {
445
+ margin: 0 0.5rem;
446
+ color: #FFC627;
447
+ }
448
+
440
449
  .center-nav {
441
450
  padding: 5px;
442
451
  font-size: 1rem;
@@ -497,12 +506,3 @@ footer .container {
497
506
  font-family: inherit; /* Ensure it uses the same font-family as normal text */
498
507
  font-style: normal; /* Remove italic for the description */
499
508
  }
500
-
501
- .goldseparator {
502
- margin: 0 0.5rem;
503
- color: #FFC627;
504
- }
505
-
506
- .gold {
507
- color: #FFC627;
508
- }
@@ -3,4 +3,4 @@ Copyright © 2025 Network Pro Strategies (Network Pro™)
3
3
  SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
4
4
  This file is part of Network Pro.
5
5
  ========================================================================== */
6
- html{-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{margin:.67em 0;font-size:2em}hr{box-sizing:content-box}pre{font-family:monospace;font-size:1em}a{background-color:#0000}abbr[title]{border-bottom:none;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted buttontext}fieldset{padding:.35em .75em .625em}legend{color:inherit;box-sizing:border-box;white-space:normal;max-width:100%;padding:0;display:table}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}details{display:block}summary{display:list-item}template{display:none}html{color:#222;scroll-behavior:smooth;font-size:1em;line-height:1.4}::-moz-selection{text-shadow:none;background:#191919}::selection{text-shadow:none;background:#191919}hr{border:0;border-top:1px solid #ccc;height:1px;margin:1em 0;padding:0;display:block;overflow:visible}audio,canvas,iframe,img,svg,video{vertical-align:middle}fieldset{border:0;margin:0;padding:0}textarea{resize:vertical}body{color:#fafafa;background-color:#191919;margin:10px;font-family:Arial,Helvetica,sans-serif}a{text-decoration:none}a:link{color:#ffc627}a:hover,a:active{color:#ffc627;text-decoration:underline}a:focus{color:#191919;background-color:#ffc627}a:visited,a:visited:hover{color:#7f6227}.hidden,[hidden]{display:none!important}.visually-hidden{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.visually-hidden.focusable:active,.visually-hidden.focusable:focus{clip:auto;width:auto;height:auto;white-space:inherit;margin:0;position:static;overflow:visible}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}@media print{*,:before,:after{color:#000!important;box-shadow:none!important;text-shadow:none!important;background:#fff!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href)")"}abbr[title]:after{content:" (" attr(title)")"}a[href^=\#]:after,a[href^=javascript\:]:after{content:""}pre{white-space:pre-wrap!important}pre,blockquote{page-break-inside:avoid;border:1px solid #999}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.full-width-section{background-position:50%;background-size:cover;width:100%;max-width:1920px;margin:0 auto}.container{max-width:1200px;margin:0 auto;padding:0 12px}.readable{max-width:900px;margin:0 auto}header,footer{width:100%}header .container,footer .container{max-width:1200px;margin:0 auto;padding:20px 12px}.gh{border-collapse:collapse;border-spacing:0;margin:0 auto}.gh td,.gh th{border-collapse:collapse;word-break:normal;padding:10px 5px;overflow:hidden}.gh .gh-tcell{text-align:center;vertical-align:middle}@media screen and (width<=767px){.gh,.gh col{width:auto!important}.gh-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.soc{border-collapse:collapse;border-spacing:0;margin:0 auto}.soc td,.soc th{border-collapse:collapse;word-break:normal;padding:8px;overflow:hidden}.soc .soc-fa{text-align:center;vertical-align:middle}@media screen and (width<=767px){.soc,.soc col{width:auto!important}.soc-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.foss{border-collapse:collapse;border-spacing:0}.foss td,.foss th{border-collapse:collapse;word-break:normal;padding:10px 5px;overflow:hidden}.foss .foss-cell{text-align:center;vertical-align:middle}@media screen and (width<=767px){.foss,.foss col{width:auto!important}.foss-wrap{-webkit-overflow-scrolling:touch;overflow-x:auto}}.bnav{text-align:center;border-collapse:collapse;border-spacing:0;margin:0 auto}.bnav td,.bnav th{text-align:center;vertical-align:middle;word-break:normal;border-style:none;padding:10px;font-size:.875rem;font-weight:700;line-height:1.125rem;overflow:hidden}.bnav .bnav-cell{text-align:center;vertical-align:middle;align-content:center}@media screen and (width<=767px){.bnav,.bnav col{width:auto!important}.bnav-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.bnav2{border-collapse:collapse;border-spacing:0;margin:0 auto}.bnav2 td{word-break:normal;border-style:none;padding:10px;font-size:.875rem;font-weight:700;line-height:1.125rem;overflow:hidden}.bnav2 th{word-break:normal;border-style:none;padding:12px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.bnav2 .bnav2-cell{text-align:center;vertical-align:middle;align-content:center}@media screen and (width<=767px){.bnav2,.bnav2 col{width:auto!important}.bnav2-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.pgp{border-collapse:collapse;border-spacing:0;margin:0 auto}.pgp td{word-break:normal;border-style:none;padding:10px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.pgp th{word-break:normal;border:1px solid #000;padding:10px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.pgp .pgp-col1{text-align:right;vertical-align:middle;padding-right:1rem}.pgp .pgp-col2{text-align:left;vertical-align:middle;padding-left:1rem}@media screen and (width<=767px){.pgp,.pgp col{width:auto!important}.pgp-wrap{-webkit-overflow-scrolling:touch;margin:2rem 0 auto;overflow-x:auto}}.logo{margin-left:auto;margin-right:auto;display:block}.index-title1{text-align:center;font-style:italic;font-weight:700}.index-title2{letter-spacing:-.015em;text-align:center;font-variant:small-caps;font-size:1.25rem;line-height:1.625rem}.index1{letter-spacing:-.035em;text-align:center;font-style:italic;font-weight:700;line-height:2.125rem}.index2{letter-spacing:-.035em;text-align:center;font-variant:small-caps;font-size:1.5rem;line-height:1.75rem}.index3{letter-spacing:-.035em;text-align:center;font-size:1.5rem;line-height:1.75rem}.index4{letter-spacing:-.035em;text-align:center;font-size:1.5rem;line-height:1.75rem;text-decoration:underline}.subhead{letter-spacing:-.035em;font-variant:small-caps;font-size:1.5rem;line-height:1.75rem}.bold{font-weight:700}.emphasis{font-style:italic}.uline{text-decoration:underline}.bolditalic{font-style:italic;font-weight:700}.bquote{border-left:3px solid #9e9e9e;margin-left:30px;padding-left:10px;font-style:italic}.small-text{font-size:.75rem;line-height:1.125rem}.large-text-center{text-align:center;font-size:1.25rem;line-height:1.75rem}.prewrap{white-space:pre-wrap;display:block}.hr-styled{width:75%;margin:auto}.center-text{text-align:center}.copyright{text-align:center;font-size:.75rem;line-height:1.125rem}.visited{color:#7f6227}.center-nav{text-align:center;padding:5px;font-size:1rem;line-height:1.5rem}.block{resize:none;background:0 0;border:none;border-radius:0;outline:none;width:100%;font-size:.75rem;line-height:1.125rem}.fingerprint{white-space:pre-line;font-weight:700;display:block}.pgp-image{width:150px;height:150px}.spacer{margin:2rem 0}.separator{margin:0 .5rem}.emoji{margin-right:8px}.headline{margin-bottom:4px;font-style:italic;font-weight:700;display:block}.label{font-family:inherit;font-weight:700}.description{font-family:inherit;font-style:normal;font-weight:400;display:inline}.goldseparator{color:#ffc627;margin:0 .5rem}.gold{color:#ffc627}
6
+ html{-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{margin:.67em 0;font-size:2em}hr{box-sizing:content-box}pre{font-family:monospace;font-size:1em}a{background-color:#0000}abbr[title]{border-bottom:none;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted buttontext}fieldset{padding:.35em .75em .625em}legend{color:inherit;box-sizing:border-box;white-space:normal;max-width:100%;padding:0;display:table}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}details{display:block}summary{display:list-item}template{display:none}html{color:#222;scroll-behavior:smooth;font-size:1em;line-height:1.4}::-moz-selection{text-shadow:none;background:#191919}::selection{text-shadow:none;background:#191919}hr{border:0;border-top:1px solid #ccc;height:1px;margin:1em 0;padding:0;display:block;overflow:visible}audio,canvas,iframe,img,svg,video{vertical-align:middle}fieldset{border:0;margin:0;padding:0}textarea{resize:vertical}body{color:#fafafa;background-color:#191919;margin:10px;font-family:Arial,Helvetica,sans-serif}a{text-decoration:none}a:link{color:#ffc627}a:hover,a:active{color:#ffc627;text-decoration:underline}a:focus{color:#191919;background-color:#ffc627}a:visited,a:visited:hover{color:#7f6227}.hidden,[hidden]{display:none!important}.visually-hidden{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.visually-hidden.focusable:active,.visually-hidden.focusable:focus{clip:auto;width:auto;height:auto;white-space:inherit;margin:0;position:static;overflow:visible}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}@media print{*,:before,:after{color:#000!important;box-shadow:none!important;text-shadow:none!important;background:#fff!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href)")"}abbr[title]:after{content:" (" attr(title)")"}a[href^=\#]:after,a[href^=javascript\:]:after{content:""}pre{white-space:pre-wrap!important}pre,blockquote{page-break-inside:avoid;border:1px solid #999}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.full-width-section{background-position:50%;background-size:cover;width:100%;max-width:1920px;margin:0 auto}.container{max-width:1200px;margin:0 auto;padding:0 12px}.readable{max-width:900px;margin:0 auto}header,footer{width:100%}header .container,footer .container{max-width:1200px;margin:0 auto;padding:20px 12px}.gh{border-collapse:collapse;border-spacing:0;margin:0 auto}.gh td,.gh th{border-collapse:collapse;word-break:normal;padding:10px 5px;overflow:hidden}.gh .gh-tcell{text-align:center;vertical-align:middle}@media screen and (width<=767px){.gh,.gh col{width:auto!important}.gh-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.soc{border-collapse:collapse;border-spacing:0;margin:0 auto}.soc td,.soc th{border-collapse:collapse;word-break:normal;padding:8px;overflow:hidden}.soc .soc-fa{text-align:center;vertical-align:middle}@media screen and (width<=767px){.soc,.soc col{width:auto!important}.soc-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.foss{border-collapse:collapse;border-spacing:0}.foss td,.foss th{border-collapse:collapse;word-break:normal;padding:10px 5px;overflow:hidden}.foss .foss-cell{text-align:center;vertical-align:middle}@media screen and (width<=767px){.foss,.foss col{width:auto!important}.foss-wrap{-webkit-overflow-scrolling:touch;overflow-x:auto}}.bnav{text-align:center;border-collapse:collapse;border-spacing:0;margin:0 auto}.bnav td,.bnav th{text-align:center;vertical-align:middle;word-break:normal;border-style:none;padding:10px;font-size:.875rem;font-weight:700;line-height:1.125rem;overflow:hidden}.bnav .bnav-cell{text-align:center;vertical-align:middle;align-content:center}@media screen and (width<=767px){.bnav,.bnav col{width:auto!important}.bnav-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.bnav2{border-collapse:collapse;border-spacing:0;margin:0 auto}.bnav2 td{word-break:normal;border-style:none;padding:10px;font-size:.875rem;font-weight:700;line-height:1.125rem;overflow:hidden}.bnav2 th{word-break:normal;border-style:none;padding:12px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.bnav2 .bnav2-cell{text-align:center;vertical-align:middle;align-content:center}@media screen and (width<=767px){.bnav2,.bnav2 col{width:auto!important}.bnav2-wrap{-webkit-overflow-scrolling:touch;margin:auto 0;overflow-x:auto}}.pgp{border-collapse:collapse;border-spacing:0;margin:0 auto}.pgp td{word-break:normal;border-style:none;padding:10px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.pgp th{word-break:normal;border:1px solid #000;padding:10px;font-size:.875rem;line-height:1.125rem;overflow:hidden}.pgp .pgp-col1{text-align:right;vertical-align:middle;padding-right:1rem}.pgp .pgp-col2{text-align:left;vertical-align:middle;padding-left:1rem}@media screen and (width<=767px){.pgp,.pgp col{width:auto!important}.pgp-wrap{-webkit-overflow-scrolling:touch;margin:2rem 0 auto;overflow-x:auto}}.logo{margin-left:auto;margin-right:auto;display:block}.index-title1{text-align:center;font-style:italic;font-weight:700}.index-title2{letter-spacing:-.015em;text-align:center;font-variant:small-caps;font-size:1.25rem;line-height:1.625rem}.index1{letter-spacing:-.035em;text-align:center;font-style:italic;font-weight:700;line-height:2.125rem}.index2{letter-spacing:-.035em;text-align:center;font-variant:small-caps;font-size:1.5rem;line-height:1.75rem}.index3{letter-spacing:-.035em;text-align:center;font-size:1.5rem;line-height:1.75rem}.index4{letter-spacing:-.035em;text-align:center;font-size:1.5rem;line-height:1.75rem;text-decoration:underline}.subhead{letter-spacing:-.035em;font-variant:small-caps;font-size:1.5rem;line-height:1.75rem}.bold{font-weight:700}.emphasis{font-style:italic}.uline{text-decoration:underline}.bolditalic{font-style:italic;font-weight:700}.bquote{border-left:3px solid #9e9e9e;margin-left:30px;padding-left:10px;font-style:italic}.small-text{font-size:.75rem;line-height:1.125rem}.large-text-center{text-align:center;font-size:1.25rem;line-height:1.75rem}.prewrap{white-space:pre-wrap;display:block}.hr-styled{width:75%;margin:auto}.center-text{text-align:center}.copyright{text-align:center;font-size:.75rem;line-height:1.125rem}.gold{color:#ffc627}.visited{color:#7f6227}.goldseparator{color:#ffc627;margin:0 .5rem}.center-nav{text-align:center;padding:5px;font-size:1rem;line-height:1.5rem}.block{resize:none;background:0 0;border:none;border-radius:0;outline:none;width:100%;font-size:.75rem;line-height:1.125rem}.fingerprint{white-space:pre-line;font-weight:700;display:block}.pgp-image{width:150px;height:150px}.spacer{margin:2rem 0}.separator{margin:0 .5rem}.emoji{margin-right:8px}.headline{margin-bottom:4px;font-style:italic;font-weight:700;display:block}.label{font-family:inherit;font-weight:700}.description{font-family:inherit;font-style:normal;font-weight:400;display:inline}
@@ -33,7 +33,7 @@ describe("sanitizeHtml", () => {
33
33
  it("removes dangerous attributes like onerror", async () => {
34
34
  const dirty = `<img src="x" onerror="alert(1)">`;
35
35
  const clean = await sanitizeHtml(dirty);
36
- expect(clean).toBe('<img src="x">');
36
+ expect(clean).toBe("<img>");
37
37
  });
38
38
 
39
39
  it("keeps valid external links", async () => {