diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml deleted file mode 100644 index 964da66..0000000 --- a/.github/workflows/preview.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: preview PR -on: - pull_request: - types: - - opened - - reopened - - synchronize - - closed - paths: - - css/** - - html/** - - js/** - - build.js - - .github/workflows/preview.yml -concurrency: preview-${{ github.ref }} -jobs: - deploy-preview: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Install - run: npm install - - name: Build - run: npm run build - - name: Deploy preview - uses: rossjrw/pr-preview-action@v1 - with: - source-dir: dist diff --git a/build.js b/build.js index 5f091e5..8448bb9 100644 --- a/build.js +++ b/build.js @@ -16,6 +16,16 @@ esbuild.buildSync({ target: dev ? "esnext" : "es5", }); +esbuild.buildSync({ + entryPoints: ["js/resizeIframe.js"], + outdir: "dist", + bundle: true, + minify: !dev, + sourcemap: dev ? "inline" : true, + target: dev ? "esnext" : "es5", + globalName: "resizeIframe", +}); + ["interwikiFrame", "styleFrame", "index"].forEach(function (frame) { fs.copyFileSync("html/" + frame + ".html", "dist/" + frame + ".html"); }); diff --git a/html/interwikiFrame.html b/html/interwikiFrame.html index df795ea..eb48d2e 100644 --- a/html/interwikiFrame.html +++ b/html/interwikiFrame.html @@ -1,17 +1,20 @@ - - - - + + - -
-
-

-
+ + + + + +
+
+

-
- - +
+
+ + + \ No newline at end of file diff --git a/js/branches-info-scp.js b/js/branches-info-scp.js index 9d77f8c..c680b70 100644 --- a/js/branches-info-scp.js +++ b/js/branches-info-scp.js @@ -79,8 +79,8 @@ export var scpBranches = { ru: { name: "Русский", head: "На других языках", - url: "http://scp-ru.wikidot.com/", - id: "169125", + url: "https://scpfoundation.net/", + id: "", category: "", }, es: { diff --git a/js/branches-info-wl.js b/js/branches-info-wl.js index e00f0c5..852b60c 100644 --- a/js/branches-info-wl.js +++ b/js/branches-info-wl.js @@ -48,4 +48,11 @@ export var wlBranches = { id: "4593099", category: "", }, + ru: { + name: "Русский", + head: "На других языках", + url: "https://scpfoundation.net/", + id: "", + category: "wl:", + }, }; diff --git a/js/createResizeIframe.js b/js/createResizeIframe.js deleted file mode 100644 index af92052..0000000 --- a/js/createResizeIframe.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Whether the interwiki should be visible. It should only be visible after - * data has been received from the API source. - */ -export var flags = { showInterwiki: false }; - -/** - * Constructs and returns a function that, when called, resizes the current - * iframes to match its contents. The function is debounced. - * - * @param {String} site - The base URL of the site. - * @param {String} frameId - The last segment of the URL of the interwiki - * iframe, used by Wikidot to identify it when resizing it. - */ -export function createResizeIframe(site, frameId) { - var container = document.getElementById("resizer-container"); - var resizer = document.createElement("iframe"); - var CacheBreak = String(Math.floor(Math.random() * 10000)); - var oldheight = 0; - resizer.style.display = "none"; - - if (frameId[0] !== "/") frameId = "/" + frameId; - - return debounce(function (receivedData) { - if (receivedData) flags.showInterwiki = true; - if (flags.showInterwiki) { - // Measure from the top of the document to the iframe container to get - // the document height - this takes into account inner margins, unlike - // e.g. document.body.clientHeight - // The container must not have display:none for this to work, which is - // why the iframe has it instead - var height = container.getBoundingClientRect().top; - // Brute-force past any subpixel issues - if (height !== oldheight) { - container.innerHTML = ""; - resizer.src = - site + - "/common--javascript/resize-iframe.html?" + - CacheBreak + - "#" + - height + - frameId; - container.appendChild(resizer); - oldheight = height; - } - } - }, 50); -} - -/** - * Debounces a function, delaying its execution until a certain amount of - * time has passed since the last time it was called, and aggregating all - * calls made in that time into one. - * - * @param {Function} func - The function to call. - * @param {Number} wait - The number of milliseconds to wait after any call - * to the debounced function before executing it. - */ -function debounce(func, wait) { - var timeout = 0; - return function () { - clearTimeout(timeout); - timeout = setTimeout(function () { - func(arguments); - }, wait); - }; -} diff --git a/js/interwiki.js b/js/interwiki.js index 85250d2..ef3a1da 100644 --- a/js/interwiki.js +++ b/js/interwiki.js @@ -1,11 +1,14 @@ -import { createResizeIframe } from "./createResizeIframe"; -import { addTranslations } from "./links"; import { addExternalStyle, createRequestStyleChange } from "./styles"; +import { ResizeObserver } from "@juggle/resize-observer"; +import { addTranslations } from "./links"; import { scpBranches } from "./branches-info-scp"; import { wlBranches } from "./branches-info-wl"; -import { ResizeObserver } from "@juggle/resize-observer"; +/** + * @type {import("./resizeIframe").createResizeIframe} + */ +var createResizeIframe = window.resizeIframe.createResizeIframe; addEventListener("DOMContentLoaded", function () { var community = getQueryString(location.search, "community"); @@ -113,7 +116,10 @@ export function createInterwiki( var resize = createResizeIframe(site, frameId); // Resize frame when size changes are detected - var observer = new ResizeObserver(resize); + var observer = new ResizeObserver(function () { + // Only resize if there's at least one translation link + if (document.getElementsByClassName("menu-item").length) resize(); + }); observer.observe(document.documentElement); // Construct the function that will be called internally and by diff --git a/js/links.js b/js/links.js index 4ee70bc..b513fd5 100644 --- a/js/links.js +++ b/js/links.js @@ -1,4 +1,3 @@ -import { flags } from "./createResizeIframe"; import { cromLookup } from "./lookup/crom"; // Configure which lookup method is currently active @@ -58,16 +57,7 @@ export function addTranslations(branches, currentBranchLang, pagename) { var header = document.querySelector(".heading p"); header.innerText = currentBranch.head; - lookupMethod( - currentBranch, - branches, - pagename, - function (pageUrl, branchName, branchLang, isOriginal) { - addTranslationLink(pageUrl, branchName, branchLang, isOriginal); - // Indicate that data has been received - flags.showInterwiki = true; - } - ); + lookupMethod(currentBranch, branches, pagename, addTranslationLink); } /** diff --git a/js/lookup/crom.js b/js/lookup/crom.js index ff35570..31849a4 100644 --- a/js/lookup/crom.js +++ b/js/lookup/crom.js @@ -69,8 +69,8 @@ export function cromLookup(currentBranch, branches, fullname, addLink) { * @param {String} url */ function normaliseUrl(url) { - if (url.indexOf(".wikidot.com") === -1) { - throw new Error("Crom requires wikidot.com branch URLs (" + url + ")"); + if (url.indexOf(".wikidot.com") === -1 && url.indexOf("scpfoundation.net") === -1) { + throw new Error("Crom requires wikidot.com or scpfoundation.net branch URLs (" + url + ")"); } return url.replace(/^https:/, "http:"); } @@ -137,8 +137,13 @@ function parseTranslations(response, currentBranch, branches, addLink) { */ function executeQuery(url, callback) { var request = new XMLHttpRequest(); - request.open("POST", "https://api.crom.avn.sh/graphql", true); - request.setRequestHeader("Content-Type", "application/json"); + var requestUrl = + "https://api.crom.avn.sh/graphql?query=" + + encodeURIComponent(query) + + "&variables=" + + encodeURIComponent(JSON.stringify({ url: url })); + request.open("GET", requestUrl, true); + request.setRequestHeader("Accept", "application/json"); request.addEventListener("readystatechange", function () { if (request.readyState === XMLHttpRequest.DONE) { try { @@ -157,5 +162,5 @@ function executeQuery(url, callback) { } } }); - request.send(JSON.stringify({ query: query, variables: { url: url } })); + request.send(); } diff --git a/js/resizeIframe.js b/js/resizeIframe.js new file mode 100644 index 0000000..a403f22 --- /dev/null +++ b/js/resizeIframe.js @@ -0,0 +1,61 @@ +/** + * Constructs and returns a function that, when called, resizes the current iframes to match its contents or the given height. The function is debounced. + * + * @param {String} site - The base URL of the site. + * @param {String} frameId - The last segment of the URL of the interwiki iframe, used by Wikidot to identify it when resizing it. + * @param {Number=} [debounceTime] - Debounce delay to stagger repeated calls to the resizer. Defaults to 750 ms. + * @returns {((height: Number=) => void)} Debounced function that resizes the iframe. Optional height parameter sets the height of the iframe; if not set, the height is calculated from the document. + */ +export function createResizeIframe(site, frameId, debounceTime) { + if (debounceTime == null) debounceTime = 750; + + var container = document.getElementById("resizer-container"); + if (container == null) { + container = document.createElement("div"); + container.id = "resizer-container"; + document.body.appendChild(container); + } + var resizer = document.createElement("iframe"); + resizer.style.display = "none"; + container.appendChild(resizer); + + // Trim leading slashes from frame ID + frameId = frameId.replace(/^\/+/, ""); + + var resize = function (height) { + if (height == null) { + // Measure from the top of the document to the iframe container to get the document height + // This takes into account inner margins, unlike e.g. document.body.clientHeight + // The container must not have display:none for this to work, which is why the iframe has it instead + height = container.getBoundingClientRect().top; + // Brute-force past any subpixel issues + if (height) height += 1; + } + resizer.src = + site + + "/common--javascript/resize-iframe.html?" + + "#" + + height + + "/" + + frameId; + }; + + return debounce(resize, debounceTime); +} + +/** + * Debounces a function, delaying its execution until a certain amount of time has passed since the last time it was called, and aggregating all calls made in that time into one. + * + * @param {Function} func - The function to call. + * @param {Number} wait - The number of milliseconds to wait after any call to the debounced function before executing it. + * @returns {Function} The debounced function. + */ +export function debounce(func, wait) { + var timeout = 0; + return function () { + clearTimeout(timeout); + timeout = setTimeout(function () { + func.apply(null, arguments); + }, wait); + }; +}