@networkpro/web 1.13.4 → 1.13.6
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 +60 -1
- package/README.md +2 -101
- package/bootstrap.local.sh +88 -0
- package/cspell.json +1 -0
- package/netlify/edge-functions/csp-report.js +13 -11
- package/package.json +3 -3
- package/src/lib/components/RedirectPage.svelte +4 -1
- package/src/lib/components/layout/HeaderDefault.svelte +16 -8
- package/src/lib/components/layout/HeaderHome.svelte +15 -7
- package/src/lib/pages/AboutContent.svelte +2 -2
- package/src/lib/pages/PGPContent.svelte +8 -6
- package/src/lib/styles/css/default.css +10 -5
- package/src/lib/styles/css/style.css +10 -14
- package/src/lib/styles/global.min.css +1 -1
- package/src/routes/links/+page.svelte +33 -0
- package/src/routes/posts/+page.svelte +33 -0
- package/stylelint.config.js +6 -0
- package/tests/unit/demo.test.js +0 -15
package/CHANGELOG.md
CHANGED
|
@@ -22,6 +22,62 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
|
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
+
## [1.13.6] - 2025-06-15
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- Introduced `.github/workflows/check-codeql.yml` reusable workflow to validate successful CodeQL analysis during CI
|
|
30
|
+
- Added `.github/workflows/templates/check-codeql.template.yml` for documentation and workflow templating purposes
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Replaced inline `check-codeql` job in `.github/workflows/build-and-publish.yml` with call to reusable workflow
|
|
35
|
+
- Updated `.node-version` and `.nvmrc` from `24.1.0` → `24.2.0` to reflect upgraded Node.js binary
|
|
36
|
+
- Replaced `ℹ️` symbol with `🛈` in `bootstrap.local.sh` to improve clarity in terminals
|
|
37
|
+
- Version bumped to **v1.13.6**
|
|
38
|
+
- Upgraded dependencies:
|
|
39
|
+
- `posthog-js` updated from `1.252.0` → `1.252.1`
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## [1.13.5] - 2025-06-14
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
|
|
47
|
+
- Introduced `links/` and `posts/` redirect routes for improved navigation and backward compatibility
|
|
48
|
+
- Added `proton-img` and `qrcode-img` utility classes to global stylesheet to eliminate inline styles in `PGPContent.svelte`
|
|
49
|
+
- Set `decoding="sync"` and `loading="eager"` on the first QR code image and the Proton Mail badge to improve perceived load performance and visual smoothness
|
|
50
|
+
- Added `rel="noopener noreferrer"` support to `RedirectPage.svelte`, now used by the new `/links` and `/posts` routes
|
|
51
|
+
- Revised `obtainium-img` class in stylesheets to improve Obtainium image rendering on mobile and enhance overall clarity
|
|
52
|
+
- Added a new `scripts/bootstrap.local.sh` script to streamline local development setup, including OS detection and Playwright dependencies
|
|
53
|
+
- Added a new “Environment Requirements” Wiki page to consolidate Node version constraints, setup instructions, and local dev tooling guidance
|
|
54
|
+
- Replaced the detailed "Getting Started" section in `README.md` with a concise reference to the Wiki and a minimal quickstart snippet
|
|
55
|
+
|
|
56
|
+
### Changed
|
|
57
|
+
|
|
58
|
+
- Promoted Node.js and npm version enforcement details from README to the Wiki for centralized documentation
|
|
59
|
+
- Removed low-priority CSP report filtering in `csp-report.js` to allow all violations to be logged and reviewed
|
|
60
|
+
- Reordered CSS rules to resolve `no-descending-specificity` warnings triggered by focus selectors
|
|
61
|
+
- Updated `HeaderHome.svelte` and `HeaderDefault.svelte` to use `PAGE.SELF` and `PAGE.BLANK` constants for target behavior
|
|
62
|
+
- Updated `AboutContent.svelte` to use application constant instead of hardcoded value
|
|
63
|
+
- Removed unused `COMPANY_INFO` destructured constant from `PGPContent.svelte`
|
|
64
|
+
- Upgraded dependencies:
|
|
65
|
+
- `svelte` updated from `5.34.1` → `5.34.3`
|
|
66
|
+
- Fixed schema warning in GitHub issue template by replacing `assignees: []` with `assignees: SunDevil311`
|
|
67
|
+
- Version bumped to **v1.13.5**
|
|
68
|
+
|
|
69
|
+
### Fixed
|
|
70
|
+
|
|
71
|
+
- Restored consistent `:visited` link color by forcing `color: #cba557 !important` across all visited interaction states
|
|
72
|
+
- Prevented gold-on-gold text issue when focusing visited links
|
|
73
|
+
- Rolled back enhanced `:focus-visible` styles to resolve flicker and override conflicts during fast navigation
|
|
74
|
+
|
|
75
|
+
### Removed
|
|
76
|
+
|
|
77
|
+
- Removed unneeded demo unit test (`demo.test.js`) from `tests/unit`
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
25
81
|
## [1.13.4] - 2025-06-13
|
|
26
82
|
|
|
27
83
|
### Changed
|
|
@@ -386,7 +442,8 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
|
|
|
386
442
|
|
|
387
443
|
<!-- Link references -->
|
|
388
444
|
|
|
389
|
-
[Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.13.
|
|
445
|
+
[Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.13.5...HEAD
|
|
446
|
+
[1.13.5]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.13.5
|
|
390
447
|
[1.13.4]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.13.4
|
|
391
448
|
[1.13.3]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.13.3
|
|
392
449
|
[1.13.2]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.13.2
|
|
@@ -400,3 +457,5 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
|
|
|
400
457
|
[1.12.4]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.12.4
|
|
401
458
|
[1.12.3]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.12.3
|
|
402
459
|
[1.12.1]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.12.1
|
|
460
|
+
|
|
461
|
+
<!-- cspell:ignore qrcode -->
|
package/README.md
CHANGED
|
@@ -156,113 +156,14 @@ tests/
|
|
|
156
156
|
|
|
157
157
|
## 🛠 Getting Started
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
For full setup guidance, including environment setup, version enforcement, and local tooling, refer to the 📚 [Environment Requirements Wiki](https://github.com/netwk-pro/netwk-pro.github.io/wiki/Environment-Requirements).
|
|
160
160
|
|
|
161
161
|
```bash
|
|
162
162
|
git clone https://github.com/netwk-pro/netwk-pro.github.io.git
|
|
163
163
|
cd netwk-pro.github.io
|
|
164
164
|
cp .env.template .env
|
|
165
165
|
npm install
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
Edit .env to configure your environment mode:
|
|
169
|
-
|
|
170
|
-
```env
|
|
171
|
-
ENV_MODE=dev # Options: dev, test, ci, preview, prod
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
> `ENV_MODE` is used for tooling and workflows — not by SvelteKit itself.
|
|
175
|
-
> Use `VITE_`-prefixed env variables for runtime values.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
### 🧰 Local Setup Scripts
|
|
180
|
-
|
|
181
|
-
To streamline onboarding and enforce project conventions, you may use the optional helper scripts:
|
|
182
|
-
|
|
183
|
-
<!-- FIXME: Create a bootstrap.local.sh file -->
|
|
184
|
-
|
|
185
|
-
| File/Script | Description |
|
|
186
|
-
| ---------------------------------- | --------------------------------------------------------------------------------- |
|
|
187
|
-
| `.env.template` | Template for local environment variables |
|
|
188
|
-
| `scripts/checkNode.js` | Validates your Node.js and npm versions |
|
|
189
|
-
| `scripts/bootstrap.local.sh` (TBD) | Interactive setup for local configuration and tooling |
|
|
190
|
-
| `.vscode/` | Editor recommendations compatible with [VSCodium](https://vscodium.com) / VS Code |
|
|
191
|
-
|
|
192
|
-
To get started quickly:
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
cp .env.template .env
|
|
196
|
-
npm install
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
> You can also use `bootstrap.local.sh` to automate the steps above and more (optional).
|
|
200
|
-
> `ENV_MODE` controls local tooling behavior — it is not used by the app runtime directly.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
### 💾 Version Enforcement
|
|
205
|
-
|
|
206
|
-
To ensure consistent environments across contributors and CI systems, this project enforces specific Node.js and npm versions via the `"engines"` field in `package.json`:
|
|
207
|
-
|
|
208
|
-
```json
|
|
209
|
-
"engines": {
|
|
210
|
-
"node": ">=22.0.0 <25",
|
|
211
|
-
"npm": ">=11.0.0 <12"
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
Version compliance is **softly enforced** after installation via a postinstall lifecycle hook:
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
npm run check:node
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
This script runs `scripts/checkNode.js`, which compares your current Node.js and npm versions against the required ranges. During the install phase, it will log **warnings** for out-of-range versions but allow installation to continue. In all other contexts (manual runs, CI workflows, etc.), it will **fail** with a descriptive error if the versions are out of spec.
|
|
222
|
-
|
|
223
|
-
**_Node Version Check (snippet from `scripts/checkNode.js`)_**
|
|
224
|
-
|
|
225
|
-
```javascript
|
|
226
|
-
const semver = require('semver');
|
|
227
|
-
const { engines } = require('../package.json');
|
|
228
|
-
|
|
229
|
-
const requiredNode = engines.node;
|
|
230
|
-
const requiredNpm = engines.npm;
|
|
231
|
-
const isPostInstall = process.env.npm_lifecycle_event === 'postinstall';
|
|
232
|
-
|
|
233
|
-
let hasError = false;
|
|
234
|
-
|
|
235
|
-
if (!semver.satisfies(process.version, requiredNode)) {
|
|
236
|
-
const msg = `Node.js ${process.version} does not satisfy required range: ${requiredNode}`;
|
|
237
|
-
isPostInstall ? console.warn(`⚠️ ${msg}`) : console.error(`❌ ${msg}`);
|
|
238
|
-
if (!isPostInstall) hasError = true;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const npmVersion = require('child_process')
|
|
242
|
-
.execSync('npm -v')
|
|
243
|
-
.toString()
|
|
244
|
-
.trim();
|
|
245
|
-
|
|
246
|
-
if (!semver.satisfies(npmVersion, requiredNpm)) {
|
|
247
|
-
const msg = `npm ${npmVersion} does not satisfy required range: ${requiredNpm}`;
|
|
248
|
-
isPostInstall ? console.warn(`⚠️ ${msg}`) : console.error(`❌ ${msg}`);
|
|
249
|
-
if (!isPostInstall) hasError = true;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (!hasError) {
|
|
253
|
-
console.log('✅ Node and npm versions are valid.');
|
|
254
|
-
} else {
|
|
255
|
-
process.exit(1);
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
For full compatibility, `.nvmrc` and `.node-version` files are provided to work seamlessly with version managers like nvm, asdf, and Volta. This ensures consistent environments across local development, CI pipelines, and deployment targets.
|
|
260
|
-
|
|
261
|
-
To manually verify your environment:
|
|
262
|
-
|
|
263
|
-
```bash
|
|
264
|
-
node -v # Should fall within engines.node
|
|
265
|
-
npm -v # Should fall within engines.npm
|
|
166
|
+
npx playwright install
|
|
266
167
|
```
|
|
267
168
|
|
|
268
169
|
</section>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Copyright © 2025 Network Pro Strategies (Network Pro™)
|
|
4
|
+
# SPDX-License-Identifier: CC-BY-4.0 OR GPL-3.0-or-later
|
|
5
|
+
# This file is part of Network Pro
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
echo "🛠 Bootstrapping local development environment..."
|
|
10
|
+
|
|
11
|
+
# Detect OS using uname
|
|
12
|
+
OS="$(uname -s)"
|
|
13
|
+
|
|
14
|
+
# Match OS string to normalized platform label
|
|
15
|
+
case "$OS" in
|
|
16
|
+
Linux*) PLATFORM="linux";;
|
|
17
|
+
Darwin*) PLATFORM="mac";;
|
|
18
|
+
MINGW*|CYGWIN*|MSYS*) PLATFORM="windows";; # Git Bash or similar
|
|
19
|
+
*) PLATFORM="unknown";;
|
|
20
|
+
esac
|
|
21
|
+
|
|
22
|
+
echo "🧭 Detected platform: $PLATFORM"
|
|
23
|
+
|
|
24
|
+
# Exit early for unsupported environments
|
|
25
|
+
if [[ "$PLATFORM" == "unknown" ]]; then
|
|
26
|
+
echo "❌ Unsupported OS. Please use macOS, Linux, WSL, or Git Bash."
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# Handle Windows-specific case (Git Bash vs native PowerShell/CMD)
|
|
31
|
+
if [[ "$PLATFORM" == "windows" ]]; then
|
|
32
|
+
if [[ -z "${BASH_VERSION:-}" ]]; then
|
|
33
|
+
echo "⚠️ Detected native Windows shell (e.g., CMD or PowerShell)."
|
|
34
|
+
echo "🛈 Please use WSL or Git Bash for full compatibility with this script."
|
|
35
|
+
exit 1
|
|
36
|
+
else
|
|
37
|
+
echo "🪟 Detected Git Bash or compatible shell on Windows."
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# macOS-specific setup logic
|
|
42
|
+
if [[ "$PLATFORM" == "mac" ]]; then
|
|
43
|
+
echo "🍎 Running macOS-specific setup..."
|
|
44
|
+
|
|
45
|
+
# Check for Homebrew presence
|
|
46
|
+
if ! command -v brew &> /dev/null; then
|
|
47
|
+
echo "🔧 Homebrew not found. You can install it via:"
|
|
48
|
+
echo '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'
|
|
49
|
+
else
|
|
50
|
+
echo "✅ Homebrew is installed"
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# Linux-specific setup logic
|
|
54
|
+
elif [[ "$PLATFORM" == "linux" ]]; then
|
|
55
|
+
echo "🐧 Running Linux-specific setup..."
|
|
56
|
+
|
|
57
|
+
# Check for common dev tool dependencies
|
|
58
|
+
REQUIRED_CMDS=("curl" "git" "node" "npm")
|
|
59
|
+
for cmd in "${REQUIRED_CMDS[@]}"; do
|
|
60
|
+
if ! command -v "$cmd" &> /dev/null; then
|
|
61
|
+
echo "⚠️ Missing required command: $cmd"
|
|
62
|
+
fi
|
|
63
|
+
done
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Log current Node.js and npm versions
|
|
67
|
+
echo "🔍 Checking Node.js and npm versions..."
|
|
68
|
+
node -v
|
|
69
|
+
npm -v
|
|
70
|
+
|
|
71
|
+
# Ensure .env file exists
|
|
72
|
+
if [ ! -f .env ]; then
|
|
73
|
+
echo "📋 Copying .env.template to .env..."
|
|
74
|
+
cp .env.template .env
|
|
75
|
+
else
|
|
76
|
+
echo "✅ .env already exists"
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Install Node.js packages
|
|
80
|
+
echo "📦 Installing Node.js packages..."
|
|
81
|
+
npm install
|
|
82
|
+
|
|
83
|
+
# Install browser binaries for Playwright testing
|
|
84
|
+
echo "🧪 Installing Playwright dependencies..."
|
|
85
|
+
npx playwright install
|
|
86
|
+
|
|
87
|
+
echo "✅ Setup complete!"
|
|
88
|
+
echo "Next: run 'npm run dev' to start the development server."
|
package/cspell.json
CHANGED
|
@@ -43,18 +43,20 @@ export default async (request, _context) => {
|
|
|
43
43
|
const violated = report['violated-directive'] ?? '';
|
|
44
44
|
const blockedUri = report['blocked-uri'] ?? '';
|
|
45
45
|
|
|
46
|
+
/*
|
|
46
47
|
// Filter: Skip img-src violations and empty URIs
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
const ignored = [
|
|
49
|
+
violated.startsWith('img-src'),
|
|
50
|
+
blockedUri === '',
|
|
51
|
+
blockedUri === 'about',
|
|
52
|
+
blockedUri.startsWith('chrome-extension://'),
|
|
53
|
+
blockedUri.startsWith('moz-extension://'),
|
|
54
|
+
].some(Boolean);
|
|
55
|
+
|
|
56
|
+
if (ignored) {
|
|
57
|
+
return new Response(null, { status: 204 });
|
|
58
|
+
}
|
|
59
|
+
*/
|
|
58
60
|
|
|
59
61
|
// Send alert for high-risk directives
|
|
60
62
|
await sendToNtfy(violated, blockedUri, report);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@networkpro/web",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.13.
|
|
4
|
+
"version": "1.13.6",
|
|
5
5
|
"description": "Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro Strategies",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"advisory",
|
|
@@ -80,9 +80,9 @@
|
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"dompurify": "^3.2.6",
|
|
83
|
-
"posthog-js": "^1.252.
|
|
83
|
+
"posthog-js": "^1.252.1",
|
|
84
84
|
"semver": "^7.7.2",
|
|
85
|
-
"svelte": "5.34.
|
|
85
|
+
"svelte": "5.34.3"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@eslint/compat": "^1.3.0",
|
|
@@ -11,6 +11,7 @@ This file is part of Network Pro.
|
|
|
11
11
|
import FullWidthSection from '$lib/components/FullWidthSection.svelte';
|
|
12
12
|
|
|
13
13
|
export let to;
|
|
14
|
+
export let rel = ''; // Accepts optional rel value
|
|
14
15
|
export let delay = 3;
|
|
15
16
|
|
|
16
17
|
onMount(() => {
|
|
@@ -39,7 +40,9 @@ This file is part of Network Pro.
|
|
|
39
40
|
<h1>Redirecting…</h1>
|
|
40
41
|
<p>You'll be taken to the destination in just a moment.</p>
|
|
41
42
|
<div class="loading-spinner" aria-hidden="true"></div>
|
|
42
|
-
<p
|
|
43
|
+
<p
|
|
44
|
+
>If nothing happens, <a href={to} rel={rel || undefined}>click here</a
|
|
45
|
+
>.</p>
|
|
43
46
|
</div>
|
|
44
47
|
</FullWidthSection>
|
|
45
48
|
|
|
@@ -8,12 +8,18 @@ This file is part of Network Pro.
|
|
|
8
8
|
|
|
9
9
|
<script>
|
|
10
10
|
import { base } from '$app/paths';
|
|
11
|
+
import { CONSTANTS } from '$lib';
|
|
11
12
|
|
|
12
13
|
// Log the base path to verify its value
|
|
13
14
|
//console.log("Base path:", base);
|
|
14
15
|
|
|
16
|
+
//console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
|
|
17
|
+
|
|
18
|
+
const { PAGE } = CONSTANTS;
|
|
19
|
+
|
|
15
20
|
const homeLink = base || '/';
|
|
16
21
|
const aboutLink = `${base}/about`;
|
|
22
|
+
const lhubLink = `${base}/links`;
|
|
17
23
|
const fossLink = `${base}/foss-spotlight`;
|
|
18
24
|
const blogLink = 'https://blog.netwk.pro';
|
|
19
25
|
|
|
@@ -31,25 +37,25 @@ This file is part of Network Pro.
|
|
|
31
37
|
* @type {NavItem[]}
|
|
32
38
|
*/
|
|
33
39
|
const nav = [
|
|
34
|
-
{ label: 'home', href: homeLink, target:
|
|
35
|
-
{ label: 'about', href: aboutLink, target:
|
|
36
|
-
{ label: 'foss', href: fossLink, target:
|
|
40
|
+
{ label: 'home', href: homeLink, target: PAGE.SELF, external: false },
|
|
41
|
+
{ label: 'about', href: aboutLink, target: PAGE.SELF, external: false },
|
|
42
|
+
{ label: 'foss', href: fossLink, target: PAGE.SELF, external: false },
|
|
37
43
|
{
|
|
38
44
|
label: 'blog',
|
|
39
45
|
href: blogLink,
|
|
40
|
-
target:
|
|
46
|
+
target: PAGE.SELF,
|
|
41
47
|
external: false,
|
|
42
48
|
},
|
|
43
49
|
{
|
|
44
50
|
label: 'discussions',
|
|
45
51
|
href: 'https://github.com/netwk-pro/netwk-pro.github.io/discussions',
|
|
46
|
-
target:
|
|
52
|
+
target: PAGE.BLANK,
|
|
47
53
|
external: true,
|
|
48
54
|
},
|
|
49
55
|
{
|
|
50
56
|
label: 'link hub',
|
|
51
|
-
href:
|
|
52
|
-
target:
|
|
57
|
+
href: lhubLink,
|
|
58
|
+
target: PAGE.BLANK,
|
|
53
59
|
external: true,
|
|
54
60
|
},
|
|
55
61
|
];
|
|
@@ -69,7 +75,7 @@ This file is part of Network Pro.
|
|
|
69
75
|
</a>
|
|
70
76
|
{#if external}
|
|
71
77
|
<sup>
|
|
72
|
-
<span
|
|
78
|
+
<span class="gold">
|
|
73
79
|
<i class="fas fa-arrow-up-right-from-square fa-2xs"></i>
|
|
74
80
|
</span>
|
|
75
81
|
</sup>
|
|
@@ -85,3 +91,5 @@ This file is part of Network Pro.
|
|
|
85
91
|
{/each}
|
|
86
92
|
</nav>
|
|
87
93
|
<!-- END DEFAULT HEADER -->
|
|
94
|
+
|
|
95
|
+
<!-- cspell:ignore lhub -->
|
|
@@ -8,12 +8,18 @@ This file is part of Network Pro.
|
|
|
8
8
|
|
|
9
9
|
<script>
|
|
10
10
|
import { base } from '$app/paths';
|
|
11
|
+
import { CONSTANTS } from '$lib';
|
|
11
12
|
|
|
12
13
|
// Log the base path to verify its value
|
|
13
14
|
//console.log("Base path:", base);
|
|
14
15
|
|
|
16
|
+
//console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
|
|
17
|
+
|
|
18
|
+
const { PAGE } = CONSTANTS;
|
|
19
|
+
|
|
15
20
|
const aboutLink = `${base}/about`;
|
|
16
21
|
const fossLink = `${base}/foss-spotlight`;
|
|
22
|
+
const lhubLink = `${base}/links`;
|
|
17
23
|
const blogLink = 'https://blog.netwk.pro';
|
|
18
24
|
|
|
19
25
|
/**
|
|
@@ -30,24 +36,24 @@ This file is part of Network Pro.
|
|
|
30
36
|
* @type {NavItem[]}
|
|
31
37
|
*/
|
|
32
38
|
const nav = [
|
|
33
|
-
{ label: 'about', href: aboutLink, target:
|
|
34
|
-
{ label: 'foss', href: fossLink, target:
|
|
39
|
+
{ label: 'about', href: aboutLink, target: PAGE.SELF, external: false },
|
|
40
|
+
{ label: 'foss', href: fossLink, target: PAGE.SELF, external: false },
|
|
35
41
|
{
|
|
36
42
|
label: 'blog',
|
|
37
43
|
href: blogLink,
|
|
38
|
-
target:
|
|
44
|
+
target: PAGE.SELF,
|
|
39
45
|
external: false,
|
|
40
46
|
},
|
|
41
47
|
{
|
|
42
48
|
label: 'discussions',
|
|
43
49
|
href: 'https://github.com/netwk-pro/netwk-pro.github.io/discussions',
|
|
44
|
-
target:
|
|
50
|
+
target: PAGE.BLANK,
|
|
45
51
|
external: true,
|
|
46
52
|
},
|
|
47
53
|
{
|
|
48
54
|
label: 'link hub',
|
|
49
|
-
href:
|
|
50
|
-
target:
|
|
55
|
+
href: lhubLink,
|
|
56
|
+
target: PAGE.BLANK,
|
|
51
57
|
external: true,
|
|
52
58
|
},
|
|
53
59
|
];
|
|
@@ -67,7 +73,7 @@ This file is part of Network Pro.
|
|
|
67
73
|
</a>
|
|
68
74
|
{#if external}
|
|
69
75
|
<sup>
|
|
70
|
-
<span
|
|
76
|
+
<span class="gold">
|
|
71
77
|
<i class="fas fa-arrow-up-right-from-square fa-2xs"></i>
|
|
72
78
|
</span>
|
|
73
79
|
</sup>
|
|
@@ -83,3 +89,5 @@ This file is part of Network Pro.
|
|
|
83
89
|
{/each}
|
|
84
90
|
</nav>
|
|
85
91
|
<!-- END HOME HEADER -->
|
|
92
|
+
|
|
93
|
+
<!-- cspell:ignore lhub -->
|
|
@@ -209,8 +209,8 @@ This file is part of Network Pro.
|
|
|
209
209
|
|
|
210
210
|
<p>
|
|
211
211
|
<strong
|
|
212
|
-
>
|
|
213
|
-
organizations that value integrity—without sacrificing agility or trust.</strong>
|
|
212
|
+
>{COMPANY_INFO.APP_NAME}™ exists to bring strong, thoughtful security
|
|
213
|
+
to organizations that value integrity—without sacrificing agility or trust.</strong>
|
|
214
214
|
We don't just secure infrastructure. We secure confidence.
|
|
215
215
|
</p>
|
|
216
216
|
|
|
@@ -16,7 +16,7 @@ This file is part of Network Pro.
|
|
|
16
16
|
|
|
17
17
|
//console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
|
|
18
18
|
|
|
19
|
-
const {
|
|
19
|
+
const { PAGE } = CONSTANTS;
|
|
20
20
|
|
|
21
21
|
const keys = [
|
|
22
22
|
{
|
|
@@ -83,14 +83,16 @@ This file is part of Network Pro.
|
|
|
83
83
|
<img
|
|
84
84
|
src="/img/powered-by-proton.svg"
|
|
85
85
|
alt="Powered by Proton"
|
|
86
|
-
|
|
86
|
+
class="proton-img"
|
|
87
|
+
loading="eager"
|
|
88
|
+
decoding="sync" />
|
|
87
89
|
</p>
|
|
88
90
|
<p class="bquote">
|
|
89
91
|
NOTE: Addresses under the <strong>s.neteng.pro</strong> domain are powered by Proton
|
|
90
92
|
Mail to ensure strong end-to-end privacy protections.
|
|
91
93
|
</p>
|
|
92
94
|
|
|
93
|
-
{#each keys as key}
|
|
95
|
+
{#each keys as key, i}
|
|
94
96
|
<section class="pgp-entry" aria-labelledby={`pgp-${key.img}`}>
|
|
95
97
|
<div class="pgp-text">
|
|
96
98
|
<h2 id={`pgp-${key.img}`}>{key.name}</h2>
|
|
@@ -131,9 +133,9 @@ This file is part of Network Pro.
|
|
|
131
133
|
<img
|
|
132
134
|
src={`/pgp/${key.img}.png`}
|
|
133
135
|
alt={`QR code for ${key.email}`}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
class="pgp-image"
|
|
137
|
+
loading={i === 0 ? 'eager' : 'lazy'}
|
|
138
|
+
decoding={i === 0 ? 'sync' : 'async'} />
|
|
137
139
|
</picture>
|
|
138
140
|
</div>
|
|
139
141
|
</section>
|
|
@@ -434,7 +434,7 @@ footer .container {
|
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
.gold {
|
|
437
|
-
color: #
|
|
437
|
+
color: #ffc627;
|
|
438
438
|
}
|
|
439
439
|
|
|
440
440
|
.visited {
|
|
@@ -443,7 +443,7 @@ footer .container {
|
|
|
443
443
|
|
|
444
444
|
.goldseparator {
|
|
445
445
|
margin: 0 0.5rem;
|
|
446
|
-
color: #
|
|
446
|
+
color: #ffc627;
|
|
447
447
|
}
|
|
448
448
|
|
|
449
449
|
.center-nav {
|
|
@@ -552,8 +552,8 @@ footer .container {
|
|
|
552
552
|
}
|
|
553
553
|
|
|
554
554
|
.obtainium-img {
|
|
555
|
-
width:
|
|
556
|
-
height:
|
|
555
|
+
width: 185px;
|
|
556
|
+
height: 55px;
|
|
557
557
|
margin-bottom: 0.25rem;
|
|
558
558
|
}
|
|
559
559
|
|
|
@@ -562,7 +562,7 @@ footer .container {
|
|
|
562
562
|
}
|
|
563
563
|
|
|
564
564
|
.obtainium-fa-down {
|
|
565
|
-
color: #
|
|
565
|
+
color: #ffc627;
|
|
566
566
|
margin-left: 4px;
|
|
567
567
|
}
|
|
568
568
|
|
|
@@ -570,3 +570,8 @@ footer .container {
|
|
|
570
570
|
width: 50px;
|
|
571
571
|
height: 50px;
|
|
572
572
|
}
|
|
573
|
+
|
|
574
|
+
.proton-img {
|
|
575
|
+
width: 168px;
|
|
576
|
+
height: 24px;
|
|
577
|
+
}
|
|
@@ -125,28 +125,19 @@ a:hover {
|
|
|
125
125
|
|
|
126
126
|
/* selected link */
|
|
127
127
|
a:active {
|
|
128
|
-
color: #
|
|
128
|
+
color: #ffc627;
|
|
129
129
|
text-decoration: underline;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
/* visited link */
|
|
133
|
-
a:visited {
|
|
134
|
-
color: #cba557;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
132
|
/* focused link */
|
|
138
|
-
a:focus
|
|
133
|
+
a:focus {
|
|
139
134
|
color: #111; /* Black text when focused */
|
|
140
135
|
background-color: #ffc627; /* Gold background when focused */
|
|
141
|
-
outline: 2px solid #ffc627;
|
|
142
|
-
outline-offset: 4px;
|
|
143
136
|
}
|
|
144
137
|
|
|
145
|
-
/*
|
|
146
|
-
a:
|
|
147
|
-
color:
|
|
148
|
-
background-color: transparent;
|
|
149
|
-
outline: none;
|
|
138
|
+
/* visited link */
|
|
139
|
+
a:visited {
|
|
140
|
+
color: #cba557;
|
|
150
141
|
}
|
|
151
142
|
|
|
152
143
|
/* visited and mouse over */
|
|
@@ -154,6 +145,11 @@ a:visited:hover {
|
|
|
154
145
|
color: #cba557;
|
|
155
146
|
}
|
|
156
147
|
|
|
148
|
+
a:visited:focus,
|
|
149
|
+
a:visited:focus-visible {
|
|
150
|
+
color: #111 !important;
|
|
151
|
+
}
|
|
152
|
+
|
|
157
153
|
/* ==========================================================================
|
|
158
154
|
Helper classes
|
|
159
155
|
========================================================================== */
|
|
@@ -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
|
|
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:#111;background-color:#ffc627}a:visited,a:visited:hover{color:#cba557}a:visited:focus,a:visited:focus-visible{color:#111!important}.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:#cba557}.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}.obtainium-direct-label{margin:.25rem 0 .75rem;font-weight:700}.obtainium-manual-label{margin-top:.75rem;font-weight:700}.obtainium-img{width:185px;height:55px;margin-bottom:.25rem}.obtainium-margin{margin-left:4px}.obtainium-fa-down{color:#ffc627;margin-left:4px}.obtainium-icon{width:50px;height:50px}.proton-img{width:168px;height:24px}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<!-- ==========================================================================
|
|
2
|
+
src/routes/contact/+page.svelte
|
|
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
|
+
<script>
|
|
10
|
+
import RedirectPage from '$lib/components/RedirectPage.svelte';
|
|
11
|
+
import { appendUTM } from '$lib/utils/utm.js';
|
|
12
|
+
import { onMount } from 'svelte';
|
|
13
|
+
import { browser } from '$app/environment';
|
|
14
|
+
|
|
15
|
+
/** @type {string | null} */
|
|
16
|
+
let target = null;
|
|
17
|
+
|
|
18
|
+
/** @type {boolean} */
|
|
19
|
+
let show = false;
|
|
20
|
+
|
|
21
|
+
onMount(() => {
|
|
22
|
+
if (!browser) return;
|
|
23
|
+
|
|
24
|
+
target = appendUTM('https://linktr.ee/neteng_pro');
|
|
25
|
+
show = true;
|
|
26
|
+
});
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
{#if show && target}
|
|
30
|
+
<RedirectPage to={target} rel="noopener noreferrer" />
|
|
31
|
+
{:else}
|
|
32
|
+
<p style="text-align: center; margin-top: 4rem;">Preparing to redirect…</p>
|
|
33
|
+
{/if}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<!-- ==========================================================================
|
|
2
|
+
src/routes/contact/+page.svelte
|
|
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
|
+
<script>
|
|
10
|
+
import RedirectPage from '$lib/components/RedirectPage.svelte';
|
|
11
|
+
import { appendUTM } from '$lib/utils/utm.js';
|
|
12
|
+
import { onMount } from 'svelte';
|
|
13
|
+
import { browser } from '$app/environment';
|
|
14
|
+
|
|
15
|
+
/** @type {string | null} */
|
|
16
|
+
let target = null;
|
|
17
|
+
|
|
18
|
+
/** @type {boolean} */
|
|
19
|
+
let show = false;
|
|
20
|
+
|
|
21
|
+
onMount(() => {
|
|
22
|
+
if (!browser) return;
|
|
23
|
+
|
|
24
|
+
target = appendUTM('https://pal.bio/netwk-pro');
|
|
25
|
+
show = true;
|
|
26
|
+
});
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
{#if show && target}
|
|
30
|
+
<RedirectPage to={target} rel="noopener noreferrer" />
|
|
31
|
+
{:else}
|
|
32
|
+
<p style="text-align: center; margin-top: 4rem;">Preparing to redirect…</p>
|
|
33
|
+
{/if}
|
package/stylelint.config.js
CHANGED
|
@@ -30,6 +30,12 @@ export default {
|
|
|
30
30
|
],
|
|
31
31
|
'property-no-vendor-prefix': null, // Allow vendor prefixes
|
|
32
32
|
'selector-no-vendor-prefix': null,
|
|
33
|
+
'no-descending-specificity': [
|
|
34
|
+
true,
|
|
35
|
+
{
|
|
36
|
+
ignore: ['selectors-within-list'],
|
|
37
|
+
},
|
|
38
|
+
],
|
|
33
39
|
'selector-pseudo-element-colon-notation': [
|
|
34
40
|
'double',
|
|
35
41
|
{
|
package/tests/unit/demo.test.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/* ==========================================================================
|
|
2
|
-
tests/unit/demo.spec.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
|
-
import { describe, expect, it } from 'vitest';
|
|
10
|
-
|
|
11
|
-
describe('sum test', () => {
|
|
12
|
-
it('adds 1 + 2 to equal 3', () => {
|
|
13
|
-
expect(1 + 2).toBe(3);
|
|
14
|
-
});
|
|
15
|
-
});
|