@networkpro/web 1.13.0 → 1.13.1

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 CHANGED
@@ -22,6 +22,44 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
22
22
 
23
23
  ---
24
24
 
25
+ ## [1.13.1] - 2025-06-12
26
+
27
+ ### Added
28
+
29
+ - Modularized `ObtainiumBlock.svelte` component for cleaner integration in `FossItemContent.svelte`
30
+ - `heliboard.json` Obtainium configuration file for download
31
+ - Dark mode-compatible styling for Obtainium blocks in the main stylesheet
32
+
33
+ ### Changed
34
+
35
+ - Version bumped to **v1.13.1**
36
+ - Removed unnecessary PostHog preload script from `app.html`
37
+ - Removed `script-src-elem 'self' 'unsafe-inline'` from CSP policy
38
+ - Replaced existing Obtainium images with optimized versions
39
+ - Revised `<title>` metadata for the root route
40
+ - Commented out debugging `console.log` statements in the following files:
41
+ - `Badges.svelte`
42
+ - `LegalNav.svelte`
43
+ - `MetaTags.svelte`
44
+ - `Footer.svelte`
45
+ - `FossItemContent.svelte`
46
+ - `FossContent.svelte`
47
+ - `HomeContent.svelte`
48
+ - `LicenseContent.svelte`
49
+ - `TermsConditionsContent.svelte`
50
+ - Revised type definitions in `src/lib/types/fossTypes.js`
51
+ - Added optional `obtainium` property to `FossItem`
52
+ - Removed unused `hideLabels` property
53
+ - Refactored `FossItemContent.svelte` to better support and display Obtainium download links and metadata
54
+ - Updated `README.md` to reflect the correct location of the `static/pgp/` directory
55
+ - Revised the `hooks.server.js` section in `README.md` to improve accuracy and reflect current CSP behavior
56
+ - Updated `tests/e2e/app.spec.js` to assert the correct title for the root route
57
+ - Upgraded dependencies:
58
+ - `posthog-js` `^1.250.2` → `^1.252.0`
59
+ - `eslint-plugin-jsdoc` `^50.8.0` → `^51.0.1`
60
+
61
+ ---
62
+
25
63
  ## [1.13.0] - 2025-06-11
26
64
 
27
65
  ### Added
