Skip to content

Commit 762c0ad

Browse files
committed
Dynamically fetch versions in docs
1 parent 0d4aee3 commit 762c0ad

7 files changed

+223
-155
lines changed

.lefthook/pre-push/check-docs-versions

-19
This file was deleted.

docs/assets/docsify-init.js

+210-110
Original file line numberDiff line numberDiff line change
@@ -1,126 +1,226 @@
1+
let clink = null;
2+
13
if (window.DOCSIFY_ROUTER_MODE === "history") {
2-
var clink = document.createElement("link")
3-
clink.rel = "canonical"
4-
document.getElementsByTagName("head")[0].appendChild(clink)
4+
clink = Docsify.dom.create("link");
5+
clink.rel = "canonical";
6+
Docsify.dom.appendTo(Docsify.dom.head, clink);
57
}
68

7-
var documentTitleBase = document.title;
9+
const documentTitleBase = document.title;
810

9-
var linksMenu = '<div class="links-menu">' +
11+
const linksMenu = '<div class="links-menu">' +
1012
'<a href="https://imgproxy.net" target="_blank" title="Website"><img src="/assets/website.svg" /></a>' +
1113
'<a href="https://github/imgproxy" target="_blank" title="GitHub"><img src="/assets/github.svg" /></a>' +
1214
'<a href="https://twitter.com/imgproxy_net" target="_blank" title="Twitter"><img src="/assets/twitter.svg" /></a>' +
1315
'<a href="https://discord.gg/5GgpXgtC9u" target="_blank" title="Discord"><img src="/assets/discord.svg" /></a>' +
1416
'</div>';
1517

16-
var docEditBase = 'https://github.com/imgproxy/imgproxy/edit/master/docs/';
18+
const docEditBase = 'https://github.com/imgproxy/imgproxy/edit/master/docs/';
1719

18-
var proBadge = document.createElement("img")
19-
proBadge.setAttribute("src", "/assets/pro.svg")
20-
proBadge.setAttribute("title", "This feature is available in imgproxy Pro")
20+
const proBadge = Docsify.dom.create("img");
21+
proBadge.setAttribute("src", "/assets/pro.svg");
22+
proBadge.setAttribute("title", "This feature is available in imgproxy Pro");
2123

22-
var proBadgeRegex = /\!\[pro\]\((\S+)\)/g;
23-
var proLink = '<a class="badge" href="https://imgproxy.net/#pro" target="_blank">' +
24-
proBadge.outerHTML + '</a>';
24+
const proBadgeRegex = /\!\[pro\]\((\S+)\)/g;
25+
const proLink = `<a class="badge" href="https://imgproxy.net/#pro" target="_blank">${proBadge.outerHTML}</a>`;
2526

26-
var oldProBadge = "<i class='badge badge-pro'></i>";
27+
const oldProBadge = "<i class='badge badge-pro'></i>";
2728

