PageSourceSearch

https://serial-studio.com/js/config.js?v=6949b27c92

js serial-studio.com collected 2026-10-02 11:56:12 UTC 8,761 bytes, 200 lines download raw bytes

1// Single source of truth for the release. Bump VERSION on a new release and
2// every download URL below is rebuilt automatically.
3const VERSION = "4.1.0";
4const TAG = "v" + VERSION;
5const RELEASE_BASE = "https://github.com/Serial-Studio/Serial-Studio/releases/download/" + TAG;
6const asset = (suffix) => `${RELEASE_BASE}/Serial-Studio-Pro-${VERSION}-${suffix}`;
7
8const config = {
9  version: {
10    latest: TAG,
11    windows: TAG,
12    macos: TAG,
13    linux: TAG
14  },
15
16  downloads: {
17    // Windows
18    windows: asset("Windows.msi"),
19    windowsPortable: asset("Windows-Portable.zip"),
20    microsoftStore: "https://apps.microsoft.com/detail/9N5PZLKJCDP7",
21
22    // macOS (universal)
23    macos: asset("macOS.dmg"),
24
25    // Linux — x64
26    linux: asset("Linux-x64.AppImage"),
27    linuxX64AppImage: asset("Linux-x64.AppImage"),
28    linuxX64Deb: asset("Linux-x64.deb"),
29    linuxX64Rpm: asset("Linux-x64.rpm"),
30
31    // Linux — ARM64 (Raspberry Pi etc.)
32    linuxArm64AppImage: asset("Linux-arm64.AppImage"),
33    linuxArm64Deb: asset("Linux-arm64.deb"),
34    linuxArm64Rpm: asset("Linux-arm64.rpm"),
35
36    flathub: "https://flathub.org/apps/com.serial_studio.Serial-Studio"
37  },
38
39  links: {
40    github: "https://github.com/Serial-Studio/Serial-Studio",
41    wiki: "https://github.com/Serial-Studio/Serial-Studio/wiki",
42    examples: "https://github.com/Serial-Studio/Serial-Studio/tree/master/examples",
43    faq: "https://serial-studio.com/help#faq",
44    releases: "https://github.com/Serial-Studio/Serial-Studio/releases",
45    license: "https://github.com/Serial-Studio/Serial-Studio/blob/master/LICENSE.md",
46    gpl: "https://github.com/Serial-Studio/Serial-Studio/blob/master/LICENSES/GPL-3.0-only.txt",
47    store: "https://store.serial-studio.com/checkout/buy/e33e6d04-639f-46b7-bd68-b46d341c5b16",
48    instagram: "https://instagram.com/serialstudio.app",
49    youtube: "https://www.youtube.com/@serial-studio-app"
50  },
51
52  contact: {
53    email: "[email protected]",
54    formspree: "https://formspree.io/f/xbdjodnk"
55  },
56
57  // Rendered into the "Trusted by" carousel on index.html (see applyConfig).
58  // To add a client: drop a logo in images/clients/ and add an entry here.
59  companies: [
60    { name: "Teledyne", url: "https://www.teledyne.com/", logo: "images/clients/teledyne.png" },
61    { name: "Bonnel", url: "https://bonnel.cz/", logo: "images/clients/bonnel.png" },
62    { name: "Harvard University", url: "https://www.harvard.edu/", logo: "images/clients/harvard.png" },
63    { name: "Windracers", url: "https://windracers.com/", logo: "images/clients/windracers.png" },
64    { name: "Kemper", url: "https://kemper.eu/", logo: "images/clients/kemper.png" },
65    { name: "Spectrum Medical", url: "https://www.spectrummedical.com/", logo: "images/clients/spectrum-medical.png" },
66    { name: "Terranova", url: "https://www.terranova.inc/", logo: "images/clients/terranova.png" },
67    { name: "NXP Semiconductors", url: "https://www.nxp.com/", logo: "images/clients/nxp.png" },
68    { name: "Aether Space", url: "https://aetherspace.be/", logo: "images/clients/aether.png" },
69    { name: "Newbury Innovation", url: "https://www.newburyelectronics.co.uk/innovation/", logo: "images/clients/newbury.png" },
70    { name: "Sorcerer", url: "https://www.sorcerer.earth/", logo: "images/clients/sorcerer.png" },
71    { name: "University of Bath", url: "https://www.bath.ac.uk/", logo: "images/clients/bath.png" },
72    { name: "Spherie", url: "https://www.spherie.com/", logo: "images/clients/spherie.png" },
73    { name: "Critical Software", url: "https://criticalsoftware.com/", logo: "images/clients/critical.png" },
74    { name: "Redlite", url: "https://redlite.nz/", logo: "images/clients/redlite.png" },
75    { name: "NJIT Baja Racing", url: "https://baja.njit.edu/", logo: "images/clients/njit.png" },
76    { name: "Marco Beverage Systems", url: "https://marcobeveragesystems.com/us/", logo: "images/clients/marco.png" },
77    { name: "Grinn Global", url: "https://grinn-global.com/", logo: "images/clients/grinn.png" },
78    { name: "Spectra Ingenuity", url: "https://spectra-ingenuity.com.au/", logo: "images/clients/spectra.png" },
79    { name: "ThoraTech", url: "https://thoratech.de/de/", logo: "images/clients/thoratech.png" },
80    { name: "CUNY - City University of New York", url: "https://www.cuny.edu/", logo: "images/clients/cuny.png" },
81    { name: "Vitabyte / Wolffsohn Research", url: "https://www.wolffsohnresearch.com/", logo: "images/clients/vitabyte.png" },
82    { name: "White River Technologies", url: "https://whiterivertech.com/", logo: "images/clients/whiteriver.png" }
83  ]
84};
85
86document.addEventListener('DOMContentLoaded', () => {
87  applyConfig();
88});
89
90function applyConfig() {
91  const downloadLinks = {
92    'windows-download': config.downloads.windows,
93    'macos-download': config.downloads.macos,
94    'linux-download': config.downloads.linux
95  };
96
97  Object.entries(downloadLinks).forEach(([id, url]) => {
98    const element = document.getElementById(id);
99    if (element) element.href = url;
100  });
101
102  applyOsDownloadHint();
103
104  document.querySelectorAll('a[data-config]').forEach(link => {
105    const configKey = link.getAttribute('data-config');
106    const keys = configKey.split('.');
107    let value = config;
108
109    keys.forEach(key => {
110      value = value[key];
111    });
112
113    if (value) link.href = value;
114  });
115
116  populateTrustedBy();
117}
118
119// OS-aware quick download hint in the index.html hero (#hero-os-download).
120// The anchor ships hidden; when the visitor is on a desktop OS we can serve,
121// point it at the right installer (URL + version from this file's SSOT) and
122// reveal it. Unrecognized platforms (Android, iOS, ChromeOS, ...) get a
123// "See all downloads" variant pointing at the #download grid; no-JS visitors
124// keep it hidden — the primary CTA still leads to #download.
125function applyOsDownloadHint() {
126  const osHint = document.getElementById('hero-os-download');
127  if (!osHint) return;
128
129  const installers = {
130    windows: { name: 'Windows', url: config.downloads.windows, pkg: '.msi installer' },
131    macos: { name: 'macOS', url: config.downloads.macos, pkg: '.dmg universal' },
132    linux: { name: 'Linux', url: config.downloads.linux, pkg: 'AppImage x64' }
133  };
134  const installer = installers[detectDesktopOS()];
135
136  if (installer) {
137    osHint.href = installer.url;
138    osHint.target = '_blank';
139    osHint.rel = 'noopener';
140    // OS name goes in a translate="no" span so page translation doesn't
141    // localize it ("Windows" -> "Ventanas" in Spanish, etc.).
142    const label = osHint.querySelector('.hero-os-hint-label');
143    label.textContent = 'Download for ';
144    const osName = document.createElement('span');
145    osName.setAttribute('translate', 'no');
146    osName.className = 'notranslate';
147    osName.textContent = installer.name;
148    label.appendChild(osName);
149    osHint.querySelector('.hero-os-hint-meta').textContent =
150      TAG + ' · ' + installer.pkg;
151  } else {
152    // Unrecognized platform (Android, iOS, ChromeOS, BSD, ...): never guess
153    // an installer — keep the default #download href and offer the grid.
154    osHint.querySelector('.hero-os-hint-label').textContent =
155      'See all downloads';
156    osHint.querySelector('.hero-os-hint-meta').textContent =
157      TAG + ' · all platforms';
158  }
159  osHint.hidden = false;
160}
161
162// Best-effort desktop OS detection for the hero quick-download hint. Returns
163// 'windows' | 'macos' | 'linux', or null for anything we don't ship a
164// one-click installer for. Mobile and ChromeOS checks run first because their
165// platform strings masquerade as desktop ones (Android reports "Linux armv8l",
166// iPadOS reports "MacIntel", ChromeOS reports "Linux x86_64").
167function detectDesktopOS() {
168  const uaData = navigator.userAgentData;
169  const platform = (uaData && uaData.platform) || navigator.platform || '';
170  const ua = navigator.userAgent || '';
171  const probe = platform + ' ' + ua;
172
173  if (uaData && uaData.mobile) return null;
174  if (/Android|iPhone|iPad|iPod|CrOS|Chrome OS/i.test(probe)) return null;
175  if (/Mac/i.test(platform)) return navigator.maxTouchPoints > 1 ? null : 'macos';
176  if (/Win/i.test(platform)) return 'windows';
177  if (/Linux|X11/i.test(platform)) return 'linux';
178  return null;
179}
180
181function populateTrustedBy() {
182  const trustedTrack = document.querySelector('.trusted-by .carousel-track');
183  if (trustedTrack) {
184    config.companies.forEach(company => {
185      const card = document.createElement('a');
186      card.href = company.url;
187      card.target = '_blank';
188      card.rel = 'noopener';
189      card.className = 'logo-card';
190
191      const img = document.createElement('img');
192      img.src = company.logo;
193      img.alt = company.name;
194      img.loading = 'lazy';
195
196      card.appendChild(img);
197      trustedTrack.appendChild(card);
198    });
199  }
200}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.