😎 Give your xaringan slides some style
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

225 lines
6.1KB

  1. ;(function () {
  2. function findPkgdownGlobalRoot () {
  3. const origin = window.location.origin
  4. const path = window.location.pathname.replace(/[^/]+$/, '')
  5. // Special cases supported by our versioned pkgdown workflow
  6. const specials = [/dev\//, /preview\//, /v\d+\.\d+\.\d+\//]
  7. for (const special of specials) {
  8. if (special.test(path)) {
  9. return origin + path.split(special)[0]
  10. }
  11. }
  12. const pkgdownDirs = ['articles', 'news', 'reference']
  13. for (const pkgdownDir of pkgdownDirs) {
  14. if (path.includes(pkgdownDir)) {
  15. return origin + path.split(`${pkgdownDir}/`)[0]
  16. }
  17. }
  18. return origin + path
  19. }
  20. function pathDir (url) {
  21. return url.replace(/\/[^/]+$/, '/')
  22. }
  23. function ensureTrailingSlash (url) {
  24. return /\/$/.test(url) ? url : url + '/'
  25. }
  26. function ensureFullPath (url) {
  27. return /^\//.test(url) ? window.location.origin + url : url
  28. }
  29. function findPkgdownLocalRoot () {
  30. // get `src` attribute of the current <script> tag
  31. const scripts = document.getElementsByTagName('script')
  32. const currentScript = scripts[scripts.length - 1]
  33. let src = pathDir(currentScript.getAttribute('src'))
  34. if (!src.includes('/') || src === '/') {
  35. src = ''
  36. }
  37. const currentDir = pathDir(window.location.href)
  38. const root = new URL(currentDir + src).toString()
  39. return ensureTrailingSlash(root)
  40. }
  41. function makeNewPkgdownLink (newBase) {
  42. newBase = ensureFullPath(newBase)
  43. newBase = ensureTrailingSlash(newBase)
  44. return window.location.href.replace(findPkgdownLocalRoot(), newBase)
  45. }
  46. async function getVersions () {
  47. let versionsUrl
  48. if (window.PKGDOWN_VERSIONS_URL) {
  49. versionsUrl = window.PKGDOWN_VERSIONS_URL
  50. } else {
  51. let pkgdownRoot = findPkgdownGlobalRoot()
  52. if (!/\/$/.test(pkgdownRoot)) {
  53. pkgdownRoot += '/'
  54. }
  55. versionsUrl = pkgdownRoot + 'doc-versions.json'
  56. }
  57. try {
  58. const response = await fetch(versionsUrl)
  59. return response.json()
  60. } catch {
  61. return null
  62. }
  63. }
  64. function createVersionDropdown (current, versions) {
  65. if (typeof versions === 'string') {
  66. console.error(
  67. '`doc-versions.json` should be an array or object, not a string'
  68. )
  69. return
  70. }
  71. const dropdown = document.createElement('ul')
  72. dropdown.classList.add('navbar-nav')
  73. const li = document.createElement('li')
  74. li.classList.add('nav-item', 'dropdown')
  75. dropdown.appendChild(li)
  76. const a = document.createElement('a')
  77. a.classList.add('nav-link', 'dropdown-toggle')
  78. if (current.matches('.text-danger')) {
  79. a.classList.add('text-danger')
  80. }
  81. a.href = '#'
  82. a.role = 'button'
  83. a.dataset.bsToggle = 'dropdown'
  84. a.ariaExpanded = false
  85. a.innerText = current.innerText
  86. li.appendChild(a)
  87. const ul = document.createElement('ul')
  88. ul.classList.add('dropdown-menu')
  89. li.appendChild(ul)
  90. if (versions.constructor === Object) {
  91. versions = [versions]
  92. }
  93. versions.forEach(item => {
  94. if (item === '---') {
  95. ul.appendChild(createVersionDropdownDivider())
  96. return
  97. }
  98. // if item is a string, it is a header
  99. if (typeof item === 'string') {
  100. ul.appendChild(createVersionDropdownHeader(item))
  101. return
  102. }
  103. const version = item.version ? item.version : item.text.replace(/^v/, '')
  104. const isCurrent = current.innerText === version
  105. ul.appendChild(createVersionDropdownItem(item, isCurrent))
  106. })
  107. return dropdown
  108. }
  109. function createVersionDropdownItem ({ text, url }, isCurrent = false) {
  110. const li = document.createElement('li')
  111. const a = document.createElement('a')
  112. a.classList.add('dropdown-item')
  113. if (isCurrent) a.classList.add('active')
  114. // link to current page in the other version (may not exist!)
  115. a.href = makeNewPkgdownLink(url)
  116. a.innerText = text
  117. li.appendChild(a)
  118. return li
  119. }
  120. function createVersionDropdownDivider () {
  121. // <li><hr class="dropdown-divider"></li>
  122. const li = document.createElement('li')
  123. const hr = document.createElement('hr')
  124. hr.classList.add('dropdown-divider')
  125. li.appendChild(hr)
  126. return li
  127. }
  128. function createVersionDropdownHeader (text) {
  129. // <li><h6 class="dropdown-header">Dropdown header</h6></li>
  130. const li = document.createElement('li')
  131. const h6 = document.createElement('h6')
  132. h6.classList.add('dropdown-header')
  133. h6.innerText = text
  134. li.appendChild(h6)
  135. return li
  136. }
  137. function insertBanner (banner) {
  138. if (!banner) return
  139. const main = document.querySelector('main')
  140. if (!main) return
  141. let { html, class: classes } = banner
  142. if (typeof classes === 'string') {
  143. // Classes can be a string or an array of strings
  144. classes = [classes]
  145. }
  146. // <div class="d-block px-3 py-2 text-center text-bold skippy">
  147. // <a href="https://getbootstrap.com/" class="text-white text-decoration-none">There's a newer version of Bootstrap!</a>
  148. // </div>
  149. const div = document.createElement('div')
  150. div.classList.add('alert', 'px-3', 'py-2', 'text-center', ...classes)
  151. div.innerHTML = html
  152. div.querySelectorAll('a').forEach(a => {
  153. if (!a.hasAttribute('href')) {
  154. a.href = makeNewPkgdownLink(findPkgdownGlobalRoot())
  155. }
  156. })
  157. main.insertAdjacentElement('afterbegin', div)
  158. return div
  159. }
  160. function maybeInsertBanner (versions) {
  161. if (!versions) return
  162. if (!Array.isArray(versions)) return
  163. // keep versions entries that are objects with a `banner` property
  164. versions = versions.filter(item => item && item.banner)
  165. const localRoot = findPkgdownLocalRoot()
  166. for (const version of versions) {
  167. const versionUrl = ensureFullPath(version.url)
  168. if (localRoot === versionUrl) {
  169. return insertBanner(version.banner)
  170. }
  171. }
  172. }
  173. async function replaceVersionWithMenu () {
  174. const current = document.querySelector('.navbar .navbar-brand + small')
  175. if (!current) return
  176. const versions = await getVersions()
  177. if (!versions) return
  178. const dropdown = createVersionDropdown(current, versions)
  179. current.replaceWith(dropdown)
  180. maybeInsertBanner(versions)
  181. }
  182. replaceVersionWithMenu()
  183. })()