28-
var versions = ["latest"].concat(window.IMGPROXY_VERSIONS);
29-
var latestVersion = window.IMGPROXY_VERSIONS[0];
30-
var versionSelect = '<select id="version-selector" name="version" class="sidebar-version-select">';
31-
versions.forEach(function (version) {
32-
var value = version == latestVersion ? "" : version;
33-
versionSelect = versionSelect + '<option value="' + value + '">' + version + '</value>';
34-
});
35-
versionSelect = versionSelect + '</select>';
36-
37-
window.$docsify = {
38-
name: '<a id="home-link" class="app-name-link" href="/"><img src="/assets/logo.svg"></a>' +
39-
linksMenu +
40-
versionSelect,
41-
nameLink: false,
42-
loadSidebar: true,
43-
relativePath: true,
44-
subMaxLevel: 3,
45-
auto2top: true,
46-
routerMode: window.DOCSIFY_ROUTER_MODE || "hash",
47-
noEmoji: true,
48-
alias: {
49-
'/latest/': 'README.md',
50-
'/latest/(.*)': '$1',
51-
'/([0-9]+\.[0-9]+)/(.*)': 'https://raw.githubusercontent.com/imgproxy/imgproxy/v$1.0/docs/$2',
52-
'/([0-9]+\.[0-9]+)/': 'https://raw.githubusercontent.com/imgproxy/imgproxy/v$1.0/docs/README.md',
53-
'/(.*)': 'https://raw.githubusercontent.com/imgproxy/imgproxy/v' + latestVersion + '.0/docs/$1',
54-
'/': 'https://raw.githubusercontent.com/imgproxy/imgproxy/v' + latestVersion + '.0/docs/README.md',
55-
},
56-
search: {
57-
namespace: 'docs-imgproxy',
58-
depth: 6,
59-
pathNamespaces: versions.map(function (v) { return "/" + v })
60-
},
61-
namespaces: [
62-
{
63-
id: "version",
64-
values: versions,
65-
optional: true,
66-
selector: "#version-selector"
67-
}
68-
],
69-
plugins: [
70-
function (hook, vm) {
71-
window.DocsifyVM = vm
72-
hook.beforeEach(function () {
73-
if (clink) {
74-
clink.href = "https://docs.imgproxy.net" + vm.route.path
75-
}
76-
});
77-
78-
hook.doneEach(function () {
79-
var appNameLink = Docsify.dom.find("#home-link");
80-
81-
if (!appNameLink) return;
82-
83-
appNameLink.href = vm.config.currentNamespace;
84-
});
85-
86-
hook.doneEach(function() {
87-
if (document.title != documentTitleBase)
88-
document.title += " | " + documentTitleBase;
89-
});
90-
91-
92-
hook.afterEach(function (html) {
93-
var docName = vm.route.file.replace(
94-
/https\:\/\/raw.githubusercontent\.com\/(.*)\/docs\//, ''
95-
)
96-
97-
if (!docName) {
98-
return html;
99-
}
100-
101-
var editButton = '<a class="github-edit-btn" title="Edit on GitHub" href="' +
102-
docEditBase + docName +
103-
'" target="_blank">' +
104-
'Edit on <strong>GitHub</strong>' +
105-
'</a>';
106-
107-
return html + editButton
108-
})
109-
110-
hook.beforeEach(function (content, next) {
111-
content = content.replaceAll(proBadgeRegex, proLink)
112-
content = content.replaceAll(oldProBadge, proLink)
113-
next(content)
114-
})
115-
116-
hook.doneEach(function () {
117-
var badges = Docsify.dom.findAll(".sidebar .badge-pro")
118-
badges.forEach(function (b) { b.replaceWith(proBadge.cloneNode()) })
119-
120-
// Docsify cuts off "target" sometimes
121-
var links = Docsify.dom.findAll("a.badge")
122-
links.forEach(function(l){ l.setAttribute("target", "_blank") })
123-
})
29+
const defaultVersions = [["latest", "latest"]];
30+
31+
const configureDocsify = (additionalVersions, latestVersion, latestTag) => {
32+
const versions = defaultVersions.concat(additionalVersions);
33+
34+
const versionAliases = {};
35+
36+
const versionSelect = ['<select id="version-selector" name="version" class="sidebar-version-select">'];
37+
versions.forEach(([version, tag]) => {
38+
const value = version == latestVersion ? "" : version;
39+
versionSelect.push(`<option value="${value}">${version}</value>`);
40+
41+
if (version !== "latest") {
42+
versionAliases[`/${version}/(.*)`] =
43+
`https://raw.githubusercontent.com/imgproxy/imgproxy/${tag}/docs/$1`;
44+
versionAliases[`/${version}/`] =
45+
`https://raw.githubusercontent.com/imgproxy/imgproxy/${tag}/docs/README.md`;
12446
}
125-
]
47+
});
48+
versionSelect.push('</select>');
49+
50+
if (latestTag === "latest") latestTag = "master";
51+
52+
window.$docsify = {
53+
name: '<a id="home-link" class="app-name-link" href="/"><img src="/assets/logo.svg"></a>' +
54+
linksMenu +
55+
versionSelect.join(""),
56+
nameLink: false,
57+
loadSidebar: true,
58+
relativePath: true,
59+
subMaxLevel: 3,
60+
auto2top: true,
61+
routerMode: window.DOCSIFY_ROUTER_MODE || "hash",
62+
noEmoji: true,
63+
alias: Object.assign(versionAliases, {
64+
'/latest/': 'README.md',
65+
'/latest/(.*)': '$1',
66+
'/([0-9]+\.[0-9]+)/(.*)': 'https://raw.githubusercontent.com/imgproxy/imgproxy/v$1.0/docs/$2',
67+
'/([0-9]+\.[0-9]+)/': 'https://raw.githubusercontent.com/imgproxy/imgproxy/v$1.0/docs/README.md',
68+
'/(.*)': `https://raw.githubusercontent.com/imgproxy/imgproxy/${latestTag}/docs/$1`,
69+
'/': `https://raw.githubusercontent.com/imgproxy/imgproxy/${latestTag}/docs/README.md`,
70+
}),
71+
search: {
72+
namespace: 'docs-imgproxy',
73+
depth: 6,
74+
// pathNamespaces: versions.map(v => "/" + v[0]),
75+
pathNamespaces: /^(\/(latest|([0-9]+\.[0-9]+)))?/,
76+
},
77+
namespaces: [
78+
{
79+
id: "version",
80+
values: versions.map(v => v[0]),
81+
optional: true,
82+
selector: "#version-selector",
83+
}
84+
],
85+
plugins: window.$docsify.plugins.concat([
86+
(hook, vm) => {
87+
window.DocsifyVM = vm;
88+
89+
hook.beforeEach(() => {
90+
if (clink)
91+
clink.href = "https://docs.imgproxy.net" + vm.route.path;
92+
});
93+
94+
hook.doneEach(() => {
95+
const appNameLink = Docsify.dom.find("#home-link");
96+
97+
if (!appNameLink) return;
98+
99+
appNameLink.href = vm.config.currentNamespace;
100+
});
101+
102+
hook.doneEach(() => {
103+
if (document.title != documentTitleBase)
104+
document.title += " | " + documentTitleBase;
105+
});
106+
107+
108+
hook.afterEach(html => {
109+
const docName = vm.route.file.replace(
110+
/https\:\/\/raw.githubusercontent\.com\/(.*)\/docs\//, ''
111+
);
112+
113+
if (!docName) return html;
114+
115+
const editButton = '<a class="github-edit-btn" title="Edit on GitHub" href="' +
116+
docEditBase + docName +
117+
'" target="_blank">' +
118+
'Edit on <strong>GitHub</strong>' +
119+
'</a>';
120+
121+
return html + editButton;
122+
})
123+
124+
hook.beforeEach((content, next) => {
125+
content = content.replaceAll(proBadgeRegex, proLink);
126+
content = content.replaceAll(oldProBadge, proLink);
127+
next(content);
128+
})
129+
130+
hook.doneEach(() => {
131+
const badges = Docsify.dom.findAll(".sidebar .badge-pro");
132+
badges.forEach(b => { b.replaceWith(proBadge.cloneNode()) });
133+
134+
// Docsify cuts off "target" sometimes
135+
const links = Docsify.dom.findAll("a.badge");
136+
links.forEach(l => { l.setAttribute("target", "_blank") });
137+
})
138+
}
139+
])
140+
}
141+
}
142+
143+
const initDocsify = (versions, latestVersion, latestTag) => {
144+
configureDocsify(versions, latestVersion, latestTag);
145+
window.runDocsify();
146+
};
147+
148+
const VERSIONS_KEY = "imgproxy.versions";
149+
const VERSIONS_ETAG_KEY = "imgproxy.versions.etag";
150+
151+
let latestVersion = "latest";
152+
let latestTag = "latest";
153+
154+
let storedVersions = [];
155+
let storedVersionsJson = localStorage.getItem(VERSIONS_KEY);
156+
let storedVersionsEtag = localStorage.getItem(VERSIONS_ETAG_KEY);
157+
158+
if (storedVersionsJson) {
159+
try {
160+
storedVersions = JSON.parse(storedVersionsJson);
161+
} catch {
162+
storedVersions = [];
163+
}
164+
}
165+
166+
if (storedVersions?.length)
167+
[latestVersion, latestTag] = storedVersions[0];
168+
else {
169+
// Just in case storedVersions is not an array
170+
storedVersions = [];
171+
storedVersionsEtag = null;
126172
}
173+
174+
fetch(
175+
"https://api.github.com/repos/imgproxy/imgproxy/releases",
176+
{
177+
headers: {
178+
"Accept": "application/json",
179+
"If-None-Match": storedVersionsEtag,
180+
},
181+
},
182+
).then((resp) => {
183+
if (resp.status === 304) {
184+
initDocsify(storedVersions, latestVersion, latestTag);
185+
return;
186+
}
187+
188+
if (resp.status != 200)
189+
throw new Error(`Can't fetch imgproxy versions: ${resp.statusText}`);
190+
191+
resp.json().then((data) => {
192+
const uniq = {};
193+
const fetchedVersions = [];
194+
195+
data.forEach((release) => {
196+
if (release.draft || release.prerelease) return;
197+
198+
var tag = release.tag_name;
199+
var matches = tag?.match(/^v([0-9]+\.[0-9]+)/);
200+
201+
if (!matches?.length) return;
202+
203+
var version = matches[1];
204+
205+
if (uniq[version]) return;
206+
207+
fetchedVersions.push([version, tag]);
208+
uniq[version] = true;
209+
});
210+
211+
if (fetchedVersions.length)
212+
[latestVersion, latestTag] = fetchedVersions[0];
213+
214+
localStorage.setItem(VERSIONS_KEY, JSON.stringify(fetchedVersions));
215+
localStorage.setItem(VERSIONS_ETAG_KEY, resp.headers.get("Etag"));
216+
217+
initDocsify(fetchedVersions, latestVersion, latestTag);
218+
219+
}).catch((e) => {
220+
initDocsify(storedVersions, latestVersion, latestTag);
221+
throw e;
222+
});
223+
}).catch((e) => {
224+
initDocsify(storedVersions, latestVersion, latestTag);
225+
throw e;
226+
});

docs/assets/docsify.min.20230513.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/assets/docsify.search.min.20230513.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/assets/versions.js

-20
This file was deleted.

0 commit comments

Comments
 (0)