Versionable APIs #283
8 changed files with 202 additions and 95 deletions
|
@ -10,9 +10,9 @@ import html from "choo/html";
|
|||
|
||||
// E X P O R T
|
||||
|
||||
export default () => html`
|
||||
export default version => html`
|
||||
<div class="api-content__body">
|
||||
<h2>lbrycrd APIs</h2>
|
||||
<h2>lbrycrd ${version}</h2>
|
||||
<p>Methods and signatures provided by the <a href="/glossary#lbrycrd">lbrycrd</a> blockchain daemon are documented below. To build, download, or run lbrycrd, see the project <a href="https://github.com/lbryio/lbrycrd/blob/master/README.md">README</a>.</p>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ import html from "choo/html";
|
|||
|
||||
// E X P O R T
|
||||
|
||||
export default () => html`
|
||||
export default version => html`
|
||||
<div class="api-content__body">
|
||||
<h2>lbry-sdk APIs</h2>
|
||||
<h2>lbry-sdk ${version}</h2>
|
||||
<p>Methods and signatures provided by the <a href="/glossary#lbry-sdk">lbry-sdk</a> daemon are documented below. To build, download, or run the daemon, see the project <a href="https://github.com/lbryio/lbry-sdk/blob/master/README.md">README</a>.</p>
|
||||
</div>
|
||||
|
||||
|
|
112
app/dist/scripts/api.js
vendored
112
app/dist/scripts/api.js
vendored
|
@ -1,67 +1,37 @@
|
|||
"use strict"; /* global document, Jets, window */
|
||||
"use strict"; /* global document, Jets, send, window */
|
||||
|
||||
|
||||
|
||||
// NOTE:
|
||||
// We declare `contentTag` and `jets` with `var` here so
|
||||
// when a visitor toggles the API page version, they are
|
||||
// not incorrectly declared multiple times via `let || const`
|
||||
|
||||
// Initiate search functionality
|
||||
const contentTag = window.location.pathname.split("/").pop() === "sdk" ?
|
||||
if (!contentTag)
|
||||
var contentTag;
|
||||
|
||||
contentTag = window.location.pathname.split("/").pop() === "sdk" ?
|
||||
".api-toc__section" :
|
||||
"#toc";
|
||||
|
||||
let jets = new Jets({
|
||||
if (!jets)
|
||||
var jets;
|
||||
|
||||
jets = new Jets({
|
||||
contentTag,
|
||||
searchTag: "#input-search"
|
||||
});
|
||||
|
||||
// Reset search on page load
|
||||
document.getElementById("input-search").value = "";
|
||||
|
||||
// Activate search
|
||||
document.getElementById("input-search").addEventListener("keyup", () => {
|
||||
if (document.getElementById("input-search").value)
|
||||
document.querySelector(".api-toc__search-clear").classList.add("active");
|
||||
else
|
||||
document.querySelector(".api-toc__search-clear").classList.remove("active");
|
||||
});
|
||||
|
||||
// Cancel search
|
||||
document.querySelector(".api-toc__search-clear").addEventListener("click", () => {
|
||||
document.getElementById("input-search").value = "";
|
||||
document.querySelector(".api-toc__search-clear").classList.remove("active");
|
||||
|
||||
jets.destroy();
|
||||
reinitJets();
|
||||
});
|
||||
|
||||
// Handle menu toggle for mobile
|
||||
if (document.getElementById("toggle-menu")) {
|
||||
document.getElementById("toggle-menu").addEventListener("click", () => {
|
||||
document.querySelector("body").classList.toggle("disable-scrolling");
|
||||
document.querySelector(".api-toc").classList.toggle("active");
|
||||
});
|
||||
|
||||
// Handle menu toggle when clicking on commands
|
||||
document.querySelectorAll(".api-toc__command a").forEach(command => {
|
||||
command.addEventListener("click", () => {
|
||||
document.querySelector("body").classList.remove("disable-scrolling");
|
||||
document.querySelector(".api-toc").classList.remove("active");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Code toggles
|
||||
handleApiLanguageToggles("cli");
|
||||
handleApiLanguageToggles("curl");
|
||||
handleApiLanguageToggles("lbrynet");
|
||||
handleApiLanguageToggles("python");
|
||||
|
||||
|
||||
|
||||
// H E L P E R S
|
||||
|
||||
function changeDocumentationVersion(value) {
|
||||
console.log(value);
|
||||
function changeDocumentationVersion(desiredVersion) { // eslint-disable-line no-unused-vars
|
||||
send({
|
||||
message: "view different documentation version",
|
||||
version: desiredVersion
|
||||
});
|
||||
}
|
||||
|
||||
function handleApiLanguageToggles(language) {
|
||||
|
@ -81,6 +51,50 @@ function handleApiLanguageToggles(language) {
|
|||
});
|
||||
}
|
||||
|
||||
function initializeApiFunctionality() { // eslint-disable-line no-unused-vars
|
||||
// Reset search on page load
|
||||
document.getElementById("input-search").value = "";
|
||||
|
||||
// Activate search
|
||||
document.getElementById("input-search").addEventListener("keyup", () => {
|
||||
if (document.getElementById("input-search").value)
|
||||
document.querySelector(".api-toc__search-clear").classList.add("active");
|
||||
else
|
||||
document.querySelector(".api-toc__search-clear").classList.remove("active");
|
||||
});
|
||||
|
||||
// Cancel search
|
||||
document.querySelector(".api-toc__search-clear").addEventListener("click", () => {
|
||||
document.getElementById("input-search").value = "";
|
||||
document.querySelector(".api-toc__search-clear").classList.remove("active");
|
||||
|
||||
jets.destroy();
|
||||
reinitJets();
|
||||
});
|
||||
|
||||
// Handle menu toggle for mobile
|
||||
if (document.getElementById("toggle-menu")) {
|
||||
document.getElementById("toggle-menu").addEventListener("click", () => {
|
||||
document.querySelector("body").classList.toggle("disable-scrolling");
|
||||
document.querySelector(".api-toc").classList.toggle("active");
|
||||
});
|
||||
|
||||
// Handle menu toggle when clicking on commands
|
||||
document.querySelectorAll(".api-toc__command a").forEach(command => {
|
||||
command.addEventListener("click", () => {
|
||||
document.querySelector("body").classList.remove("disable-scrolling");
|
||||
document.querySelector(".api-toc").classList.remove("active");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Code toggles
|
||||
handleApiLanguageToggles("cli");
|
||||
handleApiLanguageToggles("curl");
|
||||
handleApiLanguageToggles("lbrynet");
|
||||
handleApiLanguageToggles("python");
|
||||
}
|
||||
|
||||
function reinitJets() {
|
||||
jets = new Jets({
|
||||
contentTag,
|
||||
|
|
47
app/dist/scripts/app.js
vendored
47
app/dist/scripts/app.js
vendored
|
@ -4,6 +4,7 @@
|
|||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
scrollToElementOnLoad();
|
||||
initializeSmoothScroll();
|
||||
|
||||
// Automatically open external links in new tabs
|
||||
document.querySelectorAll("a[href^=http]").forEach(anchor => {
|
||||
|
@ -39,25 +40,27 @@ if (
|
|||
|
||||
|
||||
|
||||
// Smooth scroll
|
||||
document.querySelectorAll("a[href^='#']").forEach(anchor => {
|
||||
if (anchor.classList.contains("no-smooth")) // Ignore smooth scroll functionality
|
||||
return;
|
||||
function initializeSmoothScroll() {
|
||||
// Smooth scroll
|
||||
document.querySelectorAll("a[href^='#']").forEach(anchor => {
|
||||
if (anchor.classList.contains("no-smooth")) // Ignore smooth scroll functionality
|
||||
return;
|
||||
|
||||
anchor.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
anchor.addEventListener("click", event => {
|
||||
event.preventDefault();
|
||||
|
||||
const element = event.target.href.split("#").pop()
|
||||
.toLowerCase();
|
||||
let elementOffset;
|
||||
const element = event.target.href.split("#").pop()
|
||||
.toLowerCase();
|
||||
let elementOffset;
|
||||
|
||||
if (document.getElementById(element)) {
|
||||
elementOffset = document.getElementById(element).offsetTop - 150;
|
||||
window.scroll({ top: elementOffset, behavior: "smooth" });
|
||||
history.pushState({}, "", `#${element}`); // Add hash to URL bar
|
||||
}
|
||||
if (document.getElementById(element)) {
|
||||
elementOffset = document.getElementById(element).offsetTop - 150;
|
||||
window.scroll({ top: elementOffset, behavior: "smooth" });
|
||||
history.pushState({}, "", `#${element}`); // Add hash to URL bar
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Newsletter
|
||||
document.getElementById("emailAddress").addEventListener("keyup", event => {
|
||||
|
@ -88,6 +91,20 @@ document.querySelector("[data-action='subscribe to newsletter']").onclick = () =
|
|||
|
||||
// H E L P E R S
|
||||
|
||||
function runScriptsInDynamicallyInsertedHTML(element, elementHTML) { // eslint-disable-line no-unused-vars
|
||||
element.innerHTML = elementHTML;
|
||||
|
||||
Array.from(element.querySelectorAll("script")).forEach(oldScript => {
|
||||
const newScript = document.createElement("script");
|
||||
|
||||
Array.from(oldScript.attributes)
|
||||
.forEach(attr => newScript.setAttribute(attr.name, attr.value));
|
||||
|
||||
newScript.appendChild(document.createTextNode(oldScript.innerHTML));
|
||||
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||
});
|
||||
}
|
||||
|
||||
function scrollToElementOnLoad() {
|
||||
if (window.location.href.includes("#")) {
|
||||
setTimeout(() => { // give page time to breathe
|
||||
|
|
22
app/dist/scripts/sockets.js
vendored
22
app/dist/scripts/sockets.js
vendored
|
@ -1,4 +1,4 @@
|
|||
"use strict"; /* global document, location, WebSocket, window */
|
||||
"use strict"; /* global document, initializeSmoothScroll, location, runScriptsInDynamicallyInsertedHTML, WebSocket, window */
|
||||
|
||||
|
||||
|
||||
|
@ -44,6 +44,26 @@ function initializeWebSocketConnection() {
|
|||
window.location.href = data.url;
|
||||
break;
|
||||
|
||||
case data.message === "replace html":
|
||||
// create placeholder
|
||||
var placeholder = document.createElement("div");
|
||||
placeholder.setAttribute("id", "__placeholder"); // eslint-disable-line padding-line-between-statements
|
||||
document.querySelector(data.selector).insertAdjacentElement("afterend", placeholder);
|
||||
|
||||
// remove original element
|
||||
document.querySelector(data.selector).remove();
|
||||
|
||||
// add new element and remove placeholder
|
||||
document.getElementById("__placeholder").insertAdjacentHTML("afterend", data.html);
|
||||
document.getElementById("__placeholder").remove();
|
||||
|
||||
// make our scripts work
|
||||
runScriptsInDynamicallyInsertedHTML(document.querySelector(data.selector), document.querySelector(data.selector).innerHTML);
|
||||
|
||||
// make smooth scroll work on our new content
|
||||
initializeSmoothScroll();
|
||||
break;
|
||||
|
||||
case data.message === "show result":
|
||||
if (!data.example)
|
||||
return;
|
||||
|
|
15
app/index.js
15
app/index.js
|
@ -22,7 +22,20 @@ import redirects from "~data/redirects.json";
|
|||
const server = fastify({
|
||||
logger: {
|
||||
level: "warn",
|
||||
prettyPrint: process.env.NODE_ENV === "development" ? true : false
|
||||
prettyPrint: process.env.NODE_ENV === "development" ? true : false,
|
||||
redact: ["req.headers.authorization"],
|
||||
serializers: {
|
||||
req(req) {
|
||||
return {
|
||||
headers: req.headers,
|
||||
hostname: req.hostname,
|
||||
method: req.method,
|
||||
remoteAddress: req.ip,
|
||||
remotePort: req.connection.remotePort,
|
||||
url: req.url
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import html from "choo/html";
|
|||
|
||||
// U T I L S
|
||||
|
||||
import apiPage from "~view/api";
|
||||
import fetchMetadata from "~helper/fetch-metadata";
|
||||
import { generateGitHubFeed } from "~helper/github";
|
||||
import messageSlack from "~helper/slack";
|
||||
|
@ -23,7 +24,7 @@ const githubAppSecret = process.env.GITHUB_APP_SECRET;
|
|||
|
||||
// P R O G R A M
|
||||
|
||||
export default (socket, action) => {
|
||||
export default async(socket, action) => {
|
||||
if (typeof socket !== "object" && typeof action !== "object")
|
||||
return;
|
||||
|
||||
|
@ -88,6 +89,21 @@ export default (socket, action) => {
|
|||
newsletterSubscribe(action, socket);
|
||||
break;
|
||||
|
||||
case action.message === "view different documentation version":
|
||||
send(socket, {
|
||||
element: "div",
|
||||
html: await apiPage({
|
||||
params: {
|
||||
wildcard: action.version.split("-")[0]
|
||||
},
|
||||
tag: action.version.split("-")[1]
|
||||
}),
|
||||
message: "replace html",
|
||||
parentElement: "main",
|
||||
selector: ".__slate"
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -434,7 +450,7 @@ async function verifyGitHubToken(data, socket) {
|
|||
const code = data.code;
|
||||
|
||||
try {
|
||||
let result = await got.post(`https://github.com/login/oauth/access_token?client_id=${githubAppId}&client_secret=${githubAppSecret}&code=${code}`, { json: true });
|
||||
const result = await got.post(`https://github.com/login/oauth/access_token?client_id=${githubAppId}&client_secret=${githubAppSecret}&code=${code}`, { json: true });
|
||||
|
||||
const response = {
|
||||
address: data.address,
|
||||
|
|
|
@ -32,28 +32,30 @@ const octokit = new Octokit({
|
|||
// E X P O R T
|
||||
|
||||
export default async(state) => {
|
||||
state.lbry = {
|
||||
title: "API Documentation",
|
||||
description: "See API documentation, signatures, and sample calls for the LBRY APIs."
|
||||
};
|
||||
|
||||
const { tag } = state;
|
||||
const { wildcard } = state.params;
|
||||
|
||||
const repository = wildcard === "sdk" ?
|
||||
"lbry-sdk" :
|
||||
"lbrycrd";
|
||||
|
||||
state.lbry = {
|
||||
title: tag ? tag + " API Documentation" : "API Documentation",
|
||||
description: "See API documentation, signatures, and sample calls for the LBRY APIs."
|
||||
};
|
||||
|
||||
const tags = await getTags(repository);
|
||||
|
||||
try {
|
||||
const apiResponse = await parseApiFile({ repo: repository, tag: tags[0] });
|
||||
const apiResponse = await parseApiFile({ repo: repository, tag: tag ? tag : tags[0] });
|
||||
|
||||
return asyncHtml`
|
||||
<div class="__slate">
|
||||
<aside class="api-toc">
|
||||
<select class="api-toc__select" onchange="changeDocumentationVersion(value);">
|
||||
${renderVersionSelector(wildcard, tags)}
|
||||
${renderVersionSelector(wildcard, tags, tag)}
|
||||
</select>
|
||||
|
||||
<div class="api-toc__search">
|
||||
<input class="api-toc__search-field" id="input-search" placeholder="Search" type="search"/>
|
||||
<div class="api-toc__search-clear" id="clear-search" title="Clear search query">×</div>
|
||||
|
@ -64,28 +66,32 @@ export default async(state) => {
|
|||
${wildcard === "sdk" ? createSdkSidebar(apiResponse) : createApiSidebar(apiResponse)}
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
<section class="api-content">
|
||||
<div class="api-documentation" id="toc-content">
|
||||
<div></div>
|
||||
|
||||
<nav class="api-content__items">
|
||||
${renderCodeLanguageToggles(wildcard)}
|
||||
</nav>
|
||||
|
||||
${createApiHeader(wildcard)}
|
||||
${createApiHeader(wildcard, tag ? tag : tags[0])}
|
||||
${wildcard === "sdk" ? createSdkContent(apiResponse) : createApiContent(apiResponse)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script src="/assets/scripts/plugins/jets.js"></script>
|
||||
<script src="/assets/scripts/api.js"></script>
|
||||
|
||||
<script>
|
||||
initializeApiFunctionality();
|
||||
|
||||
if (window.location.pathname === "/api/blockchain")
|
||||
document.getElementById("toggle-cli").click();
|
||||
else
|
||||
document.getElementById("toggle-curl").click();
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<script src="/assets/scripts/plugins/jets.js"></script>
|
||||
<script src="/assets/scripts/api.js"></script>
|
||||
|
||||
<script>
|
||||
if (window.location.pathname === "/api/blockchain")
|
||||
document.getElementById("toggle-cli").click();
|
||||
else
|
||||
document.getElementById("toggle-curl").click();
|
||||
</script>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -149,13 +155,13 @@ function createApiContent(apiDetails) {
|
|||
return apiContent;
|
||||
}
|
||||
|
||||
function createApiHeader(slug) {
|
||||
function createApiHeader(slug, apiVersion) {
|
||||
switch(slug) {
|
||||
case "blockchain":
|
||||
return headerBlockchain();
|
||||
return headerBlockchain(apiVersion);
|
||||
|
||||
case "sdk":
|
||||
return headerSdk();
|
||||
return headerSdk(apiVersion);
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -368,15 +374,36 @@ function renderReturns(args) {
|
|||
return returnContent;
|
||||
}
|
||||
|
||||
function renderVersionSelector(pageSlug, versions) {
|
||||
function renderVersionSelector(pageSlug, versions, desiredTag) {
|
||||
const options = [
|
||||
"<option disabled>Select a version</option>"
|
||||
];
|
||||
|
||||
let optionIndex = 0;
|
||||
|
||||
// console.log("————————");
|
||||
// console.log(desiredTag);
|
||||
// console.log("————————");
|
||||
|
||||
versions.forEach(version => {
|
||||
options.push(`<option value="${pageSlug}-${version}">${version}</option>`);
|
||||
optionIndex++;
|
||||
let selectedOption = false;
|
||||
|
||||
if (desiredTag && desiredTag === version)
|
||||
selectedOption = true;
|
||||
else if (optionIndex === 1)
|
||||
selectedOption = true;
|
||||
|
||||
// if (selectedOption === true)
|
||||
// console.log(pageSlug, version);
|
||||
|
||||
options.push(
|
||||
`<option value="${pageSlug}-${version}"${selectedOption ? " selected" : ""}>${version}</option>`
|
||||
);
|
||||
});
|
||||
|
||||
// console.log(options);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue