docsify-init.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. let clink = null;
  2. if (window.DOCSIFY_ROUTER_MODE === "history") {
  3. clink = Docsify.dom.create("link");
  4. clink.rel = "canonical";
  5. Docsify.dom.appendTo(Docsify.dom.head, clink);
  6. }
  7. const documentTitleBase = document.title;
  8. const linksMenu = '<div class="links-menu">' +
  9. '<a href="https://imgproxy.net" target="_blank" title="Website"><img src="/assets/website.svg" /></a>' +
  10. '<a href="https://github.com/imgproxy" target="_blank" title="GitHub"><img src="/assets/github.svg" /></a>' +
  11. '<a href="https://twitter.com/imgproxy_net" target="_blank" title="Twitter"><img src="/assets/twitter.svg" /></a>' +
  12. '<a href="https://discord.gg/5GgpXgtC9u" target="_blank" title="Discord"><img src="/assets/discord.svg" /></a>' +
  13. '<a href="https://github.com/sponsors/imgproxy" target="_blank" title="Sponsor"><img src="/assets/heart.svg" /></a>' +
  14. '</div>';
  15. const docEditBase = 'https://github.com/imgproxy/imgproxy/edit/master/docs/';
  16. const proBadge = Docsify.dom.create("img");
  17. proBadge.setAttribute("src", "/assets/pro.svg");
  18. proBadge.setAttribute("title", "This feature is available in imgproxy Pro");
  19. const proBadgeRegex = /\!\[pro\]\((\S+)\)/g;
  20. const proLink = `<a class="badge" href="https://imgproxy.net/#pro" target="_blank">${proBadge.outerHTML}</a>`;
  21. const oldProBadge = "<i class='badge badge-pro'></i>";
  22. const configRegex = /^\* `([^`]+)`:/gm;
  23. const copyCodeBtn = '<button class="copy-code" title="Copy code"></button>';
  24. const defaultVersions = [["latest", "latest"]];
  25. const configureDocsify = (additionalVersions, latestVersion, latestTag) => {
  26. const versions = defaultVersions.concat(additionalVersions);
  27. const versionAliases = {};
  28. const versionSelect = ['<div class="sidebar-version-select"><select id="version-selector" name="version">'];
  29. versions.forEach(([version, tag]) => {
  30. const value = version == latestVersion ? "" : version;
  31. versionSelect.push(`<option value="${value}">${version}</value>`);
  32. if (version !== "latest") {
  33. versionAliases[`/${version}/(.*)`] =
  34. `https://raw.githubusercontent.com/imgproxy/imgproxy/${tag}/docs/$1`;
  35. versionAliases[`/${version}/`] =
  36. `https://raw.githubusercontent.com/imgproxy/imgproxy/${tag}/docs/README.md`;
  37. }
  38. });
  39. versionSelect.push('</select></div>');
  40. if (latestTag === "latest") latestTag = "master";
  41. window.$docsify = {
  42. name: '<a id="home-link" class="app-name-link" href="/"><img src="/assets/logo.svg"></a>' +
  43. linksMenu +
  44. versionSelect.join(""),
  45. nameLink: false,
  46. loadSidebar: true,
  47. relativePath: true,
  48. subMaxLevel: 3,
  49. auto2top: true,
  50. routerMode: window.DOCSIFY_ROUTER_MODE || "hash",
  51. noEmoji: true,
  52. alias: Object.assign(versionAliases, {
  53. '/latest/': 'README.md',
  54. '/latest/(.*)': '$1',
  55. '/([0-9]+\.[0-9]+)/(.*)': 'https://raw.githubusercontent.com/imgproxy/imgproxy/v$1.0/docs/$2',
  56. '/([0-9]+\.[0-9]+)/': 'https://raw.githubusercontent.com/imgproxy/imgproxy/v$1.0/docs/README.md',
  57. '/(.*)': `https://raw.githubusercontent.com/imgproxy/imgproxy/${latestTag}/docs/$1`,
  58. '/': `https://raw.githubusercontent.com/imgproxy/imgproxy/${latestTag}/docs/README.md`,
  59. }),
  60. search: {
  61. namespace: 'docs-imgproxy',
  62. depth: 6,
  63. // pathNamespaces: versions.map(v => "/" + v[0]),
  64. pathNamespaces: /^(\/(latest|([0-9]+\.[0-9]+)))?/,
  65. },
  66. namespaces: [
  67. {
  68. id: "version",
  69. values: versions.map(v => v[0]),
  70. optional: true,
  71. selector: "#version-selector",
  72. }
  73. ],
  74. plugins: window.$docsify.plugins.concat([
  75. (hook, vm) => {
  76. window.DocsifyVM = vm;
  77. hook.beforeEach(() => {
  78. if (clink)
  79. clink.href = "https://docs.imgproxy.net" + vm.route.path;
  80. });
  81. hook.doneEach(() => {
  82. const appNameLink = Docsify.dom.find("#home-link");
  83. if (!appNameLink) return;
  84. appNameLink.href = vm.config.currentNamespace;
  85. });
  86. hook.doneEach(() => {
  87. if (document.title != documentTitleBase)
  88. document.title += " | " + documentTitleBase;
  89. });
  90. hook.afterEach(html => {
  91. const docName = vm.route.file.replace(
  92. /https\:\/\/raw.githubusercontent\.com\/(.*)\/docs\//, ''
  93. );
  94. if (!docName) return html;
  95. const editButton = '<a class="github-edit-btn" title="Edit on GitHub" href="' +
  96. docEditBase + docName +
  97. '" target="_blank">' +
  98. 'Edit on <strong>GitHub</strong>' +
  99. '</a>';
  100. return html + editButton;
  101. })
  102. hook.beforeEach((content, next) => {
  103. content = content
  104. .replaceAll(proBadgeRegex, proLink)
  105. .replaceAll(oldProBadge, proLink);
  106. content = content
  107. .replaceAll("📝", '<i class="icon icon-note"></i>')
  108. .replaceAll("⚠️", '<i class="icon icon-warn"></i>')
  109. .replaceAll("✅", '<i class="icon icon-check"></i>')
  110. .replaceAll("❌", '<i class="icon icon-cross"></i>')
  111. .replaceAll("⏳", '<i class="icon icon-hourglass"></i>');
  112. if (vm.route.path.endsWith('/configuration'))
  113. content = content.replaceAll(configRegex, '* <code id="$1">$1</code>:');
  114. next(content);
  115. })
  116. hook.doneEach(() => {
  117. const badges = Docsify.dom.findAll(".sidebar .badge-pro");
  118. badges.forEach(b => { b.replaceWith(proBadge.cloneNode()) });
  119. // Docsify cuts off "target" sometimes
  120. const links = Docsify.dom.findAll("a.badge");
  121. links.forEach(l => { l.setAttribute("target", "_blank") });
  122. const codeBlocks = Docsify.dom.findAll('pre[data-lang]');
  123. codeBlocks.forEach(elm =>
  124. elm.insertAdjacentHTML('beforeend', copyCodeBtn));
  125. })
  126. hook.mounted(() => {
  127. const content = Docsify.dom.find('.content');
  128. content.addEventListener('click', function(e) {
  129. if (!e.target.classList.contains('copy-code'))
  130. return;
  131. const btn = e.target;
  132. const code = Docsify.dom.find(btn.parentNode, 'code');
  133. navigator.clipboard.writeText(code.innerText).then(() => {
  134. btn.classList.add('copy-code-success');
  135. setTimeout(() => {
  136. btn.classList.remove('copy-code-success');
  137. }, 1500);
  138. }).catch((err) =>{
  139. console.log(`Can't copy code: ${err}`);
  140. btn.classList.add('copy-code-error');
  141. setTimeout(() => {
  142. btn.classList.remove('copy-code-error');
  143. }, 1500);
  144. });
  145. });
  146. })
  147. }
  148. ])
  149. }
  150. }
  151. const initDocsify = (versions, latestVersion, latestTag) => {
  152. configureDocsify(versions, latestVersion, latestTag);
  153. window.runDocsify();
  154. };
  155. const VERSIONS_KEY = "imgproxy.versions";
  156. const VERSIONS_ETAG_KEY = "imgproxy.versions.etag";
  157. let latestVersion = "latest";
  158. let latestTag = "latest";
  159. let storedVersions = [];
  160. let storedVersionsJson = localStorage.getItem(VERSIONS_KEY);
  161. let storedVersionsEtag = localStorage.getItem(VERSIONS_ETAG_KEY);
  162. if (storedVersionsJson) {
  163. try {
  164. storedVersions = JSON.parse(storedVersionsJson);
  165. } catch {
  166. storedVersions = [];
  167. }
  168. }
  169. if (storedVersions?.length)
  170. [latestVersion, latestTag] = storedVersions[0];
  171. else {
  172. // Just in case storedVersions is not an array
  173. storedVersions = [];
  174. storedVersionsEtag = null;
  175. }
  176. fetch(
  177. "https://api.github.com/repos/imgproxy/imgproxy/releases",
  178. {
  179. headers: {
  180. "Accept": "application/json",
  181. "If-None-Match": storedVersionsEtag,
  182. },
  183. },
  184. ).then((resp) => {
  185. if (resp.status === 304) {
  186. initDocsify(storedVersions, latestVersion, latestTag);
  187. return;
  188. }
  189. if (resp.status != 200)
  190. throw new Error(`Can't fetch imgproxy versions: ${resp.statusText}`);
  191. resp.json().then((data) => {
  192. const uniq = {};
  193. const fetchedVersions = [];
  194. data.forEach((release) => {
  195. if (release.draft || release.prerelease) return;
  196. var tag = release.tag_name;
  197. var matches = tag?.match(/^v([0-9]+\.[0-9]+)/);
  198. if (!matches?.length) return;
  199. var version = matches[1];
  200. if (uniq[version]) return;
  201. fetchedVersions.push([version, tag]);
  202. uniq[version] = true;
  203. });
  204. if (fetchedVersions.length)
  205. [latestVersion, latestTag] = fetchedVersions[0];
  206. localStorage.setItem(VERSIONS_KEY, JSON.stringify(fetchedVersions));
  207. localStorage.setItem(VERSIONS_ETAG_KEY, resp.headers.get("Etag"));
  208. initDocsify(fetchedVersions, latestVersion, latestTag);
  209. }).catch((e) => {
  210. initDocsify(storedVersions, latestVersion, latestTag);
  211. throw e;
  212. });
  213. }).catch((e) => {
  214. initDocsify(storedVersions, latestVersion, latestTag);
  215. throw e;
  216. });