Stake Codigo Fonte
Stake Codigo Fonte
Stake Codigo Fonte
// Track which nodes are claimed during hydration. Unclaimed nodes can then be
removed from the DOM
// at the end of hydration without touching the remaining nodes.
let is_hydrating = false;
function start_hydrating() {
is_hydrating = true;
}
function end_hydrating() {
is_hydrating = false;
}
function upper_bound(low, high, key, value) {
// Return first index of value larger than input value in the range [low, high)
while (low < high) {
const mid = low + ((high - low) >> 1);
if (key(mid) <= value) {
low = mid + 1;
}
else {
high = mid;
}
}
return low;
}
function init_hydrate(target) {
if (target.hydrate_init)
return;
target.hydrate_init = true;
// We know that all children have claim_order values since the unclaimed have
been detached if target is not <head>
let children = target.childNodes;
// If target is <head>, there may be children without claim_order
if (target.nodeName === 'HEAD') {
const myChildren = [];
for (let i = 0; i < children.length; i++) {
const node = children[i];
if (node.claim_order !== undefined) {
myChildren.push(node);
}
}
children = myChildren;
}
/*
* Reorder claimed children optimally.
* We can reorder claimed children optimally by finding the longest subsequence
of
* nodes that are already claimed in order and only moving the rest. The longest
* subsequence subsequence of nodes that are claimed in order can be found by
* computing the longest increasing subsequence of .claim_order values.
*
* This algorithm is optimal in generating the least amount of reorder
operations
* possible.
*
* Proof:
* We know that, given a set of reordering operations, the nodes that do not
move
* always form an increasing subsequence, since they do not move among each
other
* meaning that they must be already ordered among each other. Thus, the maximal
* set of nodes that do not move form a longest increasing subsequence.
*/
// Compute longest increasing subsequence
// m: subsequence length j => index k of smallest value that ends an increasing
subsequence of length j
const m = new Int32Array(children.length + 1);
// Predecessor indices + 1
const p = new Int32Array(children.length);
m[0] = -1;
let longest = 0;
for (let i = 0; i < children.length; i++) {
const current = children[i].claim_order;
// Find the largest subsequence length such that it ends in a value less
than our current value
// upper_bound returns first greater value, so we subtract one
// with fast path for when we are on the current longest subsequence
const seqLen = ((longest > 0 && children[m[longest]].claim_order <=
current) ? longest + 1 : upper_bound(1, longest, idx =>
children[m[idx]].claim_order, current)) - 1;
p[i] = m[seqLen] + 1;
const newLen = seqLen + 1;
// We can guarantee that current is the smallest value. Otherwise, we would
have generated a longer sequence.
m[newLen] = i;
longest = Math.max(newLen, longest);
}
// The longest increasing subsequence of nodes (initially reversed)
const lis = [];
// The rest of the nodes, nodes that will be moved
const toMove = [];
let last = children.length - 1;
for (let cur = m[longest] + 1; cur != 0; cur = p[cur - 1]) {
lis.push(children[cur - 1]);
for (; last >= cur; last--) {
toMove.push(children[last]);
}
last--;
}
for (; last >= 0; last--) {
toMove.push(children[last]);
}
lis.reverse();
// We sort the nodes being moved to guarantee that their insertion order
matches the claim order
toMove.sort((a, b) => a.claim_order - b.claim_order);
// Finally, we move the nodes
for (let i = 0, j = 0; i < toMove.length; i++) {
while (j < lis.length && toMove[i].claim_order >= lis[j].claim_order) {
j++;
}
const anchor = j < lis.length ? lis[j] : null;
target.insertBefore(toMove[i], anchor);
}
}
function append(target, node) {
target.appendChild(node);
}
function append_styles(target, style_sheet_id, styles) {
const append_styles_to = get_root_for_style(target);
if (!append_styles_to.getElementById(style_sheet_id)) {
const style = element('style');
style.id = style_sheet_id;
style.textContent = styles;
append_stylesheet(append_styles_to, style);
}
}
function get_root_for_style(node) {
if (!node)
return document;
const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
if (root && root.host) {
return root;
}
return node.ownerDocument;
}
function append_empty_stylesheet(node) {
const style_element = element('style');
append_stylesheet(get_root_for_style(node), style_element);
return style_element;
}
function append_stylesheet(node, style) {
append(node.head || node, style);
}
function append_hydration(target, node) {
if (is_hydrating) {
init_hydrate(target);
if ((target.actual_end_child === undefined) || ((target.actual_end_child !
== null) && (target.actual_end_child.parentElement !== target))) {
target.actual_end_child = target.firstChild;
}
// Skip nodes of undefined ordering
while ((target.actual_end_child !== null) &&
(target.actual_end_child.claim_order === undefined)) {
target.actual_end_child = target.actual_end_child.nextSibling;
}
if (node !== target.actual_end_child) {
// We only insert if the ordering of this node should be modified or
the parent node is not target
if (node.claim_order !== undefined || node.parentNode !== target) {
target.insertBefore(node, target.actual_end_child);
}
}
else {
target.actual_end_child = node.nextSibling;
}
}
else if (node.parentNode !== target || node.nextSibling !== null) {
target.appendChild(node);
}
}
function insert(target, node, anchor) {
target.insertBefore(node, anchor || null);
}
function insert_hydration(target, node, anchor) {
if (is_hydrating && !anchor) {
append_hydration(target, node);
}
else if (node.parentNode !== target || node.nextSibling != anchor) {
target.insertBefore(node, anchor || null);
}
}
function detach(node) {
node.parentNode.removeChild(node);
}
function destroy_each(iterations, detaching) {
for (let i = 0; i < iterations.length; i += 1) {
if (iterations[i])
iterations[i].d(detaching);
}
}
function element(name) {
return document.createElement(name);
}
function element_is(name, is) {
return document.createElement(name, { is });
}
function object_without_properties(obj, exclude) {
const target = {};
for (const k in obj) {
if (has_prop(obj, k)
// @ts-ignore
&& exclude.indexOf(k) === -1) {
// @ts-ignore
target[k] = obj[k];
}
}
return target;
}
function svg_element(name) {
return document.createElementNS('http://www.w3.org/2000/svg', name);
}
function text(data) {
return document.createTextNode(data);
}
function space() {
return text(' ');
}
function empty() {
return text('');
}
function listen(node, event, handler, options) {
node.addEventListener(event, handler, options);
return () => node.removeEventListener(event, handler, options);
}
function prevent_default(fn) {
return function (event) {
event.preventDefault();
// @ts-ignore
return fn.call(this, event);
};
}
function stop_propagation(fn) {
return function (event) {
event.stopPropagation();
// @ts-ignore
return fn.call(this, event);
};
}
function self(fn) {
return function (event) {
// @ts-ignore
if (event.target === this)
fn.call(this, event);
};
}
function trusted(fn) {
return function (event) {
// @ts-ignore
if (event.isTrusted)
fn.call(this, event);
};
}
function attr(node, attribute, value) {
if (value == null)
node.removeAttribute(attribute);
else if (node.getAttribute(attribute) !== value)
node.setAttribute(attribute, value);
}
function set_attributes(node, attributes) {
// @ts-ignore
const descriptors = Object.getOwnPropertyDescriptors(node.__proto__);
for (const key in attributes) {
if (attributes[key] == null) {
node.removeAttribute(key);
}
else if (key === 'style') {
node.style.cssText = attributes[key];
}
else if (key === '__value') {
node.value = node[key] = attributes[key];
}
else if (descriptors[key] && descriptors[key].set) {
node[key] = attributes[key];
}
else {
attr(node, key, attributes[key]);
}
}
}
function set_svg_attributes(node, attributes) {
for (const key in attributes) {
attr(node, key, attributes[key]);
}
}
function set_custom_element_data(node, prop, value) {
if (prop in node) {
node[prop] = typeof node[prop] === 'boolean' && value === '' ? true :
value;
}
else {
attr(node, prop, value);
}
}
function xlink_attr(node, attribute, value) {
node.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);
}
function get_binding_group_value(group, __value, checked) {
const value = new Set();
for (let i = 0; i < group.length; i += 1) {
if (group[i].checked)
value.add(group[i].__value);
}
if (!checked) {
value.delete(__value);
}
return Array.from(value);
}
function to_number(value) {
return value === '' ? null : +value;
}
function time_ranges_to_array(ranges) {
const array = [];
for (let i = 0; i < ranges.length; i += 1) {
array.push({ start: ranges.start(i), end: ranges.end(i) });
}
return array;
}
function children(element) {
return Array.from(element.childNodes);
}
function init_claim_info(nodes) {
if (nodes.claim_info === undefined) {
nodes.claim_info = { last_index: 0, total_claimed: 0 };
}
}
function claim_node(nodes, predicate, processNode, createNode, dontUpdateLastIndex
= false) {
// Try to find nodes in an order such that we lengthen the longest increasing
subsequence
init_claim_info(nodes);
const resultNode = (() => {
// We first try to find an element after the previous one
for (let i = nodes.claim_info.last_index; i < nodes.length; i++) {
const node = nodes[i];
if (predicate(node)) {
const replacement = processNode(node);
if (replacement === undefined) {
nodes.splice(i, 1);
}
else {
nodes[i] = replacement;
}
if (!dontUpdateLastIndex) {
nodes.claim_info.last_index = i;
}
return node;
}
}
// Otherwise, we try to find one before
// We iterate in reverse so that we don't go too far back
for (let i = nodes.claim_info.last_index - 1; i >= 0; i--) {
const node = nodes[i];
if (predicate(node)) {
const replacement = processNode(node);
if (replacement === undefined) {
nodes.splice(i, 1);
}
else {
nodes[i] = replacement;
}
if (!dontUpdateLastIndex) {
nodes.claim_info.last_index = i;
}
else if (replacement === undefined) {
// Since we spliced before the last_index, we decrease it
nodes.claim_info.last_index--;
}
return node;
}
}
// If we can't find any matching node, we create a new one
return createNode();
})();
resultNode.claim_order = nodes.claim_info.total_claimed;
nodes.claim_info.total_claimed += 1;
return resultNode;
}
function claim_element_base(nodes, name, attributes, create_element) {
return claim_node(nodes, (node) => node.nodeName === name, (node) => {
const remove = [];
for (let j = 0; j < node.attributes.length; j++) {
const attribute = node.attributes[j];
if (!attributes[attribute.name]) {
remove.push(attribute.name);
}
}
remove.forEach(v => node.removeAttribute(v));
return undefined;
}, () => create_element(name));
}
function claim_element(nodes, name, attributes) {
return claim_element_base(nodes, name, attributes, element);
}
function claim_svg_element(nodes, name, attributes) {
return claim_element_base(nodes, name, attributes, svg_element);
}
function claim_text(nodes, data) {
return claim_node(nodes, (node) => node.nodeType === 3, (node) => {
const dataStr = '' + data;
if (node.data.startsWith(dataStr)) {
if (node.data.length !== dataStr.length) {
return node.splitText(dataStr.length);
}
}
else {
node.data = dataStr;
}
}, () => text(data), true // Text nodes should not update last index since it
is likely not worth it to eliminate an increasing subsequence of actual elements
);
}
function claim_space(nodes) {
return claim_text(nodes, ' ');
}
function find_comment(nodes, text, start) {
for (let i = start; i < nodes.length; i += 1) {
const node = nodes[i];
if (node.nodeType === 8 /* comment node */ && node.textContent.trim() ===
text) {
return i;
}
}
return nodes.length;
}
function claim_html_tag(nodes) {
// find html opening tag
const start_index = find_comment(nodes, 'HTML_TAG_START', 0);
const end_index = find_comment(nodes, 'HTML_TAG_END', start_index);
if (start_index === end_index) {
return new HtmlTagHydration();
}
init_claim_info(nodes);
const html_tag_nodes = nodes.splice(start_index, end_index + 1);
detach(html_tag_nodes[0]);
detach(html_tag_nodes[html_tag_nodes.length - 1]);
const claimed_nodes = html_tag_nodes.slice(1, html_tag_nodes.length - 1);
for (const n of claimed_nodes) {
n.claim_order = nodes.claim_info.total_claimed;
nodes.claim_info.total_claimed += 1;
}
return new HtmlTagHydration(claimed_nodes);
}
function set_data(text, data) {
data = '' + data;
if (text.wholeText !== data)
text.data = data;
}
function set_input_value(input, value) {
input.value = value == null ? '' : value;
}
function set_input_type(input, type) {
try {
input.type = type;
}
catch (e) {
// do nothing
}
}
function set_style(node, key, value, important) {
node.style.setProperty(key, value, important ? 'important' : '');
}
function select_option(select, value) {
for (let i = 0; i < select.options.length; i += 1) {
const option = select.options[i];
if (option.__value === value) {
option.selected = true;
return;
}
}
select.selectedIndex = -1; // no option should be selected
}
function select_options(select, value) {
for (let i = 0; i < select.options.length; i += 1) {
const option = select.options[i];
option.selected = ~value.indexOf(option.__value);
}
}
function select_value(select) {
const selected_option = select.querySelector(':checked') || select.options[0];
return selected_option && selected_option.__value;
}
function select_multiple_value(select) {
return [].map.call(select.querySelectorAll(':checked'), option =>
option.__value);
}
// unfortunately this can't be a constant as that wouldn't be tree-shakeable
// so we cache the result instead
let crossorigin;
function is_crossorigin() {
if (crossorigin === undefined) {
crossorigin = false;
try {
if (typeof window !== 'undefined' && window.parent) {
void window.parent.document;
}
}
catch (error) {
crossorigin = true;
}
}
return crossorigin;
}
function add_resize_listener(node, fn) {
const computed_style = getComputedStyle(node);
if (computed_style.position === 'static') {
node.style.position = 'relative';
}
const iframe = element('iframe');
iframe.setAttribute('style', 'display: block; position: absolute; top: 0; left:
0; width: 100%; height: 100%; ' +
'overflow: hidden; border: 0; opacity: 0; pointer-events: none; z-index: -
1;');
iframe.setAttribute('aria-hidden', 'true');
iframe.tabIndex = -1;
const crossorigin = is_crossorigin();
let unsubscribe;
if (crossorigin) {
iframe.src = "data:text/html,<script>onresize=function()
{parent.postMessage(0,'*')}</script>";
unsubscribe = listen(window, 'message', (event) => {
if (event.source === iframe.contentWindow)
fn();
});
}
else {
iframe.src = 'about:blank';
iframe.onload = () => {
unsubscribe = listen(iframe.contentWindow, 'resize', fn);
};
}
append(node, iframe);
return () => {
if (crossorigin) {
unsubscribe();
}
else if (unsubscribe && iframe.contentWindow) {
unsubscribe();
}
detach(iframe);
};
}
function toggle_class(element, name, toggle) {
element.classList[toggle ? 'add' : 'remove'](name);
}
function custom_event(type, detail, bubbles = false) {
const e = document.createEvent('CustomEvent');
e.initCustomEvent(type, bubbles, false, detail);
return e;
}
function query_selector_all(selector, parent = document.body) {
return Array.from(parent.querySelectorAll(selector));
}
class HtmlTag {
constructor() {
this.e = this.n = null;
}
c(html) {
this.h(html);
}
m(html, target, anchor = null) {
if (!this.e) {
this.e = element(target.nodeName);
this.t = target;
this.c(html);
}
this.i(anchor);
}
h(html) {
this.e.innerHTML = html;
this.n = Array.from(this.e.childNodes);
}
i(anchor) {
for (let i = 0; i < this.n.length; i += 1) {
insert(this.t, this.n[i], anchor);
}
}
p(html) {
this.d();
this.h(html);
this.i(this.a);
}
d() {
this.n.forEach(detach);
}
}
class HtmlTagHydration extends HtmlTag {
constructor(claimed_nodes) {
super();
this.e = this.n = null;
this.l = claimed_nodes;
}
c(html) {
if (this.l) {
this.n = this.l;
}
else {
super.c(html);
}
}
i(anchor) {
for (let i = 0; i < this.n.length; i += 1) {
insert_hydration(this.t, this.n[i], anchor);
}
}
}
function attribute_to_object(attributes) {
const result = {};
for (const attribute of attributes) {
result[attribute.name] = attribute.value;
}
return result;
}
function get_custom_elements_slots(element) {
const result = {};
element.childNodes.forEach((node) => {
result[node.slot || 'default'] = true;
});
return result;
}
let current_component;
function set_current_component(component) {
current_component = component;
}
function get_current_component() {
if (!current_component)
throw new Error('Function called outside component initialization');
return current_component;
}
function beforeUpdate(fn) {
get_current_component().$$.before_update.push(fn);
}
function onMount(fn) {
get_current_component().$$.on_mount.push(fn);
}
function afterUpdate(fn) {
get_current_component().$$.after_update.push(fn);
}
function onDestroy(fn) {
get_current_component().$$.on_destroy.push(fn);
}
function createEventDispatcher() {
const component = get_current_component();
return (type, detail) => {
const callbacks = component.$$.callbacks[type];
if (callbacks) {
// TODO are there situations where events could be dispatched
// in a server (non-DOM) environment?
const event = custom_event(type, detail);
callbacks.slice().forEach(fn => {
fn.call(component, event);
});
}
};
}
function setContext(key, context) {
get_current_component().$$.context.set(key, context);
}
function getContext(key) {
return get_current_component().$$.context.get(key);
}
function getAllContexts() {
return get_current_component().$$.context;
}
function hasContext(key) {
return get_current_component().$$.context.has(key);
}
// TODO figure out if we still want to support
// shorthand events, or if we want to implement
// a real bubbling mechanism
function bubble(component, event) {
const callbacks = component.$$.callbacks[event.type];
if (callbacks) {
// @ts-ignore
callbacks.slice().forEach(fn => fn.call(this, event));
}
}
let promise;
function wait() {
if (!promise) {
promise = Promise.resolve();
promise.then(() => {
promise = null;
});
}
return promise;
}
function dispatch(node, direction, kind) {
node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`));
}
const outroing = new Set();
let outros;
function group_outros() {
outros = {
r: 0,
c: [],
p: outros // parent group
};
}
function check_outros() {
if (!outros.r) {
run_all(outros.c);
}
outros = outros.p;
}
function transition_in(block, local) {
if (block && block.i) {
outroing.delete(block);
block.i(local);
}
}
function transition_out(block, local, detach, callback) {
if (block && block.o) {
if (outroing.has(block))
return;
outroing.add(block);
outros.c.push(() => {
outroing.delete(block);
if (callback) {
if (detach)
block.d(1);
callback();
}
});
block.o(local);
}
}
const null_transition = { duration: 0 };
function create_in_transition(node, fn, params) {
let config = fn(node, params);
let running = false;
let animation_name;
let task;
let uid = 0;
function cleanup() {
if (animation_name)
delete_rule(node, animation_name);
}
function go() {
const { delay = 0, duration = 300, easing = identity, tick = noop, css } =
config || null_transition;
if (css)
animation_name = create_rule(node, 0, 1, duration, delay, easing, css,
uid++);
tick(0, 1);
const start_time = now() + delay;
const end_time = start_time + duration;
if (task)
task.abort();
running = true;
add_render_callback(() => dispatch(node, true, 'start'));
task = loop(now => {
if (running) {
if (now >= end_time) {
tick(1, 0);
dispatch(node, true, 'end');
cleanup();
return running = false;
}
if (now >= start_time) {
const t = easing((now - start_time) / duration);
tick(t, 1 - t);
}
}
return running;
});
}
let started = false;
return {
start() {
if (started)
return;
started = true;
delete_rule(node);
if (is_function(config)) {
config = config();
wait().then(go);
}
else {
go();
}
},
invalidate() {
started = false;
},
end() {
if (running) {
cleanup();
running = false;
}
}
};
}
function create_out_transition(node, fn, params) {
let config = fn(node, params);
let running = true;
let animation_name;
const group = outros;
group.r += 1;
function go() {
const { delay = 0, duration = 300, easing = identity, tick = noop, css } =
config || null_transition;
if (css)
animation_name = create_rule(node, 1, 0, duration, delay, easing, css);
const start_time = now() + delay;
const end_time = start_time + duration;
add_render_callback(() => dispatch(node, false, 'start'));
loop(now => {
if (running) {
if (now >= end_time) {
tick(0, 1);
dispatch(node, false, 'end');
if (!--group.r) {
// this will result in `end()` being called,
// so we don't need to clean up here
run_all(group.c);
}
return false;
}
if (now >= start_time) {
const t = easing((now - start_time) / duration);
tick(1 - t, t);
}
}
return running;
});
}
if (is_function(config)) {
wait().then(() => {
// @ts-ignore
config = config();
go();
});
}
else {
go();
}
return {
end(reset) {
if (reset && config.tick) {
config.tick(1, 0);
}
if (running) {
if (animation_name)
delete_rule(node, animation_name);
running = false;
}
}
};
}
function create_bidirectional_transition(node, fn, params, intro) {
let config = fn(node, params);
let t = intro ? 0 : 1;
let running_program = null;
let pending_program = null;
let animation_name = null;
function clear_animation() {
if (animation_name)
delete_rule(node, animation_name);
}
function init(program, duration) {
const d = (program.b - t);
duration *= Math.abs(d);
return {
a: t,
b: program.b,
d,
duration,
start: program.start,
end: program.start + duration,
group: program.group
};
}
function go(b) {
const { delay = 0, duration = 300, easing = identity, tick = noop, css } =
config || null_transition;
const program = {
start: now() + delay,
b
};
if (!b) {
// @ts-ignore todo: improve typings
program.group = outros;
outros.r += 1;
}
if (running_program || pending_program) {
pending_program = program;
}
else {
// if this is an intro, and there's a delay, we need to do
// an initial tick and/or apply CSS animation immediately
if (css) {
clear_animation();
animation_name = create_rule(node, t, b, duration, delay, easing,
css);
}
if (b)
tick(0, 1);
running_program = init(program, duration);
add_render_callback(() => dispatch(node, b, 'start'));
loop(now => {
if (pending_program && now > pending_program.start) {
running_program = init(pending_program, duration);
pending_program = null;
dispatch(node, running_program.b, 'start');
if (css) {
clear_animation();
animation_name = create_rule(node, t, running_program.b,
running_program.duration, 0, easing, config.css);
}
}
if (running_program) {
if (now >= running_program.end) {
tick(t = running_program.b, 1 - t);
dispatch(node, running_program.b, 'end');
if (!pending_program) {
// we're done
if (running_program.b) {
// intro — we can tidy up immediately
clear_animation();
}
else {
// outro — needs to be coordinated
if (!--running_program.group.r)
run_all(running_program.group.c);
}
}
running_program = null;
}
else if (now >= running_program.start) {
const p = now - running_program.start;
t = running_program.a + running_program.d * easing(p /
running_program.duration);
tick(t, 1 - t);
}
}
return !!(running_program || pending_program);
});
}
}
return {
run(b) {
if (is_function(config)) {
wait().then(() => {
// @ts-ignore
config = config();
go(b);
});
}
else {
go(b);
}
},
end() {
clear_animation();
running_program = pending_program = null;
}
};
}
// source: https://html.spec.whatwg.org/multipage/indices.html
const boolean_attributes = new Set([
'allowfullscreen',
'allowpaymentrequest',
'async',
'autofocus',
'autoplay',
'checked',
'controls',
'default',
'defer',
'disabled',
'formnovalidate',
'hidden',
'ismap',
'loop',
'multiple',
'muted',
'nomodule',
'novalidate',
'open',
'playsinline',
'readonly',
'required',
'reversed',
'selected'
]);
================================================================
bitsler
importScripts("/precache-manifest.546227a5957352bb220f1278363a196c.js", "/workbox-
v4.3.1/workbox-sw.js");
workbox.setConfig({modulePathPrefix: "/workbox-v4.3.1"});
// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js')
importScripts('https://www.gstatic.com/firebasejs/8.0.0/firebase-messaging.js')
importScripts('./firebase-config.js')
// Initialize Firebase
firebase.initializeApp(firebaseConfig)
// This code listens for the user's confirmation to update the app.
self.addEventListener('message', (e) => {
if (!e.data) {
return
}
switch (e.data) {
case 'skipWaiting':
self.skipWaiting()
break
default:
// NOOP
break
}
})
workbox.core.clientsClaim()
// load from cache first if available for all files inside /static folder
workbox.routing.registerRoute(
new RegExp('/static/.*'),
new workbox.strategies.CacheFirst()
)