@networkpro/web 1.14.2 → 1.15.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 +78 -1
- package/README.md +6 -4
- package/_redirects +4 -2
- package/cspell.json +2 -0
- package/netlify/edge-functions/csp-report.js +22 -15
- package/package.json +3 -4
- package/scripts/testRedirects.js +84 -0
- package/src/app.html +1 -1
- package/src/lib/components/RedirectPage.svelte +2 -34
- package/src/lib/components/layout/HeaderDefault.svelte +8 -3
- package/src/lib/components/layout/HeaderHome.svelte +8 -3
- package/src/lib/pages/AboutContent.svelte +1 -1
- package/src/lib/pages/HomeContent.svelte +3 -9
- package/src/lib/pages/LicenseContent.svelte +1 -2
- package/src/lib/pages/PrivacyContent.svelte +45 -31
- package/src/lib/pages/PrivacyDashboard.svelte +0 -1
- package/src/lib/pages/TermsConditionsContent.svelte +2 -2
- package/src/lib/stores/trackingPreferences.js +6 -0
- package/src/lib/styles/css/default.css +31 -4
- package/src/lib/styles/global.min.css +1 -1
- package/src/lib/utils/getUTMParams.js +43 -0
- package/src/lib/utils/purify.js +1 -1
- package/src/lib/utils/redirect.js +52 -0
- package/src/lib/utils/utm.js +31 -8
- package/src/routes/consultation/+page.svelte +16 -2
- package/src/routes/contact/+page.svelte +17 -3
- package/src/routes/links/+page.svelte +24 -5
- package/src/routes/posts/+page.svelte +24 -5
- package/src/routes/privacy-rights/+page.svelte +19 -3
- package/tests/unit/{unregisterServiceWorker.test.js → client/lib/unregisterServiceWorker.test.js} +2 -2
- package/tests/unit/client/lib/utils/redirect.test.js +80 -0
- package/tests/unit/client/lib/utils/utm.test.js +59 -0
- package/tests/unit/{routes → client/routes}/page.svelte.test.js +2 -2
- package/tests/unit/{checkEnv.test.js → server/checkEnv.test.js} +2 -2
- package/tests/unit/{checkVersions.test.js → server/checkVersions.test.js} +2 -2
- package/tests/unit/{csp-report.test.js → server/csp-report.test.js} +2 -2
- package/tests/{internal → unit/server/internal}/auditCoverage.test.js +13 -6
- package/tests/unit/{lib → server/lib}/utils/purify.test.js +2 -2
- package/vitest.config.client.js +1 -4
- package/vitest.config.server.js +1 -1
- package/tests/unit/utm.test.js +0 -49
package/CHANGELOG.md
CHANGED
|
@@ -22,6 +22,82 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
|
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
+
## [1.15.0] - 2025-07-01
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- `redirect.js` utility to handle browser-aware redirects with fallback logic for Firefox.
|
|
30
|
+
- Unit test for `redirect.js` under `tests/unit/client/lib/utils/redirect.test.js`.
|
|
31
|
+
- `/consultation` redirect route to `utm.js` UTM-tracking logic.
|
|
32
|
+
- Redirect from `/foss` to `/foss-spotlight` in `_redirects`.
|
|
33
|
+
- `scripts/testRedirect.js` to verify Netlify/SvelteKit trailing slash redirect behavior.
|
|
34
|
+
- `test:redirects` script in package.json to trigger `scripts/testRedirects.js`
|
|
35
|
+
- Logic to suppress `rel="noopener noreferrer"` on internal redirects in `HeaderHome.svelte` and `HeaderDefault.svelte`
|
|
36
|
+
- `redirect` flag to navigation metadata to distinguish internal redirect behavior in `HeaderHome.svelte` and `HeaderDefault.svelte`
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- Bumped version to **v1.15.0**
|
|
41
|
+
- Restructured unit tests:
|
|
42
|
+
- Moved `purify.test.js` to `tests/unit/client/lib/utils/`
|
|
43
|
+
- Moved `utm.test.js` to `tests/unit/client/lib/utils/`
|
|
44
|
+
- Moved `unregisterServiceWorker.test.js` to `tests/unit/client/lib/utils/`
|
|
45
|
+
- Moved `page.svelte.test.js` to `tests/unit/client/routes/`
|
|
46
|
+
- Moved `checkEnv.test.js`, `checkVersions.test.js`, and `csp-report.test.js` to `tests/unit/server/`
|
|
47
|
+
- Moved `auditCoverage.test.js` to `tests/unit/server/internal/`
|
|
48
|
+
- Refactored `_redirects` file:
|
|
49
|
+
- Removed trailing slashes to match SvelteKit/Netlify conventions.
|
|
50
|
+
- Updated `RedirectPage.svelte` to use `redirectWithBrowserAwareness()` for better cross-browser redirect behavior.
|
|
51
|
+
- Refactored all relevant `+page.svelte` files to remove local redirect timeouts and centralize logic in `RedirectPage`.
|
|
52
|
+
- Updated `vitest.config.client.js` and `vitest.config.server.js` to:
|
|
53
|
+
- Reflect new directory structure
|
|
54
|
+
- Properly assign `jsdom` for client-side tests and `node` for server-side tests
|
|
55
|
+
- `/consultation`, `/contact`, `/links`, `/posts`, and `/privacy-rights` `+page.svelte` files updated to capture UTM parameters in a privacy-preserving manner.
|
|
56
|
+
- Moved inline styles from `RedirectPage.svelte` to `src/lib/styles/css/default.css`, including `@keyframes spin` animation used by `.loading-spinner`
|
|
57
|
+
- Removed unnecessary `rel` attribute from internal links in `AboutContent.svelte`, `LicenseContent.svelte`, and `PrivacyDashboard.svelte`
|
|
58
|
+
- Updated project README with revised directory structure reflecting separate client/server test folders.
|
|
59
|
+
- Upgraded dependencies:
|
|
60
|
+
- `globals` `^16.2.0` → `^16.3.0`
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
|
|
64
|
+
- Firefox-specific issue where delayed `window.location.replace()` triggered a new tab instead of redirecting in the same window — now handled by bypassing the delay in Firefox.
|
|
65
|
+
- Prevented server-context tests from breaking due to `window` usage by scoping them to client-only environments.
|
|
66
|
+
|
|
67
|
+
## Removed
|
|
68
|
+
|
|
69
|
+
- `head:flatten` and `head:validate` scripts in package.json, as the `_headers` file has been deprecated
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## [1.14.3] - 2025-06-30
|
|
74
|
+
|
|
75
|
+
### Added
|
|
76
|
+
|
|
77
|
+
- Manual event capture for redirect pages using PostHog, with automatic UTM parameter extraction
|
|
78
|
+
- Utility function `getUTMParams` for parsing UTM query values from URLs
|
|
79
|
+
- `trackingEnabled` named export from `trackingPreferences.js` for cleaner consumption
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
|
|
83
|
+
- Bumped version to **v1.14.3**
|
|
84
|
+
- Refactored redirect logic in multiple pages to integrate UTM-aware analytics
|
|
85
|
+
- All redirect pages now consistently open in a new browser tab using `<a>` fallback
|
|
86
|
+
- Enhanced `utm.js` logic to support campaign identification for `/contact`, `/links`, `/posts`, and `/privacy-rights`
|
|
87
|
+
- Updated `generator` metadata in `app.html` to `SvelteKit 2.22.2`
|
|
88
|
+
- Modified `HomeContent.svelte` to use app constant for blog link
|
|
89
|
+
- Removed inline styles from redirect pages and integrated them into the main stylesheet
|
|
90
|
+
- Renamed "Data Sharing" section in Privacy Policy to "Legal Requests and Data Disclosure"
|
|
91
|
+
- Expanded the above section to strengthen users' legal rights and privacy protections
|
|
92
|
+
- Updated Privacy Policy effective date to June 30, 2025
|
|
93
|
+
|
|
94
|
+
### Fixed
|
|
95
|
+
|
|
96
|
+
- Reinstated filtering logic in `csp-report.js` to suppress low-value or noisy CSP violations
|
|
97
|
+
- Resolved `ReferenceError` in `utm.test.js` by reordering mocked imports for `$app/environment` and `$app/stores` to comply with Vitest's hoisting behavior
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
25
101
|
## [1.14.2] - 2025-06-30
|
|
26
102
|
|
|
27
103
|
### Added
|
|
@@ -539,7 +615,8 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
|
|
|
539
615
|
|
|
540
616
|
<!-- Link references -->
|
|
541
617
|
|
|
542
|
-
[Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.
|
|
618
|
+
[Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.15.0...HEAD
|
|
619
|
+
[1.15.0]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.15.0
|
|
543
620
|
[1.14.2]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.14.2
|
|
544
621
|
[1.14.1]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.14.1
|
|
545
622
|
[1.14.0]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.14.0
|
package/README.md
CHANGED
|
@@ -92,10 +92,12 @@ This project follows the principles of [Keep a Changelog](https://keepachangelog
|
|
|
92
92
|
│ ├── robots.txt # SEO: allow/disallow crawlers
|
|
93
93
|
│ └── sitemap.xml # SEO: full site map
|
|
94
94
|
├── tests/
|
|
95
|
-
│ ├── e2e/
|
|
96
|
-
│
|
|
97
|
-
│
|
|
98
|
-
│
|
|
95
|
+
│ ├── e2e/ # Playwright end-to-end tests
|
|
96
|
+
│ └── unit/ # Vitest unit tests
|
|
97
|
+
│ ├── client/ # Client-side (jsdom) unit tests
|
|
98
|
+
│ ├── server/ # Server-side (node) unit tests
|
|
99
|
+
│ │ └── internal/ # Internal audit/test helpers
|
|
100
|
+
│ │ └── auditCoverage.test.js # Warns about untested source modules
|
|
99
101
|
├── _redirects # Netlify redirect rules
|
|
100
102
|
├── CHANGELOG.md # Chronological record of notable project changes
|
|
101
103
|
├── netlify.toml # Netlify configuration
|
package/_redirects
CHANGED
|
@@ -3,13 +3,15 @@ https://www.netwk.pro/* https://netwk.pro/:splat 301
|
|
|
3
3
|
|
|
4
4
|
# Redirect /privacy-policy (and variants) to /privacy
|
|
5
5
|
/privacy-policy /privacy 301
|
|
6
|
-
/privacy-policy/ /privacy 301
|
|
7
6
|
/privacy-policy/* /privacy/:splat 301
|
|
8
7
|
|
|
9
8
|
# Redirect /legal (and variants) to /license
|
|
10
9
|
/legal /license 301
|
|
11
|
-
/legal/ /license 301
|
|
12
10
|
/legal/* /license/:splat 301
|
|
13
11
|
|
|
12
|
+
# Redirect /foss (and variants) to /foss-spotlight
|
|
13
|
+
/foss /foss-spotlight 301
|
|
14
|
+
/foss/* /foss-spotlight/:splat 301
|
|
15
|
+
|
|
14
16
|
# Redirect for Netlify function proxy
|
|
15
17
|
/api/* /.netlify/functions/:splat 200
|
package/cspell.json
CHANGED
|
@@ -43,20 +43,25 @@ export default async (request, _context) => {
|
|
|
43
43
|
const violated = report['violated-directive'] ?? '';
|
|
44
44
|
const blockedUri = report['blocked-uri'] ?? '';
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
]
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
46
|
+
// Filter: Skip noisy or unactionable reports
|
|
47
|
+
const ignored = [
|
|
48
|
+
violated.startsWith('img-src'),
|
|
49
|
+
blockedUri === '',
|
|
50
|
+
blockedUri === 'eval',
|
|
51
|
+
blockedUri === 'about',
|
|
52
|
+
blockedUri.startsWith('chrome-extension://'),
|
|
53
|
+
blockedUri.startsWith('moz-extension://'),
|
|
54
|
+
!report['source-file'],
|
|
55
|
+
!report['document-uri'],
|
|
56
|
+
].some(Boolean);
|
|
57
|
+
|
|
58
|
+
if (ignored) {
|
|
59
|
+
console.log('[CSP-Edge] Ignored low-value violation:', {
|
|
60
|
+
directive: violated,
|
|
61
|
+
uri: blockedUri,
|
|
62
|
+
});
|
|
63
|
+
return new Response(null, { status: 204 });
|
|
64
|
+
}
|
|
60
65
|
|
|
61
66
|
// Send alert for high-risk directives
|
|
62
67
|
await sendToNtfy(violated, blockedUri, report);
|
|
@@ -97,7 +102,9 @@ async function sendToNtfy(violated, blockedUri, report) {
|
|
|
97
102
|
|
|
98
103
|
const directiveKey = violated.split(' ')[0]; // strip fallback values or sources
|
|
99
104
|
const isHighRisk = highRiskDirectives.includes(directiveKey);
|
|
100
|
-
console.log(
|
|
105
|
+
console.log(
|
|
106
|
+
`[CSP-Edge] Directive ${directiveKey} is ${isHighRisk ? '' : 'not '}high-risk`,
|
|
107
|
+
);
|
|
101
108
|
if (!isHighRisk) return;
|
|
102
109
|
|
|
103
110
|
const key = `${violated}|${blockedUri}`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@networkpro/web",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.15.0",
|
|
5
5
|
"description": "Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro Strategies",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"advisory",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"test:watch": "vitest --config vitest.config.client.js --watch",
|
|
61
61
|
"test:coverage": "npm run test:client -- --run --coverage && npm run test:server -- --run --coverage",
|
|
62
62
|
"test:e2e": "npx playwright test --retries=1",
|
|
63
|
+
"test:redirects": "node scripts/testRedirects.js",
|
|
63
64
|
"coverage:client": "node scripts/openReport.js client",
|
|
64
65
|
"coverage:server": "node scripts/openReport.js server",
|
|
65
66
|
"coverage:open": "npm run coverage:client && npm run coverage:server",
|
|
@@ -74,8 +75,6 @@
|
|
|
74
75
|
"lhci": "lhci",
|
|
75
76
|
"lhci:run": "lhci autorun --config=.lighthouserc.cjs",
|
|
76
77
|
"audit:coverage": "vitest run tests/internal/auditCoverage.test.js",
|
|
77
|
-
"head:flatten": "node scripts/flattenHeaders.js",
|
|
78
|
-
"head:validate": "node scripts/validateHeaders.js",
|
|
79
78
|
"postinstall": "npm run check:node"
|
|
80
79
|
},
|
|
81
80
|
"dependencies": {
|
|
@@ -101,7 +100,7 @@
|
|
|
101
100
|
"eslint-config-prettier": "^10.1.5",
|
|
102
101
|
"eslint-plugin-jsdoc": "^51.3.1",
|
|
103
102
|
"eslint-plugin-svelte": "^3.10.1",
|
|
104
|
-
"globals": "^16.
|
|
103
|
+
"globals": "^16.3.0",
|
|
105
104
|
"jsdom": "^26.1.0",
|
|
106
105
|
"lightningcss": "^1.30.1",
|
|
107
106
|
"markdownlint": "^0.38.0",
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/* ==========================================================================
|
|
2
|
+
scripts/testRedirects.js
|
|
3
|
+
|
|
4
|
+
Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
5
|
+
SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
6
|
+
This file is part of Network Pro.
|
|
7
|
+
========================================================================== */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @file testRedirects.js
|
|
11
|
+
* @description Tests Netlify redirects against actual endpoints to verify
|
|
12
|
+
* trailing-slash behavior.
|
|
13
|
+
*
|
|
14
|
+
* @module scripts/
|
|
15
|
+
* @author SunDevil311
|
|
16
|
+
* @updated 2025-07-01
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import https from 'https';
|
|
20
|
+
import { URL } from 'url';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {object} RedirectTest
|
|
24
|
+
* @property {string} from - The source URL to test.
|
|
25
|
+
* @property {string} to - The expected destination URL.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/** @type {RedirectTest[]} */
|
|
29
|
+
const urls = [
|
|
30
|
+
{ from: 'https://netwk.pro/privacy-policy', to: 'https://netwk.pro/privacy' },
|
|
31
|
+
{
|
|
32
|
+
from: 'https://netwk.pro/privacy-policy/',
|
|
33
|
+
to: 'https://netwk.pro/privacy',
|
|
34
|
+
},
|
|
35
|
+
{ from: 'https://netwk.pro/foss', to: 'https://netwk.pro/foss-spotlight' },
|
|
36
|
+
{ from: 'https://netwk.pro/foss/', to: 'https://netwk.pro/foss-spotlight' },
|
|
37
|
+
{
|
|
38
|
+
from: 'https://www.netwk.pro/foss',
|
|
39
|
+
to: 'https://netwk.pro/foss-spotlight',
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Tests a single redirect by making a GET request and checking the status code and location header.
|
|
45
|
+
* @param {RedirectTest} redirect - The redirect configuration to test.
|
|
46
|
+
* @returns {Promise<boolean>} - Resolves to true if the redirect is correct, false otherwise.
|
|
47
|
+
*/
|
|
48
|
+
function testRedirect({ from, to }) {
|
|
49
|
+
return new Promise((resolve) => {
|
|
50
|
+
const req = https.request(new URL(from), { method: 'GET' }, (res) => {
|
|
51
|
+
const location = res.headers.location;
|
|
52
|
+
const expectedPath = new URL(to).pathname;
|
|
53
|
+
|
|
54
|
+
if (res.statusCode === 301 && location === expectedPath) {
|
|
55
|
+
console.log(`✅ ${from} → ${location}`);
|
|
56
|
+
resolve(true);
|
|
57
|
+
} else {
|
|
58
|
+
console.error(
|
|
59
|
+
`❌ ${from} → Expected 301 to ${expectedPath}, got ${res.statusCode} to ${location}`,
|
|
60
|
+
);
|
|
61
|
+
resolve(false);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
req.on('error', (err) => {
|
|
66
|
+
console.error(`❌ ${from} → Network error: ${err.message}`);
|
|
67
|
+
resolve(false);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
req.end();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Runs all redirect tests and exits the process with a status code reflecting success or failure.
|
|
76
|
+
* @returns {Promise<void>}
|
|
77
|
+
*/
|
|
78
|
+
const runTests = async () => {
|
|
79
|
+
const results = await Promise.all(urls.map(testRedirect));
|
|
80
|
+
const failed = results.filter((r) => !r).length;
|
|
81
|
+
process.exit(failed > 0 ? 1 : 0);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
runTests();
|
package/src/app.html
CHANGED
|
@@ -8,6 +8,7 @@ This file is part of Network Pro.
|
|
|
8
8
|
|
|
9
9
|
<script>
|
|
10
10
|
import { onMount } from 'svelte';
|
|
11
|
+
import { redirectWithBrowserAwareness } from '$lib/utils/redirect.js';
|
|
11
12
|
import FullWidthSection from '$lib/components/FullWidthSection.svelte';
|
|
12
13
|
|
|
13
14
|
export let to;
|
|
@@ -15,16 +16,7 @@ This file is part of Network Pro.
|
|
|
15
16
|
export let delay = 3;
|
|
16
17
|
|
|
17
18
|
onMount(() => {
|
|
18
|
-
|
|
19
|
-
console.warn('⛔ No redirect target provided');
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
console.log('✅ Starting redirect to:', to);
|
|
24
|
-
|
|
25
|
-
setTimeout(() => {
|
|
26
|
-
window.location.href = to;
|
|
27
|
-
}, delay * 1000);
|
|
19
|
+
redirectWithBrowserAwareness(to, delay);
|
|
28
20
|
});
|
|
29
21
|
</script>
|
|
30
22
|
|
|
@@ -47,27 +39,3 @@ This file is part of Network Pro.
|
|
|
47
39
|
</FullWidthSection>
|
|
48
40
|
|
|
49
41
|
<!-- END MAIN CONTENT -->
|
|
50
|
-
|
|
51
|
-
<style>
|
|
52
|
-
.redirect-content {
|
|
53
|
-
text-align: center;
|
|
54
|
-
font-family: system-ui, sans-serif;
|
|
55
|
-
margin-top: 2rem; /* adjust as needed */
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.loading-spinner {
|
|
59
|
-
width: 48px;
|
|
60
|
-
height: 48px;
|
|
61
|
-
margin: 2rem auto;
|
|
62
|
-
border: 4px solid #ddd;
|
|
63
|
-
animation: spin 1s linear infinite;
|
|
64
|
-
border-radius: 50%;
|
|
65
|
-
border-top: 4px solid #ffc627;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
@keyframes spin {
|
|
69
|
-
to {
|
|
70
|
-
transform: rotate(360deg);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
</style>
|
|
@@ -22,6 +22,8 @@ This file is part of Network Pro.
|
|
|
22
22
|
const lhubLink = `${base}/links`;
|
|
23
23
|
const fossLink = `${base}/foss-spotlight`;
|
|
24
24
|
const blogLink = 'https://blog.netwk.pro';
|
|
25
|
+
const discussLink =
|
|
26
|
+
'https://github.com/netwk-pro/netwk-pro.github.io/discussions';
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* Navigation link object.
|
|
@@ -30,6 +32,7 @@ This file is part of Network Pro.
|
|
|
30
32
|
* @property {string} href - The URL or anchor the link points to.
|
|
31
33
|
* @property {string} target - Specifies where to open the link (e.g., "_self" or "_blank").
|
|
32
34
|
* @property {boolean} external - Whether the link points to an external resource.
|
|
35
|
+
* @property {boolean} [redirect=false] - Indicates whether the external link is actually an internal redirect.
|
|
33
36
|
*/
|
|
34
37
|
|
|
35
38
|
/**
|
|
@@ -48,15 +51,17 @@ This file is part of Network Pro.
|
|
|
48
51
|
},
|
|
49
52
|
{
|
|
50
53
|
label: 'discussions',
|
|
51
|
-
href:
|
|
54
|
+
href: discussLink,
|
|
52
55
|
target: PAGE.BLANK,
|
|
53
56
|
external: true,
|
|
57
|
+
redirect: false,
|
|
54
58
|
},
|
|
55
59
|
{
|
|
56
60
|
label: 'link hub',
|
|
57
61
|
href: lhubLink,
|
|
58
62
|
target: PAGE.BLANK,
|
|
59
63
|
external: true,
|
|
64
|
+
redirect: true,
|
|
60
65
|
},
|
|
61
66
|
];
|
|
62
67
|
|
|
@@ -69,8 +74,8 @@ This file is part of Network Pro.
|
|
|
69
74
|
|
|
70
75
|
<!-- BEGIN DEFAULT HEADER -->
|
|
71
76
|
<nav class="center-nav" aria-label="Site navigation">
|
|
72
|
-
{#each nav as { label, href, target, external }, index}
|
|
73
|
-
<a {href} {target} rel={external ? rel : undefined}>
|
|
77
|
+
{#each nav as { label, href, target, external, redirect }, index}
|
|
78
|
+
<a {href} {target} rel={!redirect && external ? rel : undefined}>
|
|
74
79
|
{label}
|
|
75
80
|
</a>
|
|
76
81
|
{#if external}
|
|
@@ -21,6 +21,8 @@ This file is part of Network Pro.
|
|
|
21
21
|
const fossLink = `${base}/foss-spotlight`;
|
|
22
22
|
const lhubLink = `${base}/links`;
|
|
23
23
|
const blogLink = 'https://blog.netwk.pro';
|
|
24
|
+
const discussLink =
|
|
25
|
+
'https://github.com/netwk-pro/netwk-pro.github.io/discussions';
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
28
|
* Navigation link object.
|
|
@@ -29,6 +31,7 @@ This file is part of Network Pro.
|
|
|
29
31
|
* @property {string} href - The URL or anchor the link points to.
|
|
30
32
|
* @property {string} target - Specifies where to open the link (e.g., "_self" or "_blank").
|
|
31
33
|
* @property {boolean} external - Whether the link points to an external resource.
|
|
34
|
+
* @property {boolean} [redirect=false] - Indicates whether the external link is actually an internal redirect.
|
|
32
35
|
*/
|
|
33
36
|
|
|
34
37
|
/**
|
|
@@ -46,15 +49,17 @@ This file is part of Network Pro.
|
|
|
46
49
|
},
|
|
47
50
|
{
|
|
48
51
|
label: 'discussions',
|
|
49
|
-
href:
|
|
52
|
+
href: discussLink,
|
|
50
53
|
target: PAGE.BLANK,
|
|
51
54
|
external: true,
|
|
55
|
+
redirect: false,
|
|
52
56
|
},
|
|
53
57
|
{
|
|
54
58
|
label: 'link hub',
|
|
55
59
|
href: lhubLink,
|
|
56
60
|
target: PAGE.BLANK,
|
|
57
61
|
external: true,
|
|
62
|
+
redirect: true,
|
|
58
63
|
},
|
|
59
64
|
];
|
|
60
65
|
|
|
@@ -67,8 +72,8 @@ This file is part of Network Pro.
|
|
|
67
72
|
|
|
68
73
|
<!-- BEGIN HOME HEADER -->
|
|
69
74
|
<nav class="center-nav" aria-label="Homepage navigation">
|
|
70
|
-
{#each nav as { label, href, target, external }, index}
|
|
71
|
-
<a {href} {target} rel={external ? rel : undefined}>
|
|
75
|
+
{#each nav as { label, href, target, external, redirect }, index}
|
|
76
|
+
<a {href} {target} rel={!redirect && external ? rel : undefined}>
|
|
72
77
|
{label}
|
|
73
78
|
</a>
|
|
74
79
|
{#if external}
|
|
@@ -217,7 +217,7 @@ This file is part of Network Pro.
|
|
|
217
217
|
<div class="spacer"></div>
|
|
218
218
|
|
|
219
219
|
<p>
|
|
220
|
-
<a
|
|
220
|
+
<a href={contactLink} target={PAGE.BLANK}>Let's connect</a>
|
|
221
221
|
to discuss how we can help secure and strengthen your business today.
|
|
222
222
|
</p>
|
|
223
223
|
|
|
@@ -15,7 +15,7 @@ This file is part of Network Pro.
|
|
|
15
15
|
|
|
16
16
|
//console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
|
|
17
17
|
|
|
18
|
-
const { COMPANY_INFO, PAGE, NAV } = CONSTANTS;
|
|
18
|
+
const { COMPANY_INFO, LINKS, PAGE, NAV } = CONSTANTS;
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* URL to the FOSS Spotlight page, using the base path
|
|
@@ -23,12 +23,6 @@ This file is part of Network Pro.
|
|
|
23
23
|
*/
|
|
24
24
|
const spotlightLink = `${base}/foss-spotlight`;
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
* URL to the external blog
|
|
28
|
-
* @type {string}
|
|
29
|
-
*/
|
|
30
|
-
const blogLink = 'https://blog.netwk.pro';
|
|
31
|
-
|
|
32
26
|
/**
|
|
33
27
|
* CSS class for the index headings.
|
|
34
28
|
* @type {string}
|
|
@@ -69,7 +63,7 @@ This file is part of Network Pro.
|
|
|
69
63
|
📡
|
|
70
64
|
<em>
|
|
71
65
|
<strong>Stay informed:</strong> Follow our
|
|
72
|
-
<a href={
|
|
66
|
+
<a href={LINKS.BLOG} target={PAGE.SELF}>blog</a>
|
|
73
67
|
and social channels for actionable insights, implementation guides, and the latest
|
|
74
68
|
cybersecurity developments.
|
|
75
69
|
</em>
|
|
@@ -81,7 +75,7 @@ This file is part of Network Pro.
|
|
|
81
75
|
|
|
82
76
|
<p class={classLarge}>
|
|
83
77
|
<strong>
|
|
84
|
-
<a href={
|
|
78
|
+
<a href={LINKS.BLOG} target={PAGE.SELF}>{COMPANY_INFO.APP_NAME} Blog</a>
|
|
85
79
|
</strong>
|
|
86
80
|
</p>
|
|
87
81
|
|
|
@@ -487,8 +487,7 @@ This file is part of Network Pro.
|
|
|
487
487
|
{:else if link.id === 'contact'}
|
|
488
488
|
<p>
|
|
489
489
|
The Company can be contacted via our
|
|
490
|
-
<a
|
|
491
|
-
>Contact Form</a>
|
|
490
|
+
<a href={contactLink} target={PAGE.BLANK}>Contact Form</a>
|
|
492
491
|
or by email at:<br />
|
|
493
492
|
📧 <strong>{CONTACT.EMAIL}</strong>
|
|
494
493
|
</p>
|