Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve offline handling #1319

Merged
merged 3 commits into from Jul 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 15 additions & 9 deletions src/core/biblio.js
Expand Up @@ -58,9 +58,8 @@ const defaultsReference = Object.freeze({
const endNormalizer = function(endStr) {
return str => {
const trimmed = str.trim();
const result = !trimmed || trimmed.endsWith(endStr)
? trimmed
: trimmed + endStr;
const result =
!trimmed || trimmed.endsWith(endStr) ? trimmed : trimmed + endStr;
return result;
};
};
Expand Down Expand Up @@ -138,9 +137,10 @@ function bibref(conf) {
for (var i = 0; i < types.length; i++) {
var type = types[i];
var refs = type === "Normative" ? norms : informs;
var l10nRefs = type === "Normative"
? conf.l10n.norm_references
: conf.l10n.info_references;
var l10nRefs =
type === "Normative"
? conf.l10n.norm_references
: conf.l10n.info_references;
if (!refs.length) continue;
var $sec = $("<section><h3></h3></section>")
.appendTo($refsec)
Expand Down Expand Up @@ -217,11 +217,17 @@ export const done = new Promise(resolve => {
});

async function updateFromNetwork(refs, options = { forceUpdate: false }) {
// Update database if needed
if (!refs.length) {
// Update database if needed, if we are online
if (!refs.length || navigator.onLine === false) {
return;
}
const response = await fetch(bibrefsURL.href + refs.join(","));
let response;
try {
response = await fetch(bibrefsURL.href + refs.join(","));
} catch (err) {
console.error(err);
return null;
}
if ((!options.forceUpdate && !response.ok) || response.status !== 200) {
return null;
}
Expand Down
115 changes: 49 additions & 66 deletions src/core/highlight.js
Expand Up @@ -5,90 +5,73 @@
*/
import "deps/regenerator";
import ghCss from "deps/text!core/css/github.css";
import { makeOwnerSwapper } from "core/utils";
import { pub, sub } from "core/pubsubhub";
import { worker } from "core/worker";

export const name = "core/highlight";

// Opportunistically insert the style into the head to reduce FOUC.
var codeStyle = document.createElement("style");
const codeStyle = document.createElement("style");
codeStyle.textContent = ghCss;
var swapStyleOwner = makeOwnerSwapper(codeStyle);
swapStyleOwner(document.head);

document.head.appendChild(codeStyle);
let idCounter = 0;
function getLanguageHint(classList) {
return Array.from(classList)
.filter(item => item !== "highlight" && item !== "nolinks")
.map(item => item.toLowerCase());
}
let doneResolver;
let doneRejector;
export const done = new Promise((resolve, reject) => {
doneResolver = resolve;
doneRejector = reject;
});

export async function run(conf, doc, cb) {
export async function run(conf) {
// Nothing to do
if (conf.noHighlightCSS) {
doneResolver();
return cb();
return;
}

if (codeStyle.ownerDocument !== doc) {
swapStyleOwner(doc.head);
const highlightables = Array.from(
document.querySelectorAll("pre:not(.idl):not(.nohighlight), code.highlight")
);
if (!highlightables.length) {
return;
}

const promisesToHighlight = Array.from(
doc.querySelectorAll("pre:not(.idl):not(.nohighlight),code.highlight")
)
.map(element => {
const promisesToHighlight = highlightables.map(element => {
return new Promise(resolve => {
if (element.textContent.trim() === "") {
return resolve(element); // no work to do
}
const done = () => {
element.setAttribute("aria-busy", "false");
resolve(element);
};
// We always resolve, even if we couldn't actually highlight
const timeoutId = setTimeout(() => {
console.error("Timed-out waiting for highlight:", element);
done();
}, 1000);
const msg = {
action: "highlight",
code: element.textContent,
id: "highlight:" + idCounter++,
languages: getLanguageHint(element.classList),
};
element.setAttribute("aria-busy", "true");
return element;
})
.map(element => {
return new Promise((resolve, reject) => {
if (element.textContent.trim() === "") {
return resolve(element); // no work to do
element.setAttribute("aria-live", "polite");
worker.postMessage(msg);
worker.addEventListener("message", function listener(ev) {
const { data: { id, code, language, value } } = ev;
if (id !== msg.id) {
return; // not for us!
}
const msg = {
action: "highlight",
code: element.textContent,
id: Math.random().toString(),
languages: getLanguageHint(element.classList),
};
element.setAttribute("aria-live", "polite");
worker.postMessage(msg);
worker.addEventListener("message", function listener(ev) {
if (ev.data.id !== msg.id) {
return; // not for us!
}
worker.removeEventListener("message", listener);
const { value, language } = ev.data;
element.innerHTML = value;
if (element.localName === "pre") {
element.classList.add("hljs");
element.classList.add(language);
}
resolve(element);
});
setTimeout(() => {
element.setAttribute("aria-busy", "false");
const errMsg = "Timeout error trying to process: " + msg.code;
const err = new Error(errMsg);
reject(err);
}, 5000);
element.innerHTML = value;
if (element.localName === "pre") {
element.classList.add("hljs");
}
if (language) {
element.classList.add(language);
}
clearTimeout(timeoutId);
worker.removeEventListener("message", listener);
done();
});
});
try {
const tranformedElements = await Promise.all(promisesToHighlight);
tranformedElements.forEach(element =>
element.setAttribute("aria-busy", "false")
);
doneResolver();
} catch (err) {
console.error(err);
doneRejector(err);
}
cb();
});
await Promise.all(promisesToHighlight);
}
48 changes: 20 additions & 28 deletions worker/respec-worker.js
@@ -1,37 +1,29 @@
// ReSpec Worker v0.1.0
// ReSpec Worker v0.1.1
"use strict";
importScripts("https://www.w3.org/Tools/respec/respec-highlight.js");
try {
importScripts("https://www.w3.org/Tools/respec/respec-highlight.js");
hljs.configure({
tabReplace: " ", // 2 spaces
languages: ["abnf", "css", "http", "javascript", "json", "markdown", "xml"],
});
} catch (err) {
console.error("Network error loading/configuring highlighter", err);
}

hljs.configure({
tabReplace: " ", // 2 spaces
languages: [
"abnf",
"css",
"http",
"javascript",
"json",
"markdown",
"xml",
],
});

self.addEventListener("message", function(e) {
switch (e.data.action) {
self.addEventListener("message", ({ data: originalData }) => {
const data = Object.assign({}, originalData);
switch (data.action) {
case "highlight":
const code = e.data.code;
const langs = e.data.languages.length ? e.data.languages : undefined;
const result = self.hljs.highlightAuto(code, langs);
const data = Object.assign({
value: result.value,
language: result.language
}, e.data);
const { code } = data;
const langs = data.languages.length ? data.languages : undefined;
try {
self.postMessage(data);
const { value, language } = self.hljs.highlightAuto(code, langs);
Object.assign(data, { value, language });
} catch (err) {
console.error("Could not transform some code?", err);
// Post back the original unhighlighted code.
const fallbackData = Object.assign({}, e.data, { value: e.data.code });
self.postMessage(fallbackData);
// Post back the original code
Object.assign(data, { value: code, language: "" });
}
}
self.postMessage(data);
});