diff --git a/app/components/api/header-blockchain.js b/app/components/api/header-blockchain.js index a27c5ef..e7b1f27 100644 --- a/app/components/api/header-blockchain.js +++ b/app/components/api/header-blockchain.js @@ -10,9 +10,9 @@ import html from "choo/html"; // E X P O R T -export default () => html` +export default version => html`
-

lbrycrd APIs

+

lbrycrd ${version}

Methods and signatures provided by the lbrycrd blockchain daemon are documented below. To build, download, or run lbrycrd, see the project README.

diff --git a/app/components/api/header-sdk.js b/app/components/api/header-sdk.js index bdf28e1..c4008ed 100644 --- a/app/components/api/header-sdk.js +++ b/app/components/api/header-sdk.js @@ -10,9 +10,9 @@ import html from "choo/html"; // E X P O R T -export default () => html` +export default version => html`
-

lbry-sdk APIs

+

lbry-sdk ${version}

Methods and signatures provided by the lbry-sdk daemon are documented below. To build, download, or run the daemon, see the project README.

diff --git a/app/dist/scripts/api.js b/app/dist/scripts/api.js index d0a6feb..fd805d7 100644 --- a/app/dist/scripts/api.js +++ b/app/dist/scripts/api.js @@ -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, diff --git a/app/dist/scripts/app.js b/app/dist/scripts/app.js index 6768844..7f89af4 100755 --- a/app/dist/scripts/app.js +++ b/app/dist/scripts/app.js @@ -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 diff --git a/app/dist/scripts/sockets.js b/app/dist/scripts/sockets.js index 6d6d6cf..34f315a 100644 --- a/app/dist/scripts/sockets.js +++ b/app/dist/scripts/sockets.js @@ -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; diff --git a/app/index.js b/app/index.js index 123a776..9ac81d5 100755 --- a/app/index.js +++ b/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 + }; + } + } } }); diff --git a/app/sockets.js b/app/sockets.js index f5cc29f..be2d2da 100644 --- a/app/sockets.js +++ b/app/sockets.js @@ -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, diff --git a/app/views/api.js b/app/views/api.js index 796ec42..5521d6b 100644 --- a/app/views/api.js +++ b/app/views/api.js @@ -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`
+
+ - ${createApiHeader(wildcard)} + ${createApiHeader(wildcard, tag ? tag : tags[0])} ${wildcard === "sdk" ? createSdkContent(apiResponse) : createApiContent(apiResponse)}
+ + + + +
- - - - - `; } @@ -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 = [ "" ]; + let optionIndex = 0; + + // console.log("————————"); + // console.log(desiredTag); + // console.log("————————"); + versions.forEach(version => { - options.push(``); + 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( + `` + ); }); + // console.log(options); + return options; }