@networkpro/web 1.12.8 → 1.13.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/CHANGELOG.md +64 -1
- package/README.md +8 -8
- package/cspell.json +1 -0
- package/eslint.config.mjs +48 -48
- package/jsconfig.template.jsonc +3 -1
- package/netlify/edge-functions/csp-report.js +31 -31
- package/package.json +6 -6
- package/playwright.config.js +14 -14
- package/postcss.config.mjs +1 -1
- package/scripts/auditScripts.js +16 -16
- package/scripts/bundleCss.js +5 -5
- package/scripts/checkEnv.js +6 -6
- package/scripts/checkNode.js +10 -10
- package/scripts/checkVersions.js +6 -6
- package/scripts/flattenHeaders.js +13 -13
- package/scripts/generateTest.js +5 -5
- package/scripts/openReport.js +3 -3
- package/scripts/validateHeaders.js +13 -13
- package/src/hooks.client.ts +1 -1
- package/src/hooks.server.js +31 -31
- package/src/lib/components/Badges.svelte +9 -9
- package/src/lib/components/CodeBlock.svelte +13 -0
- package/src/lib/components/ContainerSection.svelte +1 -1
- package/src/lib/components/FullWidthSection.svelte +3 -3
- package/src/lib/components/LegalNav.svelte +6 -6
- package/src/lib/components/Logo.svelte +9 -9
- package/src/lib/components/MetaTags.svelte +3 -3
- package/src/lib/components/PWAInstallButton.svelte +4 -4
- package/src/lib/components/RedirectPage.svelte +4 -4
- package/src/lib/components/SocialMedia.svelte +16 -16
- package/src/lib/components/foss/FossItemContent.svelte +18 -18
- package/src/lib/components/layout/Footer.svelte +17 -17
- package/src/lib/components/layout/HeaderDefault.svelte +16 -16
- package/src/lib/components/layout/HeaderHome.svelte +14 -14
- package/src/lib/images.js +34 -34
- package/src/lib/index.js +15 -15
- package/src/lib/meta.js +29 -29
- package/src/lib/pages/AboutContent.svelte +24 -24
- package/src/lib/pages/FossContent.svelte +12 -12
- package/src/lib/pages/HomeContent.svelte +6 -6
- package/src/lib/pages/LicenseContent.svelte +38 -38
- package/src/lib/pages/PGPContent.svelte +61 -29
- package/src/lib/pages/PrivacyContent.svelte +39 -39
- package/src/lib/pages/PrivacyDashboard.svelte +12 -12
- package/src/lib/pages/TermsConditionsContent.svelte +28 -28
- package/src/lib/pages/TermsUseContent.svelte +26 -26
- package/src/lib/registerServiceWorker.js +25 -25
- package/src/lib/stores/posthog.js +13 -13
- package/src/lib/stores/trackingPreferences.js +19 -19
- package/src/lib/styles/css/default.css +5 -1
- package/src/lib/styles/global.min.css +1 -1
- package/src/lib/unregisterServiceWorker.js +1 -1
- package/src/lib/utils/purify.js +4 -4
- package/src/lib/utils/utm.js +2 -2
- package/src/routes/+error.svelte +4 -4
- package/src/routes/+layout.js +6 -6
- package/src/routes/+layout.svelte +29 -29
- package/src/routes/+page.server.js +2 -2
- package/src/routes/+page.svelte +9 -9
- package/src/routes/about/+page.server.js +2 -2
- package/src/routes/about/+page.svelte +7 -7
- package/src/routes/api/mock-csp/+server.js +3 -3
- package/src/routes/consultation/+page.svelte +5 -5
- package/src/routes/contact/+page.svelte +5 -5
- package/src/routes/foss-spotlight/+page.server.js +2 -2
- package/src/routes/foss-spotlight/+page.svelte +7 -7
- package/src/routes/license/+page.server.js +2 -2
- package/src/routes/license/+page.svelte +7 -7
- package/src/routes/pgp/+page.server.js +2 -2
- package/src/routes/pgp/+page.svelte +7 -7
- package/src/routes/pgp/[key]/+server.js +9 -9
- package/src/routes/privacy/+page.server.js +2 -2
- package/src/routes/privacy/+page.svelte +7 -7
- package/src/routes/privacy-dashboard/+page.server.js +2 -2
- package/src/routes/privacy-dashboard/+page.svelte +8 -8
- package/src/routes/privacy-rights/+page.svelte +5 -5
- package/src/routes/status/+page.server.js +2 -2
- package/src/routes/terms-conditions/+page.server.js +2 -2
- package/src/routes/terms-conditions/+page.svelte +7 -7
- package/src/routes/terms-of-use/+page.server.js +2 -2
- package/src/routes/terms-of-use/+page.svelte +7 -7
- package/src/service-worker.js +86 -85
- package/static/disableSw.js +2 -2
- package/static/img/powered-by-proton.svg +1 -0
- package/static/offline.html +7 -7
- package/static/sitemap.xml +64 -4
- package/stylelint.config.js +56 -56
- package/svelte.config.js +6 -6
- package/tests/e2e/app.spec.js +25 -25
- package/tests/e2e/mobile.spec.js +18 -18
- package/tests/e2e/shared/helpers.js +4 -4
- package/tests/internal/auditCoverage.test.js +24 -24
- package/tests/unit/checkEnv.test.js +10 -10
- package/tests/unit/checkVersions.test.js +4 -4
- package/tests/unit/csp-report.test.js +24 -24
- package/tests/unit/demo.test.js +3 -3
- package/tests/unit/lib/utils/purify.test.js +12 -12
- package/tests/unit/routes/page.svelte.test.js +10 -10
- package/tests/unit/unregisterServiceWorker.test.js +5 -5
- package/tests/unit/utm.test.js +13 -13
- package/vite.config.js +5 -5
- package/vitest-setup-client.js +4 -4
- package/vitest.config.client.js +15 -15
- package/vitest.config.server.js +13 -13
|
@@ -14,16 +14,16 @@ This file is part of Network Pro.
|
|
|
14
14
|
* and PWA behavior.
|
|
15
15
|
*/
|
|
16
16
|
export function registerServiceWorker() {
|
|
17
|
-
const disableSW = window?.__DISABLE_SW__ || location.search.includes(
|
|
17
|
+
const disableSW = window?.__DISABLE_SW__ || location.search.includes('nosw');
|
|
18
18
|
|
|
19
19
|
if (disableSW) {
|
|
20
|
-
console.warn(
|
|
20
|
+
console.warn('⚠️ Service Worker registration disabled via diagnostic mode.');
|
|
21
21
|
|
|
22
|
-
if (
|
|
22
|
+
if ('serviceWorker' in navigator) {
|
|
23
23
|
navigator.serviceWorker.getRegistrations().then((registrations) => {
|
|
24
24
|
registrations.forEach((reg) =>
|
|
25
25
|
reg.unregister().then((success) => {
|
|
26
|
-
console.log(
|
|
26
|
+
console.log('🧹 SW unregistered from registerServiceWorker.js:', success);
|
|
27
27
|
})
|
|
28
28
|
);
|
|
29
29
|
});
|
|
@@ -32,51 +32,51 @@ export function registerServiceWorker() {
|
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
if (
|
|
36
|
-
const isFirefox = navigator.userAgent.includes(
|
|
35
|
+
if ('serviceWorker' in navigator) {
|
|
36
|
+
const isFirefox = navigator.userAgent.includes('Firefox');
|
|
37
37
|
const isDevelopment =
|
|
38
|
-
location.hostname ===
|
|
38
|
+
location.hostname === 'localhost' || location.hostname === '127.0.0.1';
|
|
39
39
|
|
|
40
40
|
if (isFirefox && isDevelopment) {
|
|
41
|
-
console.log(
|
|
41
|
+
console.log('🛑 SW registration skipped in Firefox development mode');
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
window.addEventListener(
|
|
45
|
+
window.addEventListener('load', () => {
|
|
46
46
|
navigator.serviceWorker
|
|
47
|
-
.register(
|
|
47
|
+
.register('service-worker.js')
|
|
48
48
|
.then((registration) => {
|
|
49
|
-
console.log(
|
|
49
|
+
console.log('✅ Service Worker registered with scope:', registration.scope);
|
|
50
50
|
|
|
51
51
|
// 🧼 Manual cleanup of unexpected caches
|
|
52
52
|
caches.keys().then((keys) => {
|
|
53
53
|
keys.forEach((key) => {
|
|
54
|
-
if (!key.startsWith(
|
|
55
|
-
console.log(
|
|
54
|
+
if (!key.startsWith('cache-')) {
|
|
55
|
+
console.log('🧹 Deleting unexpected cache:', key);
|
|
56
56
|
caches.delete(key);
|
|
57
57
|
}
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
registration.addEventListener(
|
|
61
|
+
registration.addEventListener('updatefound', () => {
|
|
62
62
|
const newWorker = registration.installing;
|
|
63
|
-
console.log(
|
|
63
|
+
console.log('[SW-CLIENT] New service worker installing...');
|
|
64
64
|
|
|
65
65
|
if (!newWorker) return;
|
|
66
66
|
|
|
67
67
|
let updatePrompted = false;
|
|
68
68
|
|
|
69
|
-
newWorker.addEventListener(
|
|
70
|
-
console.log(
|
|
69
|
+
newWorker.addEventListener('statechange', () => {
|
|
70
|
+
console.log('[SW-CLIENT] New worker state:', newWorker.state);
|
|
71
71
|
|
|
72
72
|
if (
|
|
73
|
-
newWorker.state ===
|
|
73
|
+
newWorker.state === 'installed' &&
|
|
74
74
|
navigator.serviceWorker.controller &&
|
|
75
75
|
!updatePrompted
|
|
76
76
|
) {
|
|
77
77
|
updatePrompted = true;
|
|
78
|
-
console.log(
|
|
79
|
-
if (confirm(
|
|
78
|
+
console.log('[SW-CLIENT] New SW installed. Prompting user to reload.');
|
|
79
|
+
if (confirm('New content is available. Reload to update?')) {
|
|
80
80
|
window.location.reload();
|
|
81
81
|
}
|
|
82
82
|
}
|
|
@@ -84,22 +84,22 @@ export function registerServiceWorker() {
|
|
|
84
84
|
});
|
|
85
85
|
})
|
|
86
86
|
.catch((error) => {
|
|
87
|
-
console.error(
|
|
87
|
+
console.error('❌ Service Worker registration failed:', error);
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
let refreshing = false;
|
|
91
|
-
navigator.serviceWorker.addEventListener(
|
|
92
|
-
console.log(
|
|
91
|
+
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
|
92
|
+
console.log('[SW-CLIENT] Controller changed.');
|
|
93
93
|
if (!refreshing) {
|
|
94
94
|
refreshing = true;
|
|
95
95
|
window.location.reload();
|
|
96
96
|
}
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
window.addEventListener(
|
|
99
|
+
window.addEventListener('beforeinstallprompt', (e) => {
|
|
100
100
|
e.preventDefault();
|
|
101
101
|
window.dispatchEvent(
|
|
102
|
-
new CustomEvent(
|
|
102
|
+
new CustomEvent('pwa-install-available', {
|
|
103
103
|
detail: /** @type {BeforeInstallPromptEvent} */ (e),
|
|
104
104
|
}),
|
|
105
105
|
);
|
|
@@ -14,8 +14,8 @@ SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
|
14
14
|
import {
|
|
15
15
|
remindUserToReconsent,
|
|
16
16
|
trackingPreferences,
|
|
17
|
-
} from
|
|
18
|
-
import { get, writable } from
|
|
17
|
+
} from '$lib/stores/trackingPreferences.js';
|
|
18
|
+
import { get, writable } from 'svelte/store';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Tracks whether tracking is allowed based on cookies, DNT/GPC, and user preference.
|
|
@@ -41,7 +41,7 @@ let ph = null;
|
|
|
41
41
|
* @returns {Promise<void>}
|
|
42
42
|
*/
|
|
43
43
|
export async function initPostHog() {
|
|
44
|
-
if (initialized || typeof window ===
|
|
44
|
+
if (initialized || typeof window === 'undefined') return;
|
|
45
45
|
initialized = true;
|
|
46
46
|
|
|
47
47
|
const { enabled } = get(trackingPreferences);
|
|
@@ -49,32 +49,32 @@ export async function initPostHog() {
|
|
|
49
49
|
showReminder.set(get(remindUserToReconsent)); // ✅ use derived store instead
|
|
50
50
|
|
|
51
51
|
if (!enabled) {
|
|
52
|
-
console.log(
|
|
52
|
+
console.log('[PostHog] Tracking is disabled — skipping init.');
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
const posthogModule = await import(
|
|
56
|
+
const posthogModule = await import('posthog-js');
|
|
57
57
|
ph = posthogModule.default;
|
|
58
58
|
|
|
59
59
|
// cspell:disable-next-line
|
|
60
|
-
ph.init(
|
|
61
|
-
api_host:
|
|
60
|
+
ph.init('phc_Qshfo6AXzh4pS7aPigfqyeo4qj1qlyh7gDuHDeVMSR0', {
|
|
61
|
+
api_host: 'https://us.i.posthog.com',
|
|
62
62
|
autocapture: true,
|
|
63
63
|
capture_pageview: false,
|
|
64
|
-
person_profiles:
|
|
64
|
+
person_profiles: 'identified_only',
|
|
65
65
|
loaded: (phInstance) => {
|
|
66
66
|
if (!enabled) {
|
|
67
67
|
console.log(
|
|
68
|
-
|
|
68
|
+
'[PostHog] ⛔ User opted out — calling opt_out_capturing()',
|
|
69
69
|
);
|
|
70
70
|
phInstance.opt_out_capturing();
|
|
71
71
|
} else {
|
|
72
|
-
console.log(
|
|
72
|
+
console.log('[PostHog] ✅ Tracking enabled');
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
ph.capture(
|
|
77
|
+
ph.capture('$pageview');
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/**
|
|
@@ -105,8 +105,8 @@ export function identify(id, properties = {}) {
|
|
|
105
105
|
* @returns {void}
|
|
106
106
|
*/
|
|
107
107
|
export function _resetPostHog() {
|
|
108
|
-
if (import.meta.env.MODE ===
|
|
109
|
-
console.warn(
|
|
108
|
+
if (import.meta.env.MODE === 'production') {
|
|
109
|
+
console.warn('[PostHog] _resetPostHog() called in production — no-op');
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -19,8 +19,8 @@ This file is part of Network Pro.
|
|
|
19
19
|
* @module src/lib/stores
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import { browser } from
|
|
23
|
-
import { derived, writable } from
|
|
22
|
+
import { browser } from '$app/environment';
|
|
23
|
+
import { derived, writable } from 'svelte/store';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* @typedef {object} TrackingState
|
|
@@ -36,7 +36,7 @@ import { derived, writable } from "svelte/store";
|
|
|
36
36
|
* @returns {string} Raw document.cookie or empty string (SSR-safe)
|
|
37
37
|
*/
|
|
38
38
|
function readCookies() {
|
|
39
|
-
return browser ? document.cookie ||
|
|
39
|
+
return browser ? document.cookie || '' : '';
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
@@ -96,7 +96,7 @@ function removeConsentTimestamp() {
|
|
|
96
96
|
function getPrivacySignals() {
|
|
97
97
|
if (!browser) return { dnt: false, gpc: false };
|
|
98
98
|
|
|
99
|
-
const dnt = navigator.doNotTrack ===
|
|
99
|
+
const dnt = navigator.doNotTrack === '1';
|
|
100
100
|
// @ts-expect-error: Non-standard GPC property
|
|
101
101
|
const gpc = navigator.globalPrivacyControl === true;
|
|
102
102
|
|
|
@@ -112,18 +112,18 @@ function getPrivacySignals() {
|
|
|
112
112
|
* @returns {string}
|
|
113
113
|
*/
|
|
114
114
|
function deriveStatus({ optedOut, optedIn, dnt, gpc }) {
|
|
115
|
-
if (optedOut) return
|
|
116
|
-
if (optedIn) return
|
|
117
|
-
if (dnt || gpc) return
|
|
118
|
-
return
|
|
115
|
+
if (optedOut) return '🔒 Tracking disabled (manual opt-out)';
|
|
116
|
+
if (optedIn) return '✅ Tracking enabled (manual opt-in)';
|
|
117
|
+
if (dnt || gpc) return '🛑 Tracking disabled (via browser signal)';
|
|
118
|
+
return '⚙️ Using default settings (tracking enabled)';
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
/**
|
|
122
122
|
* @returns {TrackingState}
|
|
123
123
|
*/
|
|
124
124
|
function computePreferences() {
|
|
125
|
-
const optedOut = cookieExists(
|
|
126
|
-
const optedIn = cookieExists(
|
|
125
|
+
const optedOut = cookieExists('disable_tracking');
|
|
126
|
+
const optedIn = cookieExists('enable_tracking');
|
|
127
127
|
const { dnt, gpc } = getPrivacySignals();
|
|
128
128
|
|
|
129
129
|
const enabled = optedIn || (!optedOut && !dnt && !gpc);
|
|
@@ -143,7 +143,7 @@ export const trackingPreferences = writable(
|
|
|
143
143
|
dnt: false,
|
|
144
144
|
gpc: false,
|
|
145
145
|
enabled: false,
|
|
146
|
-
status:
|
|
146
|
+
status: '⏳ Checking tracking preferences...',
|
|
147
147
|
},
|
|
148
148
|
);
|
|
149
149
|
|
|
@@ -154,8 +154,8 @@ export const trackingPreferences = writable(
|
|
|
154
154
|
function hasUserManuallySetTrackingPreference() {
|
|
155
155
|
const cookies = readCookies();
|
|
156
156
|
return (
|
|
157
|
-
cookies.includes(
|
|
158
|
-
cookies.includes(
|
|
157
|
+
cookies.includes('enable_tracking=true') ||
|
|
158
|
+
cookies.includes('disable_tracking=true')
|
|
159
159
|
);
|
|
160
160
|
}
|
|
161
161
|
|
|
@@ -193,8 +193,8 @@ export function refreshTrackingPreferences() {
|
|
|
193
193
|
* @returns {void}
|
|
194
194
|
*/
|
|
195
195
|
export function setOptIn() {
|
|
196
|
-
setCookie(
|
|
197
|
-
removeCookie(
|
|
196
|
+
setCookie('enable_tracking');
|
|
197
|
+
removeCookie('disable_tracking');
|
|
198
198
|
setConsentTimestamp();
|
|
199
199
|
refreshTrackingPreferences();
|
|
200
200
|
}
|
|
@@ -204,8 +204,8 @@ export function setOptIn() {
|
|
|
204
204
|
* @returns {void}
|
|
205
205
|
*/
|
|
206
206
|
export function setOptOut() {
|
|
207
|
-
setCookie(
|
|
208
|
-
removeCookie(
|
|
207
|
+
setCookie('disable_tracking');
|
|
208
|
+
removeCookie('enable_tracking');
|
|
209
209
|
setConsentTimestamp();
|
|
210
210
|
refreshTrackingPreferences();
|
|
211
211
|
}
|
|
@@ -215,8 +215,8 @@ export function setOptOut() {
|
|
|
215
215
|
* @returns {void}
|
|
216
216
|
*/
|
|
217
217
|
export function clearPrefs() {
|
|
218
|
-
removeCookie(
|
|
219
|
-
removeCookie(
|
|
218
|
+
removeCookie('enable_tracking');
|
|
219
|
+
removeCookie('disable_tracking');
|
|
220
220
|
removeConsentTimestamp();
|
|
221
221
|
refreshTrackingPreferences();
|
|
222
222
|
}
|
|
@@ -457,12 +457,16 @@ footer .container {
|
|
|
457
457
|
.block {
|
|
458
458
|
width: 100%;
|
|
459
459
|
border: none;
|
|
460
|
-
font-size: 0.
|
|
460
|
+
font-size: 0.875rem;
|
|
461
461
|
line-height: 1.125rem;
|
|
462
462
|
background: none;
|
|
463
463
|
border-radius: 0;
|
|
464
|
+
font-family: monospace; /* retain code look */
|
|
464
465
|
outline: none;
|
|
466
|
+
overflow-wrap: break-word; /* modern replacement */
|
|
465
467
|
resize: none;
|
|
468
|
+
white-space: normal; /* allow wrapping */
|
|
469
|
+
word-break: normal; /* avoid deprecated behavior */
|
|
466
470
|
}
|
|
467
471
|
|
|
468
472
|
.fingerprint {
|
|
@@ -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:visited{color:#7f6227}a:focus-visible{color:#191919;outline-offset:4px;background-color:#ffc627;outline:2px solid #ffc627}a:focus:not(:focus-visible){color:inherit;background-color:#0000;outline:none}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:.
|
|
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:visited{color:#7f6227}a:focus-visible{color:#191919;outline-offset:4px;background-color:#ffc627;outline:2px solid #ffc627}a:focus:not(:focus-visible){color:inherit;background-color:#0000;outline:none}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{overflow-wrap:break-word;resize:none;white-space:normal;word-break:normal;background:0 0;border:none;border-radius:0;outline:none;width:100%;font-family:monospace;font-size:.875rem;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}.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.pgp-entry{flex-wrap:wrap;align-items:center;gap:2rem;margin-bottom:2rem;display:flex}.pgp-text{flex:2;min-width:250px}.pgp-qr{flex:1;min-width:150px}
|
|
@@ -13,7 +13,7 @@ export function unregisterServiceWorker() {
|
|
|
13
13
|
if ('serviceWorker' in navigator) {
|
|
14
14
|
navigator.serviceWorker.getRegistrations().then((registrations) => {
|
|
15
15
|
registrations.forEach((reg) => reg.unregister());
|
|
16
|
-
console.log(
|
|
16
|
+
console.log('🧹 All service workers unregistered.');
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
}
|
package/src/lib/utils/purify.js
CHANGED
|
@@ -15,7 +15,7 @@ This file is part of Network Pro.
|
|
|
15
15
|
* @updated 2025-06-01
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import createDOMPurify from
|
|
18
|
+
import createDOMPurify from 'dompurify';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* @typedef {ReturnType<import('dompurify').default>} DOMPurifyInstance
|
|
@@ -37,13 +37,13 @@ let jsdomWindow = null;
|
|
|
37
37
|
export async function getDOMPurify() {
|
|
38
38
|
if (DOMPurifyInstance) return DOMPurifyInstance;
|
|
39
39
|
|
|
40
|
-
if (typeof window !==
|
|
40
|
+
if (typeof window !== 'undefined') {
|
|
41
41
|
// ✅ Client-side: use native window
|
|
42
42
|
DOMPurifyInstance = createDOMPurify(window);
|
|
43
43
|
} else {
|
|
44
44
|
// ✅ SSR: dynamically import jsdom to avoid bundling
|
|
45
|
-
const { JSDOM } = await import(
|
|
46
|
-
jsdomWindow = jsdomWindow || new JSDOM(
|
|
45
|
+
const { JSDOM } = await import('jsdom');
|
|
46
|
+
jsdomWindow = jsdomWindow || new JSDOM('').window;
|
|
47
47
|
DOMPurifyInstance = createDOMPurify(jsdomWindow);
|
|
48
48
|
}
|
|
49
49
|
|
package/src/lib/utils/utm.js
CHANGED
|
@@ -20,8 +20,8 @@ This file is part of Network Pro.
|
|
|
20
20
|
* @returns {string | null}
|
|
21
21
|
*/
|
|
22
22
|
export function appendUTM(url) {
|
|
23
|
-
if (typeof window ===
|
|
23
|
+
if (typeof window === 'undefined') return null;
|
|
24
24
|
|
|
25
|
-
const utm = new URLSearchParams(window.location.search).get(
|
|
25
|
+
const utm = new URLSearchParams(window.location.search).get('utm_source');
|
|
26
26
|
return utm ? `${url}?utm_source=${encodeURIComponent(utm)}` : url;
|
|
27
27
|
}
|
package/src/routes/+error.svelte
CHANGED
|
@@ -24,21 +24,21 @@ This file is part of Network Pro.
|
|
|
24
24
|
*/
|
|
25
25
|
export let error;
|
|
26
26
|
|
|
27
|
-
const centerText =
|
|
27
|
+
const centerText = 'center-text';
|
|
28
28
|
|
|
29
29
|
// Get the pathname from the URL if available
|
|
30
30
|
const pathname =
|
|
31
|
-
typeof window !==
|
|
31
|
+
typeof window !== 'undefined' ? window.location.pathname : '/';
|
|
32
32
|
</script>
|
|
33
33
|
|
|
34
34
|
<main>
|
|
35
35
|
<h1 class={centerText}
|
|
36
|
-
>{status} - {status === 404 ?
|
|
36
|
+
>{status} - {status === 404 ? 'Page Not Found' : 'Error'}</h1>
|
|
37
37
|
<p class={centerText}>
|
|
38
38
|
{#if status === 404}
|
|
39
39
|
The page "{pathname}" does not exist.
|
|
40
40
|
{:else}
|
|
41
|
-
{error?.message ||
|
|
41
|
+
{error?.message || 'An error occurred'}
|
|
42
42
|
{/if}
|
|
43
43
|
</p>
|
|
44
44
|
</main>
|
package/src/routes/+layout.js
CHANGED
|
@@ -12,27 +12,27 @@ This file is part of Network Pro.
|
|
|
12
12
|
* @property {string} description - The description of the page
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { meta as routeMeta } from
|
|
15
|
+
import { meta as routeMeta } from '$lib/meta.js'; // Import meta from $lib/meta.js and alias it
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Fallback metadata to satisfy typing in +layout.svelte and +page.svelte.
|
|
19
19
|
* Actual meta content is provided per-route via +page.server.js.
|
|
20
20
|
*/
|
|
21
21
|
const fallbackMeta = {
|
|
22
|
-
title:
|
|
22
|
+
title: 'Security, Networking, Privacy — Network Pro™',
|
|
23
23
|
description:
|
|
24
|
-
|
|
24
|
+
'Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro™',
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
export const prerender =
|
|
28
|
-
export const trailingSlash =
|
|
27
|
+
export const prerender = 'auto';
|
|
28
|
+
export const trailingSlash = 'never';
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* @param {{ url: URL }} param0
|
|
32
32
|
* @returns {{ pathname: string, meta: MetaData }}
|
|
33
33
|
*/
|
|
34
34
|
export function load({ url }) {
|
|
35
|
-
const normalizedPathname = url.pathname.replace(/\/+$/,
|
|
35
|
+
const normalizedPathname = url.pathname.replace(/\/+$/, '') || '/';
|
|
36
36
|
|
|
37
37
|
// Check if meta data for the route exists in `meta.js`, otherwise use the fallback
|
|
38
38
|
const currentMeta = routeMeta[normalizedPathname] || fallbackMeta;
|
|
@@ -9,50 +9,50 @@ This file is part of Network Pro.
|
|
|
9
9
|
<script>
|
|
10
10
|
export let data;
|
|
11
11
|
|
|
12
|
-
import { onMount } from
|
|
13
|
-
import { afterNavigate } from
|
|
14
|
-
import { initPostHog, showReminder, capture } from
|
|
15
|
-
import { registerServiceWorker } from
|
|
16
|
-
import { browser } from
|
|
17
|
-
|
|
18
|
-
import ContainerSection from
|
|
19
|
-
import Footer from
|
|
20
|
-
import HeaderDefault from
|
|
21
|
-
import HeaderHome from
|
|
22
|
-
import PWAInstallButton from
|
|
23
|
-
|
|
24
|
-
import
|
|
25
|
-
import
|
|
26
|
-
|
|
27
|
-
import logoPng from
|
|
28
|
-
import logoWbp from
|
|
29
|
-
import faviconSvg from
|
|
30
|
-
import appleTouchIcon from
|
|
12
|
+
import { onMount } from 'svelte';
|
|
13
|
+
import { afterNavigate } from '$app/navigation';
|
|
14
|
+
import { initPostHog, showReminder, capture } from '$lib/stores/posthog';
|
|
15
|
+
import { registerServiceWorker } from '$lib/registerServiceWorker.js';
|
|
16
|
+
import { browser } from '$app/environment';
|
|
17
|
+
|
|
18
|
+
import ContainerSection from '$lib/components/ContainerSection.svelte';
|
|
19
|
+
import Footer from '$lib/components/layout/Footer.svelte';
|
|
20
|
+
import HeaderDefault from '$lib/components/layout/HeaderDefault.svelte';
|
|
21
|
+
import HeaderHome from '$lib/components/layout/HeaderHome.svelte';
|
|
22
|
+
import PWAInstallButton from '$lib/components/PWAInstallButton.svelte';
|
|
23
|
+
|
|
24
|
+
import '$lib/styles/global.min.css';
|
|
25
|
+
import '$lib/styles/fa-global.css';
|
|
26
|
+
|
|
27
|
+
import logoPng from '$lib/img/logo-web.png';
|
|
28
|
+
import logoWbp from '$lib/img/logo-web.webp';
|
|
29
|
+
import faviconSvg from '$lib/img/favicon.svg';
|
|
30
|
+
import appleTouchIcon from '$lib/img/icon-180x180.png';
|
|
31
31
|
|
|
32
32
|
$: shouldShowReminder = $showReminder;
|
|
33
33
|
|
|
34
34
|
onMount(() => {
|
|
35
|
-
console.log(
|
|
35
|
+
console.log('[APP] onMount triggered in +layout.svelte');
|
|
36
36
|
|
|
37
37
|
registerServiceWorker();
|
|
38
38
|
initPostHog();
|
|
39
39
|
|
|
40
40
|
// Register navigation tracking only on client
|
|
41
41
|
afterNavigate(() => {
|
|
42
|
-
capture(
|
|
42
|
+
capture('$pageview');
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
if (browser) {
|
|
46
|
-
const isDev = import.meta.env.MODE ===
|
|
46
|
+
const isDev = import.meta.env.MODE === 'development';
|
|
47
47
|
|
|
48
48
|
// Check for ?debug=true in URL (no persistence)
|
|
49
49
|
const urlParams = new URLSearchParams(window.location.search);
|
|
50
|
-
const debug = urlParams.get(
|
|
50
|
+
const debug = urlParams.get('debug') === 'true';
|
|
51
51
|
|
|
52
52
|
if (isDev || debug) {
|
|
53
|
-
console.log(
|
|
54
|
-
console.log(
|
|
55
|
-
console.log(
|
|
53
|
+
console.log('ENV MODE =', import.meta.env.MODE);
|
|
54
|
+
console.log('isDev =', isDev);
|
|
55
|
+
console.log('debug param =', debug);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// Preload logo assets
|
|
@@ -65,10 +65,10 @@ This file is part of Network Pro.
|
|
|
65
65
|
|
|
66
66
|
// fallback values if data.meta not set
|
|
67
67
|
const metaTitle =
|
|
68
|
-
data?.meta?.title ||
|
|
68
|
+
data?.meta?.title || 'Security, Networking, Privacy — Network Pro™';
|
|
69
69
|
const metaDescription =
|
|
70
70
|
data?.meta?.description ||
|
|
71
|
-
|
|
71
|
+
'Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro™';
|
|
72
72
|
</script>
|
|
73
73
|
|
|
74
74
|
<svelte:head>
|
|
@@ -88,7 +88,7 @@ This file is part of Network Pro.
|
|
|
88
88
|
<!-- BEGIN HEADER -->
|
|
89
89
|
<header id="header-nav">
|
|
90
90
|
<ContainerSection>
|
|
91
|
-
{#if data.pathname ===
|
|
91
|
+
{#if data.pathname === '/'}
|
|
92
92
|
<!-- Render the Home Header for the root route -->
|
|
93
93
|
<HeaderHome />
|
|
94
94
|
<PWAInstallButton />
|
|
@@ -6,7 +6,7 @@ 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
|
-
import { defaultMeta, meta } from
|
|
9
|
+
import { defaultMeta, meta } from '$lib/meta.js';
|
|
10
10
|
|
|
11
11
|
export const prerender = false;
|
|
12
12
|
|
|
@@ -23,6 +23,6 @@ export const prerender = false;
|
|
|
23
23
|
*/
|
|
24
24
|
export function load() {
|
|
25
25
|
return {
|
|
26
|
-
meta: meta[
|
|
26
|
+
meta: meta['/'] || defaultMeta,
|
|
27
27
|
};
|
|
28
28
|
}
|
package/src/routes/+page.svelte
CHANGED
|
@@ -7,25 +7,25 @@ This file is part of Network Pro.
|
|
|
7
7
|
========================================================================== -->
|
|
8
8
|
|
|
9
9
|
<script>
|
|
10
|
-
import Badges from
|
|
11
|
-
import FullWidthSection from
|
|
12
|
-
import HomeContent from
|
|
13
|
-
import LegalNav from
|
|
14
|
-
import Logo from
|
|
15
|
-
import SocialMedia from
|
|
16
|
-
import MetaTags from
|
|
10
|
+
import Badges from '$lib/components/Badges.svelte';
|
|
11
|
+
import FullWidthSection from '$lib/components/FullWidthSection.svelte';
|
|
12
|
+
import HomeContent from '$lib/pages/HomeContent.svelte';
|
|
13
|
+
import LegalNav from '$lib/components/LegalNav.svelte';
|
|
14
|
+
import Logo from '$lib/components/Logo.svelte';
|
|
15
|
+
import SocialMedia from '$lib/components/SocialMedia.svelte';
|
|
16
|
+
import MetaTags from '$lib/components/MetaTags.svelte';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* @type {string}
|
|
20
20
|
* Style class for the horizontal rule element.
|
|
21
21
|
*/
|
|
22
|
-
const hrStyle =
|
|
22
|
+
const hrStyle = 'hr-styled';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* @type {string}
|
|
26
26
|
* Style class for the div element.
|
|
27
27
|
*/
|
|
28
|
-
const spaceStyle =
|
|
28
|
+
const spaceStyle = 'spacer';
|
|
29
29
|
|
|
30
30
|
export let data;
|
|
31
31
|
</script>
|
|
@@ -6,13 +6,13 @@ 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
|
-
import { defaultMeta, meta } from
|
|
9
|
+
import { defaultMeta, meta } from '$lib/meta.js';
|
|
10
10
|
|
|
11
11
|
export const prerender = false;
|
|
12
12
|
|
|
13
13
|
/** @type {import('./$types').PageServerLoad} */
|
|
14
14
|
export function load() {
|
|
15
15
|
return {
|
|
16
|
-
meta: meta[
|
|
16
|
+
meta: meta['/about'] || defaultMeta,
|
|
17
17
|
};
|
|
18
18
|
}
|