@qwik.dev/core
Version:
An open source framework for building instant loading web apps at any scale, without the extra effort.
164 lines (163 loc) • 5.06 kB
JavaScript
const Q_RESOLVED_SELECTOR = 'template[q\\:r="';
const Q_RESOLVED_ATTR = "q:r";
const Q_RESULT_PARENT_SELECTOR = '[q\\:rp="';
const Q_GROUP_ATTR = "q:g";
const Q_INDEX_ATTR = "q:i";
const Q_ORDER_ATTR = "q:o";
const Q_CONTAINER_SELECTOR = "[q\\:container]:not([q\\:container=html]):not([q\\:container=text])";
const installOutOfOrderExecutor = (doc) => {
const groups = /* @__PURE__ */ new WeakMap();
const process = (boundaryId, content) => {
var _a;
const executorDoc = doc;
(_a = executorDoc.qProcessOOOS) == null ? void 0 : _a.call(executorDoc, boundaryId, content);
};
const getScope = () => {
const script = doc.currentScript;
return script ? script.closest(Q_CONTAINER_SELECTOR) || doc : doc;
};
const group = (scope, groupId, total, order) => {
let scopedGroups = groups.get(scope);
if (!scopedGroups) {
groups.set(scope, scopedGroups = {});
}
return scopedGroups[groupId] || (scopedGroups[groupId] = {
r: {},
n: 0,
t: total,
o: order
});
};
const getResolvedTemplate = (scope, boundaryId) => {
const currentScript = doc.currentScript;
const previousElement = currentScript ? currentScript.previousElementSibling : null;
if (previousElement && previousElement.localName === "template" && previousElement.getAttribute(Q_RESOLVED_ATTR) === String(boundaryId)) {
return previousElement;
}
const templates = scope.querySelectorAll(Q_RESOLVED_SELECTOR + boundaryId + '"]');
return templates.length ? templates[templates.length - 1] : null;
};
const getPlaceholderTemplate = (content, boundaryId) => {
return content.querySelector(Q_RESOLVED_SELECTOR + boundaryId + '"]');
};
const getResultParent = (scope, boundaryId) => {
return scope.querySelector(Q_RESULT_PARENT_SELECTOR + boundaryId + '"]');
};
const reveal = (content, fallback) => {
if (!content) {
return 0;
}
if (fallback && fallback.style) {
fallback.style.display = "none";
}
if (content.style) {
content.style.display = "contents";
}
return 1;
};
const move = (scope, boundaryId, resolved) => {
if (!resolved) {
return null;
}
const content = getResultParent(scope, boundaryId);
const placeholder = content ? getPlaceholderTemplate(content, boundaryId) : null;
const parent = placeholder ? placeholder.parentNode : null;
if (!placeholder || !content || !parent) {
return null;
}
parent.insertBefore(resolved.content, placeholder);
placeholder.remove();
resolved.remove();
return [content, content.previousElementSibling];
};
const flush = (group2) => {
const order = group2.o;
let entry;
let index;
let swapped = 0;
if (order === "p") {
for (const key in group2.r) {
entry = group2.r[key];
if (entry[0] && reveal(entry[0], entry[1])) {
entry[0] = 0;
swapped++;
}
}
} else if (order === "s") {
for (index = group2.n; (entry = group2.r[index]) && entry[0]; index++) {
if (!reveal(entry[0], entry[1])) {
break;
}
entry[0] = 0;
swapped++;
group2.n = index + 1;
}
} else if (order === "r") {
if (group2.t < 0) {
return 0;
}
if (group2.n < 0) {
group2.n = group2.t - 1;
}
for (index = group2.n; (entry = group2.r[index]) && entry[0]; index--) {
if (!reveal(entry[0], entry[1])) {
break;
}
entry[0] = 0;
swapped++;
group2.n = index - 1;
}
} else {
if (group2.t < 0) {
return 0;
}
for (index = 0; index < group2.t; index++) {
entry = group2.r[index];
if (!entry) {
return 0;
}
}
for (index = 0; index < group2.t; index++) {
entry = group2.r[index];
if (entry[0] && reveal(entry[0], entry[1])) {
entry[0] = 0;
swapped++;
}
}
}
return swapped;
};
const qO = ((boundaryId) => {
const scope = getScope();
const resolved = getResolvedTemplate(scope, boundaryId);
if (!resolved) {
return;
}
const entry = move(scope, boundaryId, resolved);
if (!entry) {
return;
}
process(boundaryId, entry[0] || null);
const groupId = resolved.getAttribute(Q_GROUP_ATTR);
if (groupId) {
const index = +(resolved.getAttribute(Q_INDEX_ATTR) || 0);
const currentGroup = group(scope, groupId, -1, resolved.getAttribute(Q_ORDER_ATTR) || "p");
currentGroup.r[index] = entry;
flush(currentGroup);
return;
}
reveal(entry[0] || null, entry[1]);
});
qO.g = (groupId, total, order) => {
const currentGroup = group(getScope(), groupId, total, order);
currentGroup.t = total;
currentGroup.o = order;
if (currentGroup.o === "r" && currentGroup.n === 0) {
currentGroup.n = total - 1;
}
flush(currentGroup);
};
qO.d = doc;
globalThis.qO = qO;
};
installOutOfOrderExecutor(document);