mirror of
https://github.com/glassflame/glassflame.github.io.git
synced 2024-11-25 17:44:26 +00:00
Complete refactoring?
This commit is contained in:
parent
610c849264
commit
803b61f434
12 changed files with 252 additions and 116 deletions
39
index.html
39
index.html
|
@ -24,12 +24,15 @@
|
|||
--color-blue: #53DFDD;
|
||||
--color-purple: #A882FF;
|
||||
|
||||
--color-node: var(--color-gray);
|
||||
|
||||
--edge-width: 2px;
|
||||
--node-group-border-width: 2px;
|
||||
--node-file-border-width: 2px;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 128px;
|
||||
width: max-content;
|
||||
height: max-content;
|
||||
|
@ -37,11 +40,18 @@
|
|||
background-color: var(--color-background);
|
||||
color: var(--color-foreground);
|
||||
}
|
||||
|
||||
svg line {
|
||||
stroke: var(--color-node);
|
||||
stroke-width: var(--edge-width);
|
||||
}
|
||||
</style>
|
||||
<!-- Templates -->
|
||||
<template id="template-vault">
|
||||
<style>
|
||||
.vault {
|
||||
|
||||
}
|
||||
</style>
|
||||
<div class="vault">
|
||||
<slot name="vault-child"></slot>
|
||||
|
@ -57,19 +67,6 @@
|
|||
width: max-content;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
.canvas * {
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.canvas *:first-child {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.canvas *:not(:first-child) {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
<div class="canvas">
|
||||
<slot name="canvas-edges">{Canvas edges}</slot>
|
||||
|
@ -159,18 +156,19 @@
|
|||
</template>
|
||||
<template id="template-edge">
|
||||
<style>
|
||||
.edge svg line {
|
||||
stroke: var(--color-node);
|
||||
stroke-width: var(--edge-width);
|
||||
.edge {
|
||||
|
||||
}
|
||||
</style>
|
||||
<div class="edge">
|
||||
<div class="canvas-item edge">
|
||||
<slot name="edge-svg">{Edge SVG}</slot>
|
||||
</div>
|
||||
</template>
|
||||
<template id="template-markdown">
|
||||
<style>
|
||||
.markdown
|
||||
.markdown {
|
||||
|
||||
}
|
||||
</style>
|
||||
<div class="markdown">
|
||||
<slot name="markdown-document">{Markdown text}</slot>
|
||||
|
@ -203,9 +201,8 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<a class="wikilink"><slot name="wikilink-anchor">{Wikilink text}</slot></a>
|
||||
<a class="wikilink"></a>
|
||||
</template>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
<body is="x-browse"></body>
|
||||
</html>
|
|
@ -1,11 +0,0 @@
|
|||
export function configFromURL(location) {
|
||||
const queryString = new URLSearchParams(location.search)
|
||||
const vref = queryString.get("vref")
|
||||
const wref = queryString.get("wref")
|
||||
|
||||
return {vref, wref}
|
||||
}
|
||||
|
||||
export function configFromWindow() {
|
||||
return configFromURL(window.location)
|
||||
}
|
64
src/elements/browse.mjs
Normal file
64
src/elements/browse.mjs
Normal file
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* The body element for the pages viewer, handling most low-level things.
|
||||
*/
|
||||
export class BrowseElement extends HTMLBodyElement {
|
||||
/**
|
||||
* Parameters to be used to display *things*.
|
||||
* @type {{vault: string, path: string, highlight: string}}
|
||||
*/
|
||||
parameters
|
||||
|
||||
/**
|
||||
* Recalculate the value of {@link parameters} using the current {@link window.location}.
|
||||
* @returns {void}
|
||||
*/
|
||||
recalculateParameters() {
|
||||
const location = window.location
|
||||
const params = new URLSearchParams(location.search)
|
||||
const vault = params.get("vault")
|
||||
const path = params.get("path")
|
||||
const highlight = location.hash.replace(/^#/, "")
|
||||
this.parameters = {vault, path, highlight}
|
||||
}
|
||||
|
||||
// TODO: Add a landing page
|
||||
|
||||
/**
|
||||
* The vault element, describing to its descendants how to handle various situations.
|
||||
* @type {VaultElement}
|
||||
*/
|
||||
vaultElement
|
||||
|
||||
/**
|
||||
* The display element showing the contents of the specified file.
|
||||
* @type {DisplayElement}
|
||||
*/
|
||||
rootDisplayElement
|
||||
|
||||
/**
|
||||
* Recreate all contents of this element to match the current value of {@link parameters}.
|
||||
*/
|
||||
recreateContents() {
|
||||
if(this.vaultElement) {
|
||||
this.vaultElement.remove()
|
||||
this.vaultElement = null
|
||||
this.rootDisplayElement = null
|
||||
}
|
||||
|
||||
this.vaultElement = document.createElement("x-vault")
|
||||
this.vaultElement.base = this.parameters.vault
|
||||
this.vaultElement.cooldownMs = 200
|
||||
|
||||
this.rootDisplayElement = document.createElement("x-display")
|
||||
this.rootDisplayElement.path = this.parameters.path
|
||||
this.rootDisplayElement.slot = "vault-child"
|
||||
|
||||
this.vaultElement.appendChild(this.rootDisplayElement)
|
||||
this.appendChild(this.vaultElement)
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.recalculateParameters()
|
||||
this.recreateContents()
|
||||
}
|
||||
}
|
|
@ -40,10 +40,10 @@ export class CanvasElement extends CustomElement {
|
|||
|
||||
/**
|
||||
* Update the values of {@link document} and {@link parsedDocument} from the `document` attribute of the element.
|
||||
* @throws SyntaxError If `contents` is not valid JSON.
|
||||
* @throws SyntaxError If `document` is not valid JSON.
|
||||
*/
|
||||
recalculateContents() {
|
||||
this.#document = this.getAttribute("contents")
|
||||
reparseDocument() {
|
||||
this.#document = this.getAttribute("document")
|
||||
this.#parsedDocument = JSON.parse(this.#document)
|
||||
}
|
||||
|
||||
|
@ -155,31 +155,28 @@ export class CanvasElement extends CustomElement {
|
|||
this.nodesContainer.slot = this.constructor.NODES_SLOT_NAME
|
||||
|
||||
for(const node of this.parsedDocument["nodes"]) {
|
||||
let {id, type, color, x, y, width, height} = node
|
||||
x, y, width, height = Number(x), Number(y), Number(width), Number(height)
|
||||
const {id, type, color, x, y, width, height} = node
|
||||
const [nodeX, nodeY, nodeWidth, nodeHeight] = [Number(x), Number(y), Number(width), Number(height)]
|
||||
|
||||
const element = document.createElement(`${this.constructor.NODE_ELEMENT_NAME_PREFIX}${type}`)
|
||||
|
||||
element.setAttribute("id", `node-${id}`)
|
||||
element.setAttribute("x", `${x - this.minX.x}`)
|
||||
element.setAttribute("y", `${y - this.minY.y}`)
|
||||
element.setAttribute("width", `${width}`)
|
||||
element.setAttribute("height", `${height}`)
|
||||
if(color) element.setAttribute("color", color)
|
||||
element.x = nodeX - this.minX.x
|
||||
element.y = nodeY - this.minY.y
|
||||
element.width = nodeWidth
|
||||
element.height = nodeHeight
|
||||
if(color) element.obsidianColor = color
|
||||
|
||||
this.nodeElementsById[id] = element
|
||||
|
||||
switch(type) {
|
||||
case "text":
|
||||
const {text} = node
|
||||
element.setAttribute("text", text)
|
||||
element.setAttribute("document", text)
|
||||
break
|
||||
|
||||
case "file":
|
||||
const {file} = node
|
||||
const {name} = fileDetails(file)
|
||||
element.setAttribute("file", file)
|
||||
element.setAttribute("file-name", name)
|
||||
element.setAttribute("path", file)
|
||||
this.nodeElementsByPath[file] = element
|
||||
this.nodeElementsByName[name] = element
|
||||
break
|
||||
|
@ -199,6 +196,7 @@ export class CanvasElement extends CustomElement {
|
|||
|
||||
this.nodesContainer.style["width"] = `${this.maxX.x + this.maxX.width - this.minX.x}px`
|
||||
this.nodesContainer.style["height"] = `${this.maxY.y + this.maxY.height - this.minY.y}px`
|
||||
this.nodesContainer.style["position"] = "relative"
|
||||
|
||||
this.appendChild(this.nodesContainer)
|
||||
}
|
||||
|
@ -219,7 +217,7 @@ export class CanvasElement extends CustomElement {
|
|||
* Name of the slot where the edge container should be placed.
|
||||
* @type {string}
|
||||
*/
|
||||
static EDGES_SLOT_NAME = "canvas-nodes"
|
||||
static EDGES_SLOT_NAME = "canvas-edges"
|
||||
|
||||
/**
|
||||
* Prefix to the name of the element to create for each edge.
|
||||
|
@ -258,13 +256,14 @@ export class CanvasElement extends CustomElement {
|
|||
|
||||
this.edgesContainer.style["width"] = `${this.maxX.x + this.maxX.width - this.minX.x}px`
|
||||
this.edgesContainer.style["height"] = `${this.maxY.y + this.maxY.height - this.minY.y}px`
|
||||
this.edgesContainer.style["position"] = "absolute"
|
||||
|
||||
this.appendChild(this.edgesContainer)
|
||||
}
|
||||
|
||||
onConnect() {
|
||||
super.onConnect()
|
||||
this.recalculateContents()
|
||||
this.reparseDocument()
|
||||
this.recalculateMinMax()
|
||||
this.recreateNodes()
|
||||
this.recreateEdges()
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { CustomElement } from "../base.mjs";
|
||||
import {MalformedError} from "../../utils/errors.mjs";
|
||||
|
||||
|
||||
/**
|
||||
|
@ -12,6 +13,9 @@ export class CanvasItemElement extends CustomElement {
|
|||
get x() {
|
||||
return Number(this.getAttribute("x"))
|
||||
}
|
||||
set x(value) {
|
||||
this.setAttribute("x", value.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {number} The Y coordinate of the top left vertex of this element.
|
||||
|
@ -19,6 +23,9 @@ export class CanvasItemElement extends CustomElement {
|
|||
get y() {
|
||||
return Number(this.getAttribute("y"))
|
||||
}
|
||||
set y(value) {
|
||||
this.setAttribute("y", value.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {number} The horizontal width of this element.
|
||||
|
@ -26,6 +33,9 @@ export class CanvasItemElement extends CustomElement {
|
|||
get width() {
|
||||
return Number(this.getAttribute("width"))
|
||||
}
|
||||
set width(value) {
|
||||
this.setAttribute("width", value.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {number} The vertical height of this element.
|
||||
|
@ -33,6 +43,9 @@ export class CanvasItemElement extends CustomElement {
|
|||
get height() {
|
||||
return Number(this.getAttribute("height"))
|
||||
}
|
||||
set height(value) {
|
||||
this.setAttribute("height", value.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* The color of this element, as stored in Obsidian Canvas files.
|
||||
|
@ -48,6 +61,14 @@ export class CanvasItemElement extends CustomElement {
|
|||
|
||||
return color // Hex color specified
|
||||
}
|
||||
set obsidianColor(value) {
|
||||
if(value === null) {
|
||||
this.removeAttribute("color")
|
||||
}
|
||||
else {
|
||||
this.setAttribute("color", value.toString())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an Obsidian Canvas color, return its corresponding CSS color.
|
||||
|
@ -58,18 +79,23 @@ export class CanvasItemElement extends CustomElement {
|
|||
if(color === null || color === "") {
|
||||
return "var(--color-gray)"
|
||||
}
|
||||
else if(color.match(/^#[0-9A-F]{3}$|^#[0-9A-F]{6}$/i)) {
|
||||
return color
|
||||
else if(typeof color === "string") {
|
||||
if(color.match(/^#[0-9A-F]{3}$|^#[0-9A-F]{6}$/i)) {
|
||||
return color
|
||||
}
|
||||
else {
|
||||
throw new MalformedError("String obisidianColor is not an hex code.")
|
||||
}
|
||||
}
|
||||
else {
|
||||
return {
|
||||
"0": "var(--color-gray)",
|
||||
"1": "var(--color-red)",
|
||||
"2": "var(--color-orange)",
|
||||
"3": "var(--color-yellow)",
|
||||
"4": "var(--color-green)",
|
||||
"5": "var(--color-blue)",
|
||||
"6": "var(--color-purple)",
|
||||
0: "var(--color-gray)",
|
||||
1: "var(--color-red)",
|
||||
2: "var(--color-orange)",
|
||||
3: "var(--color-yellow)",
|
||||
4: "var(--color-green)",
|
||||
5: "var(--color-blue)",
|
||||
6: "var(--color-purple)",
|
||||
}[color]
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +106,14 @@ export class CanvasItemElement extends CustomElement {
|
|||
get cssColor() {
|
||||
return this.constructor.obsidianColorToCssColor(this.obsidianColor)
|
||||
}
|
||||
set cssColor(value) {
|
||||
if(value === null) {
|
||||
this.removeAttribute("color")
|
||||
}
|
||||
else {
|
||||
this.setAttribute("color", value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The CSS selector of the element in the template representing the canvas item.
|
||||
|
@ -108,11 +142,11 @@ export class CanvasItemElement extends CustomElement {
|
|||
resetCanvasItemCssProperties() {
|
||||
this.canvasItemElement.style.setProperty("box-sizing", "border-box")
|
||||
this.canvasItemElement.style.setProperty("position", "absolute")
|
||||
this.canvasItemElement.style.setProperty("left", `${this.getAttribute("x")}px`)
|
||||
this.canvasItemElement.style.setProperty("top", `${this.getAttribute("y")}px`)
|
||||
this.canvasItemElement.style.setProperty("width", `${this.getAttribute("width")}px`)
|
||||
this.canvasItemElement.style.setProperty("height", `${this.getAttribute("height")}px`)
|
||||
this.canvasItemElement.style.setProperty("--color-node", this.constructor.obsidianColorToCssColor(this.getAttribute("color")))
|
||||
this.canvasItemElement.style.setProperty("left", `${this.x}px`)
|
||||
this.canvasItemElement.style.setProperty("top", `${this.y}px`)
|
||||
this.canvasItemElement.style.setProperty("width", `${this.width}px`)
|
||||
this.canvasItemElement.style.setProperty("height", `${this.height}px`)
|
||||
this.canvasItemElement.style.setProperty("--color-node", this.cssColor)
|
||||
}
|
||||
|
||||
onConnect() {
|
||||
|
|
|
@ -76,8 +76,7 @@ export class NodeFileElement extends NodeElement {
|
|||
|
||||
this.contentsElement = document.createElement("x-display")
|
||||
this.contentsElement.slot = this.constructor.CONTENTS_ELEMENT_SLOT
|
||||
this.contentsElement.setAttribute("vault", findFirstAncestor(this, DisplayElement).vault) // TODO: Add a vault attribute to DisplayElement
|
||||
this.contentsElement.setAttribute("path", this.pathRelativeToVault) // TODO: Add a path attribute to DisplayElement
|
||||
this.contentsElement.path = this.pathRelativeToVault
|
||||
this.appendChild(this.contentsElement)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,11 @@ export class DisplayElement extends CustomElement {
|
|||
* Get the path or name of the file this node points to.
|
||||
* @returns {string} The value in question.
|
||||
*/
|
||||
get target() {
|
||||
return this.getAttribute("target")
|
||||
get path() {
|
||||
return this.getAttribute("path")
|
||||
}
|
||||
set path(value) {
|
||||
return this.setAttribute("path", value)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,7 +87,7 @@ export class DisplayElement extends CustomElement {
|
|||
this.contentsElement = null
|
||||
}
|
||||
|
||||
const {extension} = fileDetails(this.target)
|
||||
const {extension} = fileDetails(this.path)
|
||||
|
||||
switch(extension) {
|
||||
case "md":
|
||||
|
@ -100,30 +103,30 @@ export class DisplayElement extends CustomElement {
|
|||
|
||||
this.contentsElement.setAttribute("document", this.document)
|
||||
this.contentsElement.slot = this.constructor.CONTAINER_ELEMENT_SLOT
|
||||
this.appendChild(this.loadingElement)
|
||||
this.appendChild(this.contentsElement)
|
||||
}
|
||||
|
||||
/**
|
||||
* The plaintext contents of the {@link target} document.
|
||||
* The plaintext contents of the {@link path} document.
|
||||
* @type {string}
|
||||
*/
|
||||
document
|
||||
|
||||
/**
|
||||
* Reload the {@link target} {@link document}.
|
||||
* Reload the {@link path} {@link document}.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async reloadDocument() {
|
||||
const response = await this.vault.fetchCooldown(this.target)
|
||||
const response = await this.vault.fetchCooldown(this.path)
|
||||
// TODO: Add a check that the request was successful
|
||||
this.document = await response.text()
|
||||
}
|
||||
|
||||
onConnect() {
|
||||
async onConnect() {
|
||||
super.onConnect()
|
||||
this.recalculateVault()
|
||||
this.recreateLoadingElement()
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
this.reloadDocument().then(this.recreateContentsElement)
|
||||
await this.reloadDocument()
|
||||
this.recreateContentsElement()
|
||||
}
|
||||
}
|
|
@ -2,3 +2,4 @@ export {CanvasElement, NodeFileElement, NodeGroupElement, NodeTextElement, EdgeE
|
|||
export {MarkdownElement, HashtagElement, WikilinkElement, FrontMatterElement} from "./markdown/index.mjs"
|
||||
export {DisplayElement} from "./display.mjs"
|
||||
export {VaultElement} from "./vault.mjs"
|
||||
export {BrowseElement} from "./browse.mjs"
|
||||
|
|
|
@ -6,7 +6,7 @@ import { CustomElement } from "../base.mjs";
|
|||
*/
|
||||
export class WikilinkElement extends CustomElement {
|
||||
static get template() {
|
||||
return document.getElementById("template-hashtag")
|
||||
return document.getElementById("template-wikilink")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,9 +22,21 @@ export class WikilinkElement extends CustomElement {
|
|||
* @returns {string} The text in question.
|
||||
*/
|
||||
get text() {
|
||||
return this.getAttribute("text") ?? this.target
|
||||
// TODO: Dirty hack to hide "undefined"
|
||||
const text = this.getAttribute("text")
|
||||
// noinspection EqualityComparisonWithCoercionJS
|
||||
if(text == "undefined") {
|
||||
return this.target
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
/**
|
||||
* The CSS selector of the anchor element.
|
||||
* @type {string}
|
||||
*/
|
||||
static ANCHOR_SELECTOR = "a.wikilink"
|
||||
|
||||
/**
|
||||
* The element displaying the wikilink.
|
||||
* Can be recreated with {@link recreateTagElement}.
|
||||
|
@ -33,30 +45,21 @@ export class WikilinkElement extends CustomElement {
|
|||
anchorElement
|
||||
|
||||
/**
|
||||
* The name of the slot where {@link anchorElement} should be placed in.
|
||||
* @type {string}
|
||||
*/
|
||||
static ANCHOR_ELEMENT_SLOT = "wikilink-anchor"
|
||||
|
||||
/**
|
||||
* Recreate {@link anchorElement} with the current value of {@link target} and {@link text}.
|
||||
Update the value of the {@link canvasItemElement} by querying the current {@link instance} with {@link ANCHOR_SELECTOR}.
|
||||
* @returns {void}
|
||||
*/
|
||||
recreateTagElement() {
|
||||
if(this.anchorElement) {
|
||||
this.anchorElement.remove()
|
||||
this.anchorElement = null
|
||||
}
|
||||
recalculateAnchorElement() {
|
||||
this.anchorElement = this.instance.querySelector(this.constructor.ANCHOR_SELECTOR)
|
||||
}
|
||||
|
||||
this.anchorElement = document.createElement("a")
|
||||
this.anchorElement.slot = this.constructor.ANCHOR_ELEMENT_SLOT
|
||||
this.anchorElement.href = "#" // TODO: Add href behaviour to the anchor.
|
||||
resetAnchorElementProperties() {
|
||||
this.anchorElement.href = this.target
|
||||
this.anchorElement.innerText = this.text
|
||||
this.appendChild(this.anchorElement)
|
||||
}
|
||||
|
||||
onConnect() {
|
||||
super.onConnect()
|
||||
this.recreateTagElement()
|
||||
this.recalculateAnchorElement()
|
||||
this.resetAnchorElementProperties()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ export class VaultElement extends CustomElement {
|
|||
get base() {
|
||||
return this.getAttribute("base")
|
||||
}
|
||||
set base(value) {
|
||||
this.setAttribute("base", value)
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link fetch} the file at the given path ignoring cooldowns.
|
||||
|
@ -32,33 +35,59 @@ export class VaultElement extends CustomElement {
|
|||
* Cooldown between two {@link fetchCooldown} requests in milliseconds, as obtained from the `cooldown` parameter.
|
||||
*/
|
||||
get cooldownMs() {
|
||||
return Number(this.getAttribute("cooldown"))
|
||||
return Number(this.getAttribute("cooldown") ?? 5000)
|
||||
}
|
||||
set cooldownMs(value) {
|
||||
this.setAttribute("cooldown", value.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue containing the `resolve` functions necessary to make the calls to {@link fetchCooldown} proceed beyond the waiting phase.
|
||||
* To be called by the preceding {@link fetchCooldown} if possible.
|
||||
* @type {((v: unknown) => void)[]}
|
||||
* FIFO queue of {@link fetch} promises to be awaited, with a {@link cooldownMs} pause between each of them.
|
||||
* @type {((v: undefined) => void)[]}
|
||||
*/
|
||||
#fetchQueue = []
|
||||
|
||||
/**
|
||||
* Promise that can be called to resume {@link #fetchQueueScheduler} if {@link #fetchQueue} is no longer empty.
|
||||
* @type {((v: undefined) => void)|null}
|
||||
*/
|
||||
#somethingInFetchQueue
|
||||
|
||||
/**
|
||||
* @returns {Promise<void>} A Promise that will wait for this caller's turn in the {@link #fetchQueue}.
|
||||
*/
|
||||
fetchQueueTurn() {
|
||||
async fetchQueueTurn() {
|
||||
return new Promise(resolve => {
|
||||
this.#fetchQueue.push(resolve)
|
||||
console.debug("[Fetch queue] Waiting for my turn...")
|
||||
if(this.#somethingInFetchQueue !== null) {
|
||||
console.debug("[Fetch queue] Asking scheduler to resume...")
|
||||
this.#somethingInFetchQueue(undefined)
|
||||
this.#somethingInFetchQueue = null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* A promise that will advance the fetch queue after {@link cooldownMs}.
|
||||
* Resolves promises in the {@link #fetchQueue} with a cooldown.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async #scheduleNextFetchQueueTurn() {
|
||||
await sleep(this.cooldownMs)
|
||||
const resolve = this.#fetchQueue.shift()
|
||||
resolve()
|
||||
async #fetchQueueScheduler() {
|
||||
while(this.isConnected) {
|
||||
console.debug("[Fetch scheduler] Scheduler running one iteration...")
|
||||
if(this.#fetchQueue.length === 0) {
|
||||
const somethingInFetchQueue = new Promise(resolve => {
|
||||
this.#somethingInFetchQueue = resolve
|
||||
console.debug("[Fetch scheduler] Nothing to do, waiting...")
|
||||
})
|
||||
await somethingInFetchQueue
|
||||
}
|
||||
const promise = this.#fetchQueue.shift()
|
||||
console.debug("[Fetch scheduler] Advancing...")
|
||||
promise()
|
||||
console.debug("[Fetch scheduler] Cooling down for:", this.cooldownMs)
|
||||
await sleep(this.cooldownMs)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,20 +96,19 @@ export class VaultElement extends CustomElement {
|
|||
* @returns {Promise<Response>} The resulting HTTP response.
|
||||
*/
|
||||
async fetchCooldown(path) {
|
||||
// Sit waiting in queue
|
||||
if(this.#fetchQueue.length > 0) {
|
||||
await this.fetchQueueTurn()
|
||||
}
|
||||
// Await for this request's turn in the fetchQueue
|
||||
await this.fetchQueueTurn()
|
||||
// Perform the request
|
||||
const result = await this.fetchImmediately(path)
|
||||
// Start the next item in queue
|
||||
// noinspection ES6MissingAwait
|
||||
this.#scheduleNextFetchQueueTurn()
|
||||
// Return the request's result
|
||||
return result
|
||||
}
|
||||
|
||||
onConnect() {
|
||||
super.onConnect()
|
||||
|
||||
// noinspection JSIgnoredPromiseFromCall
|
||||
this.#fetchQueueScheduler()
|
||||
}
|
||||
}
|
|
@ -1,12 +1,26 @@
|
|||
import { CanvasElement, HashtagElement, NodeFileElement, WikilinkElement, DisplayElement, EdgeElement, NodeGroupElement, NodeTextElement, FrontMatterElement, MarkdownElement } from "./elements/index.mjs";
|
||||
import {
|
||||
CanvasElement,
|
||||
HashtagElement,
|
||||
NodeFileElement,
|
||||
WikilinkElement,
|
||||
DisplayElement,
|
||||
EdgeElement,
|
||||
NodeGroupElement,
|
||||
NodeTextElement,
|
||||
FrontMatterElement,
|
||||
MarkdownElement,
|
||||
VaultElement, BrowseElement
|
||||
} from "./elements/index.mjs";
|
||||
|
||||
customElements.define("x-vault", VaultElement)
|
||||
customElements.define("x-display", DisplayElement)
|
||||
customElements.define("x-canvas", CanvasElement)
|
||||
customElements.define("x-node-group", NodeGroupElement)
|
||||
customElements.define("x-node-file", NodeFileElement)
|
||||
customElements.define("x-node-text", NodeTextElement)
|
||||
customElements.define("x-node-group", NodeGroupElement)
|
||||
customElements.define("x-edge", EdgeElement)
|
||||
customElements.define("x-markdown", MarkdownElement)
|
||||
customElements.define("x-frontmatter", FrontMatterElement)
|
||||
customElements.define("x-wikilink", WikilinkElement)
|
||||
customElements.define("x-hashtag", HashtagElement)
|
||||
customElements.define("x-canvas", CanvasElement)
|
||||
customElements.define("x-display", DisplayElement)
|
||||
customElements.define("x-edge", EdgeElement)
|
||||
customElements.define("x-wikilink", WikilinkElement)
|
||||
customElements.define("x-browse", BrowseElement, {extends: "body"})
|
||||
|
|
|
@ -21,3 +21,8 @@ export class FetchError extends Error {
|
|||
this.response = response
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A file is maliciously malformed.
|
||||
*/
|
||||
export class MalformedError extends Error {}
|
Loading…
Reference in a new issue