|
248 | 248 | data-current-version="dev" |
249 | 249 | data-current-label="dev" |
250 | 250 | data-target-uri="_modules/index.html" |
| 251 | + data-site-root="https://pgmpy.org" |
| 252 | + data-manifest-url="https://pgmpy.org/versions.json" |
251 | 253 | > |
252 | 254 |
|
253 | 255 |
|
|
290 | 292 | const currentVersion = select.dataset.currentVersion; |
291 | 293 | const currentLabel = select.dataset.currentLabel || currentVersion; |
292 | 294 | const currentTargetUri = (select.dataset.targetUri || "").replace(/^\/+/, ""); |
| 295 | + const siteRoot = (select.dataset.siteRoot || "").replace(/\/+$/, ""); |
| 296 | + const manifestUrl = select.dataset.manifestUrl; |
293 | 297 |
|
294 | 298 | if (!Array.from(select.options).some(function(option) { return option.value === currentVersion; })) { |
295 | 299 | const option = document.createElement("option"); |
|
300 | 304 | } |
301 | 305 |
|
302 | 306 | const buildTargetUrl = function(baseUrl) { |
| 307 | + const normalized = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/"; |
303 | 308 | if (!currentTargetUri || currentTargetUri === "index.html") { |
304 | | - return baseUrl; |
| 309 | + return normalized; |
305 | 310 | } |
306 | | - return new URL(currentTargetUri, baseUrl).toString(); |
| 311 | + return new URL(currentTargetUri, normalized).toString(); |
307 | 312 | }; |
308 | 313 |
|
309 | 314 | const navigateToVersion = async function(option) { |
|
312 | 317 | return; |
313 | 318 | } |
314 | 319 |
|
315 | | - const targetUrl = buildTargetUrl(baseUrl); |
| 320 | + const normalized = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/"; |
| 321 | + const targetUrl = buildTargetUrl(normalized); |
316 | 322 |
|
317 | | - if (targetUrl === baseUrl) { |
318 | | - window.location.href = baseUrl; |
| 323 | + if (targetUrl === normalized) { |
| 324 | + window.location.href = normalized; |
319 | 325 | return; |
320 | 326 | } |
321 | 327 |
|
322 | 328 | try { |
323 | 329 | const response = await fetch(targetUrl, { method: "HEAD" }); |
324 | | - window.location.href = response.ok ? targetUrl : baseUrl; |
| 330 | + window.location.href = response.ok ? targetUrl : normalized; |
325 | 331 | } catch (error) { |
326 | 332 | window.location.href = targetUrl; |
327 | 333 | } |
|
334 | 340 | } |
335 | 341 | navigateToVersion(option); |
336 | 342 | }); |
| 343 | + |
| 344 | + const populateFromManifest = function(manifest) { |
| 345 | + if (!siteRoot) { |
| 346 | + return; |
| 347 | + } |
| 348 | + |
| 349 | + const stableName = manifest && manifest.stable; |
| 350 | + const releases = manifest && Array.isArray(manifest.releases) ? manifest.releases : []; |
| 351 | + const development = manifest && Array.isArray(manifest.development) ? manifest.development : []; |
| 352 | + |
| 353 | + const fragment = document.createDocumentFragment(); |
| 354 | + |
| 355 | + const appendOption = function(group, value, textContent, url) { |
| 356 | + const option = document.createElement("option"); |
| 357 | + option.value = value; |
| 358 | + option.textContent = textContent; |
| 359 | + option.dataset.url = url; |
| 360 | + if (value === currentVersion) { |
| 361 | + option.selected = true; |
| 362 | + } |
| 363 | + group.appendChild(option); |
| 364 | + }; |
| 365 | + |
| 366 | + if (stableName || releases.length) { |
| 367 | + const releasesGroup = document.createElement("optgroup"); |
| 368 | + releasesGroup.label = "Releases"; |
| 369 | + if (stableName) { |
| 370 | + appendOption(releasesGroup, "stable", stableName + " (stable)", siteRoot + "/"); |
| 371 | + } |
| 372 | + releases.forEach(function(name) { |
| 373 | + appendOption(releasesGroup, name, name, siteRoot + "/" + name + "/"); |
| 374 | + }); |
| 375 | + fragment.appendChild(releasesGroup); |
| 376 | + } |
| 377 | + |
| 378 | + if (development.length) { |
| 379 | + const developmentGroup = document.createElement("optgroup"); |
| 380 | + developmentGroup.label = "In Development"; |
| 381 | + development.forEach(function(name) { |
| 382 | + appendOption(developmentGroup, name, name, siteRoot + "/" + name + "/"); |
| 383 | + }); |
| 384 | + fragment.appendChild(developmentGroup); |
| 385 | + } |
| 386 | + |
| 387 | + const hasCurrent = Array.from(fragment.querySelectorAll("option")).some(function(option) { |
| 388 | + return option.value === currentVersion; |
| 389 | + }); |
| 390 | + if (!hasCurrent) { |
| 391 | + const option = document.createElement("option"); |
| 392 | + option.value = currentVersion; |
| 393 | + option.textContent = currentLabel; |
| 394 | + option.selected = true; |
| 395 | + fragment.insertBefore(option, fragment.firstChild); |
| 396 | + } |
| 397 | + |
| 398 | + select.replaceChildren(fragment); |
| 399 | + }; |
| 400 | + |
| 401 | + if (manifestUrl) { |
| 402 | + fetch(manifestUrl, { cache: "no-cache" }) |
| 403 | + .then(function(response) { |
| 404 | + if (!response.ok) { |
| 405 | + throw new Error("manifest fetch failed: " + response.status); |
| 406 | + } |
| 407 | + return response.json(); |
| 408 | + }) |
| 409 | + .then(populateFromManifest) |
| 410 | + .catch(function() { /* keep server-rendered fallback */ }); |
| 411 | + } |
337 | 412 | }); |
338 | 413 | })(); |
339 | 414 | </script></div> |
|
489 | 564 | data-current-version="dev" |
490 | 565 | data-current-label="dev" |
491 | 566 | data-target-uri="_modules/index.html" |
| 567 | + data-site-root="https://pgmpy.org" |
| 568 | + data-manifest-url="https://pgmpy.org/versions.json" |
492 | 569 | > |
493 | 570 |
|
494 | 571 |
|
|
531 | 608 | const currentVersion = select.dataset.currentVersion; |
532 | 609 | const currentLabel = select.dataset.currentLabel || currentVersion; |
533 | 610 | const currentTargetUri = (select.dataset.targetUri || "").replace(/^\/+/, ""); |
| 611 | + const siteRoot = (select.dataset.siteRoot || "").replace(/\/+$/, ""); |
| 612 | + const manifestUrl = select.dataset.manifestUrl; |
534 | 613 |
|
535 | 614 | if (!Array.from(select.options).some(function(option) { return option.value === currentVersion; })) { |
536 | 615 | const option = document.createElement("option"); |
|
541 | 620 | } |
542 | 621 |
|
543 | 622 | const buildTargetUrl = function(baseUrl) { |
| 623 | + const normalized = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/"; |
544 | 624 | if (!currentTargetUri || currentTargetUri === "index.html") { |
545 | | - return baseUrl; |
| 625 | + return normalized; |
546 | 626 | } |
547 | | - return new URL(currentTargetUri, baseUrl).toString(); |
| 627 | + return new URL(currentTargetUri, normalized).toString(); |
548 | 628 | }; |
549 | 629 |
|
550 | 630 | const navigateToVersion = async function(option) { |
|
553 | 633 | return; |
554 | 634 | } |
555 | 635 |
|
556 | | - const targetUrl = buildTargetUrl(baseUrl); |
| 636 | + const normalized = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/"; |
| 637 | + const targetUrl = buildTargetUrl(normalized); |
557 | 638 |
|
558 | | - if (targetUrl === baseUrl) { |
559 | | - window.location.href = baseUrl; |
| 639 | + if (targetUrl === normalized) { |
| 640 | + window.location.href = normalized; |
560 | 641 | return; |
561 | 642 | } |
562 | 643 |
|
563 | 644 | try { |
564 | 645 | const response = await fetch(targetUrl, { method: "HEAD" }); |
565 | | - window.location.href = response.ok ? targetUrl : baseUrl; |
| 646 | + window.location.href = response.ok ? targetUrl : normalized; |
566 | 647 | } catch (error) { |
567 | 648 | window.location.href = targetUrl; |
568 | 649 | } |
|
575 | 656 | } |
576 | 657 | navigateToVersion(option); |
577 | 658 | }); |
| 659 | + |
| 660 | + const populateFromManifest = function(manifest) { |
| 661 | + if (!siteRoot) { |
| 662 | + return; |
| 663 | + } |
| 664 | + |
| 665 | + const stableName = manifest && manifest.stable; |
| 666 | + const releases = manifest && Array.isArray(manifest.releases) ? manifest.releases : []; |
| 667 | + const development = manifest && Array.isArray(manifest.development) ? manifest.development : []; |
| 668 | + |
| 669 | + const fragment = document.createDocumentFragment(); |
| 670 | + |
| 671 | + const appendOption = function(group, value, textContent, url) { |
| 672 | + const option = document.createElement("option"); |
| 673 | + option.value = value; |
| 674 | + option.textContent = textContent; |
| 675 | + option.dataset.url = url; |
| 676 | + if (value === currentVersion) { |
| 677 | + option.selected = true; |
| 678 | + } |
| 679 | + group.appendChild(option); |
| 680 | + }; |
| 681 | + |
| 682 | + if (stableName || releases.length) { |
| 683 | + const releasesGroup = document.createElement("optgroup"); |
| 684 | + releasesGroup.label = "Releases"; |
| 685 | + if (stableName) { |
| 686 | + appendOption(releasesGroup, "stable", stableName + " (stable)", siteRoot + "/"); |
| 687 | + } |
| 688 | + releases.forEach(function(name) { |
| 689 | + appendOption(releasesGroup, name, name, siteRoot + "/" + name + "/"); |
| 690 | + }); |
| 691 | + fragment.appendChild(releasesGroup); |
| 692 | + } |
| 693 | + |
| 694 | + if (development.length) { |
| 695 | + const developmentGroup = document.createElement("optgroup"); |
| 696 | + developmentGroup.label = "In Development"; |
| 697 | + development.forEach(function(name) { |
| 698 | + appendOption(developmentGroup, name, name, siteRoot + "/" + name + "/"); |
| 699 | + }); |
| 700 | + fragment.appendChild(developmentGroup); |
| 701 | + } |
| 702 | + |
| 703 | + const hasCurrent = Array.from(fragment.querySelectorAll("option")).some(function(option) { |
| 704 | + return option.value === currentVersion; |
| 705 | + }); |
| 706 | + if (!hasCurrent) { |
| 707 | + const option = document.createElement("option"); |
| 708 | + option.value = currentVersion; |
| 709 | + option.textContent = currentLabel; |
| 710 | + option.selected = true; |
| 711 | + fragment.insertBefore(option, fragment.firstChild); |
| 712 | + } |
| 713 | + |
| 714 | + select.replaceChildren(fragment); |
| 715 | + }; |
| 716 | + |
| 717 | + if (manifestUrl) { |
| 718 | + fetch(manifestUrl, { cache: "no-cache" }) |
| 719 | + .then(function(response) { |
| 720 | + if (!response.ok) { |
| 721 | + throw new Error("manifest fetch failed: " + response.status); |
| 722 | + } |
| 723 | + return response.json(); |
| 724 | + }) |
| 725 | + .then(populateFromManifest) |
| 726 | + .catch(function() { /* keep server-rendered fallback */ }); |
| 727 | + } |
578 | 728 | }); |
579 | 729 | })(); |
580 | 730 | </script></div> |
|
0 commit comments