@@ -310,7 +348,8 @@ This project attempts to follow [Keep a Changelog](https://keepachangelog.com/en
310
348
 
311
349
  <!-- Link references -->
312
350
 
313
- [Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.13.0...HEAD
351
+ [Unreleased]: https://github.com/netwk-pro/netwk-pro.github.io/compare/v1.13.1...HEAD
352
+ [1.13.1]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.13.1
314
353
  [1.13.0]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.13.0
315
354
  [1.12.9]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.12.9
316
355
  [1.12.8]: https://github.com/netwk-pro/netwk-pro.github.io/releases/tag/v1.12.8
package/README.md CHANGED
@@ -77,16 +77,17 @@ This project follows the principles of [Keep a Changelog](https://keepachangelog
77
77
  │ │ └── csp-report.js # Receives CSP violation reports
78
78
  ├── scripts/ # General-purpose utility scripts
79
79
  ├── src/
80
- │ ├── app.html # Entry HTML (CSP meta, bootstrapping)
81
- │ ├── hooks.client.ts # Client-side error handling
82
- │ ├── hooks.server.js # Injects CSP headers and permissions policy
83
80
  │ ├── lib/ # Components, utilities, types, styles
84
81
  │ │ ├── components/ # Svelte components
85
82
  │ │ ├── data/ # Custom data (e.g. JSON, metadata, constants)
86
83
  │ │ └── utils/ # Helper utilities
87
84
  │ ├── routes/ # SvelteKit pages (+page.svelte, +server.js)
85
+ │ ├── app.html # Entry HTML (CSP meta, bootstrapping)
86
+ │ ├── hooks.client.ts # Client-side error handling
87
+ │ ├── hooks.server.js # Injects CSP headers and permissions policy
88
88
  │ └── service-worker.js # Custom PWA service worker
89
89
  ├── static/ # Public assets served at site root
90
+ │ ├── pgp/
90
91
  │ ├── disableSw.js # Service worker bypass (via ?nosw param)
91
92
  │ ├── manifest.json # PWA metadata
92
93
  │ ├── robots.txt # SEO: allow/disallow crawlers
@@ -180,6 +181,8 @@ ENV_MODE=dev # Options: dev, test, ci, preview, prod
180
181
 
181
182
  To streamline onboarding and enforce project conventions, you may use the optional helper scripts:
182
183
 
184
+ <!-- FIXME: Create a bootstrap.local.sh file -->
185
+
183
186
  | File/Script | Description |
184
187
  | ---------------------------------- | --------------------------------------------------------------------------------- |
185
188
  | `.env.template` | Template for local environment variables |
@@ -279,16 +282,21 @@ This project includes custom runtime configuration files for enhancing security,
279
282
 
280
283
  Located at `src/hooks.server.js`, this file is responsible for injecting dynamic security headers. It includes:
281
284
 
282
- - Content Security Policy (CSP) with support for relaxed directives (inline scripts allowed)
283
- - Permissions Policy to explicitly disable unnecessary browser APIs
284
- - X-Content-Type-Options, X-Frame-Options, and Referrer-Policy headers
285
+ - A Content Security Policy (CSP) configured with relaxed directives to permit inline scripts and styles (`'unsafe-inline'`)
286
+ - A Permissions Policy to explicitly disable unnecessary browser APIs
287
+ - Standard security headers such as `X-Content-Type-Options`, `X-Frame-Options`, and `Referrer-Policy`
288
+
289
+ > ℹ️ A stricter CSP (excluding `'unsafe-inline'`) was attempted but reverted due to framework-level and third-party script compatibility issues. The current policy allows inline scripts to ensure stability across SvelteKit and analytics features such as PostHog.
290
+
291
+ #### Future Improvements
285
292
 
286
- > 💡 The CSP nonce feature has been disabled. Inline scripts are now allowed through the policy using the `"script-src 'self' 'unsafe-inline'"` directive. If you wish to use nonces in the future, you can re-enable them by uncommenting the relevant sections in `hooks.server.js` and modifying your inline `<script>` tags.
293
+ To implement a strict nonce-based CSP in the future:
287
294
 
288
- To re-enable nonce generation for inline scripts in the future:
295
+ 1. Add nonce generation and injection logic in `hooks.server.js`
296
+ 2. Update all inline `<script>` tags (e.g. in `app.html`) to include `nonce="__cspNonce__"`
297
+ 3. Ensure any analytics libraries or dynamic scripts support nonced or external loading
289
298
 
290
- 1. Uncomment the nonce generation and injection logic in `hooks.server.js`.
291
- 2. Add `nonce="__cspNonce__"` to inline `<script>` blocks in `app.html` or route templates.
299
+ Note: Strict CSP adoption may require restructuring third-party integrations and deeper framework coordination.
292
300
 
293
301
  > 💡 The `[headers]` block in `netlify.toml` has been deprecated — all headers are now set dynamically from within SvelteKit.
294
302
 
package/cspell.json CHANGED
@@ -44,6 +44,7 @@
44
44
  "netwk",
45
45
  "networkpro",
46
46
  "Nextcloud",
47
+ "nonced",
47
48
  "noopener",
48
49
  "noreferrer",
49
50
  "nosniff",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@networkpro/web",
3
3
  "private": false,
4
- "version": "1.13.0",
4
+ "version": "1.13.1",
5
5
  "description": "Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro Strategies",
6
6
  "keywords": [
7
7
  "advisory",
@@ -80,7 +80,7 @@
80
80
  },
81
81
  "dependencies": {
82
82
  "dompurify": "^3.2.6",
83
- "posthog-js": "^1.250.2",
83
+ "posthog-js": "^1.252.0",
84
84
  "semver": "^7.7.2",
85
85
  "svelte": "5.34.1"
86
86
  },
@@ -99,7 +99,7 @@
99
99
  "browserslist": "^4.25.0",
100
100
  "eslint": "^9.28.0",
101
101
  "eslint-config-prettier": "^10.1.5",
102
- "eslint-plugin-jsdoc": "^50.8.0",
102
+ "eslint-plugin-jsdoc": "^51.0.1",
103
103
  "eslint-plugin-svelte": "^3.9.2",
104
104
  "globals": "^16.2.0",
105
105
  "jsdom": "^26.1.0",
package/src/app.html CHANGED
@@ -34,15 +34,6 @@
34
34
  href="https://us-assets.i.posthog.com"
35
35
  crossorigin="anonymous" />
36
36
 
37
- <!-- Preload the PostHog script -->
38
- <link
39
- rel="preload"
40
- href="https://us-assets.i.posthog.com/array/phc_Qshfo6AXzh4pS7aPigfqyeo4qj1qlyh7gDuHDeVMSR0/config.js"
41
- as="script" />
42
- <script
43
- src="https://us-assets.i.posthog.com/array/phc_Qshfo6AXzh4pS7aPigfqyeo4qj1qlyh7gDuHDeVMSR0/config.js"
44
- defer></script>
45
-
46
37
  <!-- Preload FontAwesome webfonts -->
47
38
  <link
48
39
  rel="preload"
@@ -31,7 +31,6 @@ export async function handle({ event, resolve }) {
31
31
  const cspDirectives = [
32
32
  "default-src 'self';",
33
33
  "script-src 'self' 'unsafe-inline' https://us.i.posthog.com https://us-assets.i.posthog.com;",
34
- "script-src-elem 'self' 'unsafe-inline' https://us.i.posthog.com https://us-assets.i.posthog.com;",
35
34
  "style-src 'self' 'unsafe-inline';",
36
35
  "img-src 'self' data:;",
37
36
  "connect-src 'self' https://us.i.posthog.com https://us-assets.i.posthog.com;",
@@ -15,7 +15,7 @@ This file is part of Network Pro.
15
15
  // Log the base path to verify its value
16
16
  //console.log("Base path:", base);
17
17
 
18
- console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
18
+ //console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
19
19
 
20
20
  const { PAGE } = CONSTANTS;
21
21
 
@@ -13,7 +13,7 @@ This file is part of Network Pro.
13
13
  // Log the base path to verify its value
14
14
  //console.log("Base path:", base);
15
15
 
16
- console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
16
+ //console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
17
17
 
18
18
  const { PAGE } = CONSTANTS;
19
19
 
@@ -12,7 +12,7 @@ This file is part of Network Pro.
12
12
 
13
13
  import { CONSTANTS } from '$lib';
14
14
 
15
- console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
15
+ //console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
16
16
 
17
17
  const { COMPANY_INFO, LINKS } = CONSTANTS;
18
18
 
@@ -10,21 +10,19 @@ This file is part of Network Pro.
10
10
  /* at-html is sanitized by DOMPurify */
11
11
  /* eslint-disable svelte/no-at-html-tags */
12
12
 
13
+ import ObtainiumBlock from '$lib/components/foss/ObtainiumBlock.svelte';
14
+ import FossFeatures from '$lib/components/foss/FossFeatures.svelte';
15
+
13
16
  import { onMount } from 'svelte';
14
17
  import { sanitizeHtml } from '$lib/utils/purify.js';
15
- import FossFeatures from '$lib/components/foss/FossFeatures.svelte';
16
- // Import directly from $lib by way of image utility
17
18
  import { obtainiumPng, obtainiumWbp } from '$lib';
19
+
18
20
  import { CONSTANTS } from '$lib';
19
21
 
20
- console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
22
+ //console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
21
23
 
22
24
  const { PAGE, NAV } = CONSTANTS;
23
25
 
24
- /** @type {string} */
25
- const obtainiumLink =
26
- 'https://apps.obtainium.imranr.dev/redirect.html?r=obtainium://app/%7B%22id%22%3A%22fe.linksheet.nightly%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2FLinkSheet%2Fnightly%22%2C%22author%22%3A%221fexd%22%2C%22name%22%3A%22LinkSheet%20Nightly%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Atrue%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Afalse%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Afalse%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22LinkSheet.Nightly%5C%22%2C%5C%22invertAPKFilter%5C%22%3Atrue%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22Restore%20link%20control%20on%20Android%2012%2B%5C%22%7D%22%7D';
27
-
28
26
  /** @type {"async"} */
29
27
  const decoding = 'async';
30
28
 
@@ -71,7 +69,7 @@ This file is part of Network Pro.
71
69
  fetchpriority={isFirst ? 'high' : 'auto'}
72
70
  src={fossItem.images.png}
73
71
  alt={fossItem.imgAlt}
74
- style="width: 50px; height: 50px" />
72
+ class="obtainium-icon" />
75
73
  </picture>
76
74
  </td>
77
75
  <td class="foss-cell">
@@ -105,49 +103,20 @@ This file is part of Network Pro.
105
103
 
106
104
  &nbsp;
107
105
 
108
- <div class="linksheet">
106
+ <div class="obtainium">
109
107
  <!-- Special handling for LinkSheet's Obtainium link -->
110
- {#if fossItem.id === 'linksheet'}
111
- <div class="linksheet-entry">
112
- <a rel={PAGE.REL} href={obtainiumLink} target={PAGE.BLANK}>
113
- <picture>
114
- <source srcset={obtainiumWbp} type="image/webp" />
115
- <img
116
- decoding={isFirst ? 'sync' : decoding}
117
- loading={isFirst ? 'eager' : loading}
118
- fetchpriority={isFirst ? 'high' : 'auto'}
119
- src={obtainiumPng}
120
- alt="Obtainium"
121
- style="width: 207px; height: 80px" />
122
- </picture>
123
- </a>
124
- <p>
125
- <span style="color: #ffc627"
126
- ><i class="fas fa-file-arrow-down" style="margin-left: 8px;"></i
127
- ></span>
128
- <a
129
- href="/bin/linksheet.json"
130
- type="application/json"
131
- download
132
- style="margin-left: 8px;"
133
- target={PAGE.BLANK}>
134
- Obtainium App Config
135
- </a>
136
- </p>
137
- </div>
108
+ {#if fossItem.obtainium}
109
+ <ObtainiumBlock obtainium={fossItem.obtainium} {isFirst} />
138
110
  {/if}
139
111
 
140
112
  <!-- Other links -->
141
- {#each fossItem.links as { label, href, imgAlt, downloadText, downloadHref, hideLabels }, i}
142
- <!-- Skip the first link for LinkSheet since we already handled it separately -->
143
- {#if !(fossItem.id === 'linksheet' && i === 0)}
144
- <div class="linksheet-entry">
145
- {#if !hideLabels && label && href}
146
- <strong>{label}:</strong>
147
- <a rel={PAGE.REL} {href} target={PAGE.BLANK}>{href}</a>
148
- {/if}
149
- </div>
150
- {/if}
113
+ {#each fossItem.links as { label, href, imgAlt, downloadText, downloadHref }, i}
114
+ <div class="linksheet-entry">
115
+ {#if label && href}
116
+ <strong>{label}:</strong>
117
+ <a rel={PAGE.REL} {href} target={PAGE.BLANK}>{href}</a>
118
+ {/if}
119
+ </div>
151
120
  {/each}
152
121
  </div>
153
122
 
@@ -0,0 +1,64 @@
1
+ <!-- ==========================================================================
2
+ src/lib/components/foss/ObtainiumBlock.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
+ <!-- Encapsulated UI block for Obtainium deep-link + manual config download. -->
10
+
11
+ <script>
12
+ /// <reference path="$lib/types/fossTypes.js" />
13
+ /** @type {{ href: string; download: string; label: string; isFirst?: boolean }} */
14
+ export let obtainium;
15
+ export let isFirst = false;
16
+
17
+ import { obtainiumPng, obtainiumWbp } from '$lib';
18
+ import { CONSTANTS } from '$lib';
19
+
20
+ const { PAGE } = CONSTANTS;
21
+
22
+ /** @type {"async"} */
23
+ const decoding = 'async';
24
+
25
+ /** @type {"lazy"} */
26
+ const loading = 'lazy';
27
+ </script>
28
+
29
+ <div class="linksheet-entry">
30
+ <p class="obtainium-direct-label">Open directly in Obtainium:</p>
31
+
32
+ <a
33
+ rel={PAGE.REL}
34
+ href={obtainium.href}
35
+ target={PAGE.BLANK}
36
+ aria-label="Open this app in Obtainium">
37
+ <picture>
38
+ <source srcset={obtainiumWbp} type="image/webp" />
39
+ <img
40
+ decoding={isFirst ? 'sync' : decoding}
41
+ loading={isFirst ? 'eager' : loading}
42
+ fetchpriority={isFirst ? 'high' : 'auto'}
43
+ src={obtainiumPng}
44
+ alt="Obtainium"
45
+ class="obtainium-img" />
46
+ </picture>
47
+ </a>
48
+
49
+ <p class="obtainium-manual-label">Download and import manually:</p>
50
+
51
+ <p>
52
+ <span class="obtainium-fa-down">
53
+ <i class="fas fa-file-arrow-down"></i>
54
+ </span>
55
+ <a
56
+ href={obtainium.download}
57
+ type="application/json"
58
+ download
59
+ class="obtainium-margin"
60
+ target={PAGE.BLANK}>
61
+ {obtainium.label}
62
+ </a>
63
+ </p>
64
+ </div>
@@ -17,7 +17,7 @@ This file is part of Network Pro.
17
17
  // Log the base path to verify its value
18
18
  //console.log("Base path:", base);
19
19
 
20
- console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
20
+ //console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
21
21
 
22
22
  const { COMPANY_INFO, CONTACT, PAGE, NAV } = CONSTANTS;
23
23
 
@@ -7,14 +7,23 @@ This file is part of Network Pro.
7
7
  ========================================================================== */
8
8
 
9
9
  // Import FOSS images
10
- import { base } from "$app/paths";
11
10
  import { acodePng, acodeWbp, eauthPng, eauthWbp, hboardPng, hboardWbp, lsheetPng, lsheetWbp, pmxPng, pmxWbp, squirclePng, squircleWbp, tosPng, tosWbp, urlPng, urlWbp } from "$lib";
12
11
 
12
+ // cspell:disable
13
13
  /**
14
- * URL to the LinkSheet config file, using the base path
14
+ * External URL to add HeliBoard to Obtainium
15
15
  * @type {string}
16
16
  */
17
- const lsheetDl = `${base}/bin/linksheet.json`;
17
+ const hboardLink = "obtainium://app/%7B%22id%22%3A%22helium314.keyboard%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2FHelium314%2FHeliBoard%22%2C%22author%22%3A%22Helium314%22%2C%22name%22%3A%22HeliBoard%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Afalse%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22release%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22HeliBoard%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22HeliBoard%20is%20a%20privacy-conscious%20and%20customizable%20open-source%20keyboard%2C%20based%20on%20AOSP%20%2F%20OpenBoard.%20Does%20not%20use%20internet%20permission%2C%20and%20thus%20is%20100%25%20offline.%5C%22%2C%5C%22appAuthor%5C%22%3A%5C%22Helium314%5C%22%7D%22%7D";
18
+ //cspell:enable
19
+
20
+ // cspell:disable
21
+ /**
22
+ * External URL to add LinkSheet Nightly to Obtainium
23
+ * @type {string}
24
+ */
25
+ const lsheetLink = "obtainium://app/%7B%22id%22%3A%22fe.linksheet.nightly%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2FLinkSheet%2Fnightly%22%2C%22author%22%3A%221fexd%22%2C%22name%22%3A%22LinkSheet%20Nightly%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Atrue%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Afalse%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Afalse%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22LinkSheet.Nightly%5C%22%2C%5C%22invertAPKFilter%5C%22%3Atrue%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22LinkSheet%20Nightly%5C%22%2C%5C%22shizukuPretendToBeGooglePlay%5C%22%3Afalse%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22Restore%20link%20control%20on%20Android%2012%2B%5C%22%2C%5C%22appAuthor%5C%22%3A%5C%221fexd%5C%22%7D%22%7D";
26
+ //cspell:enable
18
27
 
19
28
  export const fossData = [
20
29
  {
@@ -138,6 +147,11 @@ export const fossData = [
138
147
  </p>
139
148
 
140
149
  `,
150
+ obtainium: {
151
+ label: "Obtainium App Config",
152
+ href: hboardLink,
153
+ download: "/bin/heliboard.json"
154
+ },
141
155
  links: [
142
156
  {
143
157
  label: "GitHub",
@@ -511,14 +525,12 @@ export const fossData = [
511
525
  ],
512
526
  detailsDescription: `
513
527
  `,
528
+ obtainium: {
529
+ label: "Obtainium App Config",
530
+ href: lsheetLink,
531
+ download: "/bin/linksheet.json"
532
+ },
514
533
  links: [
515
- {
516
- imgAlt: "Obtainium",
517
- hideLabels: true, // Special flag to control rendering
518
- downloadText: "Obtainium App Config",
519
- downloadHref:
520
- {lsheetDl},
521
- },
522
534
  {
523
535
  label: "GitHub",
524
536
  href: "https://github.com/LinkSheet/LinkSheet",
Binary file
Binary file
package/src/lib/meta.js CHANGED
@@ -18,7 +18,7 @@ This file is part of Network Pro.
18
18
  const meta = {
19
19
  '/': {
20
20
  title:
21
- 'Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro',
21
+ 'Security, Networking, Privacy — Network Pro Strategies',
22
22
  description:
23
23
  'Locking Down Networks, Unlocking Confidence™ | Security, Networking, Privacy — Network Pro™',
24
24
  },
@@ -11,7 +11,7 @@ This file is part of Network Pro.
11
11
  import FossItemContent from '$lib/components/foss/FossItemContent.svelte';
12
12
  import { CONSTANTS } from '$lib';
13
13
 
14
- console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
14
+ //console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
15
15
 
16
16
  const { PAGE } = CONSTANTS;
17
17
 
@@ -51,7 +51,7 @@ This file is part of Network Pro.
51
51
  */
52
52
  const pageInfo = {
53
53
  title: 'FOSS Spotlight',
54
- lastUpdated: 'June 8, 2025',
54
+ lastUpdated: 'June 12, 2025',
55
55
  };
56
56
  </script>
57
57
 
@@ -13,7 +13,7 @@ This file is part of Network Pro.
13
13
  // Log the base path to verify its value
14
14
  //console.log("Base path:", base);
15
15
 
16
- console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
16
+ //console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
17
17
 
18
18
  const { COMPANY_INFO, PAGE, NAV } = CONSTANTS;
19
19
 
@@ -16,7 +16,7 @@ This file is part of Network Pro.
16
16
  // Log the base path to verify its value
17
17
  //console.log("Base path:", base);
18
18
 
19
- console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
19
+ //console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
20
20
 
21
21
  const { COMPANY_INFO, CONTACT, PAGE, LINKS, NAV } = CONSTANTS;
22
22
 
@@ -15,7 +15,7 @@ This file is part of Network Pro.
15
15
  // Log the base path to verify its value
16
16
  //console.log("Base path:", base);
17
17
 
18
- console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
18
+ //console.log(CONSTANTS.COMPANY_INFO.APP_NAME);
19
19
 
20
20
  const { COMPANY_INFO, PAGE, NAV } = CONSTANTS;
21
21
 
@@ -540,3 +540,33 @@ footer .container {
540
540
  flex: 1;
541
541
  min-width: 150px;
542
542
  }
543
+
544
+ .obtainium-direct-label {
545
+ margin: .25rem 0 0.75rem 0;
546
+ font-weight: bold;
547
+ }
548
+
549
+ .obtainium-manual-label {
550
+ font-weight: bold;
551
+ margin-top: 0.75rem;
552
+ }
553
+
554
+ .obtainium-img {
555
+ width: 201px;
556
+ height: 60px;
557
+ margin-bottom: 0.25rem;
558
+ }
559
+
560
+ .obtainium-margin {
561
+ margin-left: 4px;
562
+ }
563
+
564
+ .obtainium-fa-down {
565
+ color: #FFC627;
566
+ margin-left: 4px;
567
+ }
568
+
569
+ .obtainium-icon {
570
+ width: 50px;
571
+ height: 50px;
572
+ }
@@ -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{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}
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}.obtainium-direct-label{margin:.25rem 0 .75rem;font-weight:700}.obtainium-manual-label{margin-top:.75rem;font-weight:700}.obtainium-img{width:201px;height:60px;margin-bottom:.25rem}.obtainium-margin{margin-left:4px}.obtainium-fa-down{color:#ffc627;margin-left:4px}.obtainium-icon{width:50px;height:50px}
@@ -12,7 +12,7 @@ This file is part of Network Pro.
12
12
  * src/lib/components/foss/FossItemContent.svelte
13
13
  * @module src/lib/types
14
14
  * @author SunDevil311
15
- * @updated 2025-06-03
15
+ * @updated 2025-06-12
16
16
  */
17
17
 
18
18
  /**
@@ -22,7 +22,13 @@ This file is part of Network Pro.
22
22
  * @property {string} [imgAlt]
23
23
  * @property {string} [downloadText]
24
24
  * @property {string} [downloadHref]
25
- * @property {boolean} [hideLabels]
25
+ */
26
+
27
+ /**
28
+ * @typedef {object} FossObtainium
29
+ * @property {string} href // Link for Obtainium intent
30
+ * @property {string} label // Text for the manual config download link
31
+ * @property {string} download // Filename for the downloaded config
26
32
  */
27
33
 
28
34
  /**
@@ -37,4 +43,5 @@ This file is part of Network Pro.
37
43
  * @property {Array<any>} features
38
44
  * @property {Array<string>} notes
39
45
  * @property {Array<FossLink>} links
46
+ * @property {FossObtainium} [obtainium]
40
47
  */
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "helium314.keyboard",
3
+ "url": "https://github.com/Helium314/HeliBoard",
4
+ "author": "Helium314",
5
+ "name": "HeliBoard",
6
+ "preferredApkIndex": 0,
7
+ "additionalSettings": "{\"includePrereleases\":false,\"fallbackToOlderReleases\":true,\"filterReleaseTitlesByRegEx\":\"\",\"filterReleaseNotesByRegEx\":\"\",\"verifyLatestTag\":false,\"dontSortReleasesList\":false,\"useLatestAssetDateAsReleaseDate\":false,\"trackOnly\":false,\"versionExtractionRegEx\":\"\",\"matchGroupToUse\":\"\",\"versionDetection\":true,\"releaseDateAsVersion\":false,\"useVersionCodeAsOSVersion\":false,\"apkFilterRegEx\":\"release\",\"invertAPKFilter\":false,\"autoApkFilterByArch\":true,\"appName\":\"HeliBoard\",\"shizukuPretendToBeGooglePlay\":false,\"exemptFromBackgroundUpdates\":false,\"skipUpdateNotifications\":false,\"about\":\"HeliBoard is a privacy-conscious and customizable open-source keyboard, based on AOSP / OpenBoard. Does not use internet permission, and thus is 100% offline.\",\"appAuthor\":\"Helium314\"}"
8
+ }
@@ -33,7 +33,7 @@ test.describe('Desktop Tests', () => {
33
33
  await setDesktopView(page);
34
34
  await page.goto('/');
35
35
  await page.waitForLoadState('load', { timeout: 60000 });
36
- await expect(page).toHaveTitle(/Locking Down Networks/);
36
+ await expect(page).toHaveTitle(/Security, Networking, Privacy/);
37
37
  });
38
38
 
39
39
  // Root route should display nav bar and about link
@@ -97,7 +97,7 @@ test.describe('Mobile Tests', () => {
97
97
  await setMobileView(page);
98
98
  await page.goto('/');
99
99
  await page.waitForLoadState('load', { timeout: 60000 });
100
- await expect(page).toHaveTitle(/Locking Down Networks/);
100
+ await expect(page).toHaveTitle(/Security, Networking, Privacy/);
101
101
  });
102
102
 
103
103
  // Root route should display headings properly on mobile